【问题标题】:protobuf.net via multi-threadingprotobuf.net 通过多线程
【发布时间】:2013-10-14 09:22:15
【问题描述】:

我想使用 protobuf.net 反序列化大量数据,但我发现它无法通过多线程提高吞吐量。

我的测试场景:

  1. 单线程,CPU负载为25%(1/4 cpu资源)
  2. 单线程,4 个进程,cpu 负载为 9x %(4/4 cpu 资源)
  3. 4线程,1进程,cpu负载为30%~60%

也就是说,protobuf 在多线程下无法充分利用 cpu 资源。

这是我的代码

    private static void DeSerialize()
    {
        while (true)
        { 
            Dictionary<string, byte[]>  cache ;
            if (queue.TryDequeue(out cache))
            {
                foreach (byte[] unit in cache.Values)
                {
                    using (MemoryStream stream = new MemoryStream(unit))
                    {
                        CommonUtil.DeSerializeBuf<User>(stream);
                    }
                }
            }
            else break;
        }
    }

    private static void DeSerializeThread()
    {
        for (int i = 0; i < 4; i++)
        {
            Thread a = new Thread(DeSerialize);
            a.Start();
        }
    }

protobuf.net 如何通过多线程充分利用多个 CPU 资源?在我的情况下,多进程是不可接受的。

我的并行测试代码:

        var dic = new Dictionary<string, byte[]>();
        for (int i = 0; i < 10000000; i++)
        {
            MemoryStream stream = new MemoryStream();
            ProtoBuf.Serializer.Serialize<string>(stream, "some value which is awesome" + i);
            byte[] buffer = stream.ToArray();
            dic.Add("key" + i, buffer);
        }

        var watch = new Stopwatch();
        watch.Restart();
        Console.Write("start parallel..");

        var result = dic.AsParallel().Select(p => ProtoBuf.Serializer.Deserialize<string>(new MemoryStream(p.Value))).ToList();
        var p1 = watch.ElapsedMilliseconds;
        Console.WriteLine("end parallel " + p1);

        watch.Restart();
        Console.Write("start sequential..");

        var result2 = dic.Select(p => CommonUtil.DeSerializeBuf<string>(new MemoryStream(p.Value))).ToList();
        var p2 = watch.ElapsedMilliseconds;
        Console.WriteLine("end parallel " + p2);

谢谢。

【问题讨论】:

  • 您是否尝试使用 Parallel 或更改您的异步代码?
  • 我将不得不查看 PC 上的具体示例,但是:protobuf-net 被设计为完全并发/线程安全而没有阻塞问题。顺便说一句:你有多少个内核?
  • 我的电脑有 4 个内核。我尝试了除 protobuf 之外的其他 cpu-busy 操作。例如,循环创建对象,在“4 个线程,1 个进程”的情况下,我可以获得超过 80% 的 cpu 负载。这就是为什么我想知道问题可能存在于 protobuf 实现中。
  • protobuffer 实际上没有问题,请尝试我在下面的回复中发布的示例,并在您的代码中使用并行方法,您会发现它将使用您的处理器几乎 90%跨度>

标签: c# multithreading protocol-buffers


【解决方案1】:

我可以给你一个简短的例子来说明如何使用 Linq 作为并行,也许这会有所帮助

var dic = new Dictionary<string, byte[]>();
for (int i = 0; i < 1000000; i++)
{
    dic.Add("key" + i, Serialize<string>("some value which is awesome" + i));
}

var watch = new Stopwatch();
watch.Restart();
Console.WriteLine("start parallel");

var result = dic.AsParallel().Select(p => Deserialize<string>(p.Value)).ToList();
var p1 = watch.ElapsedMilliseconds;

watch.Restart();
Console.WriteLine("start sequential");

var result2 = dic.Select(p => Deserialize<string>(p.Value)).ToList();
var p2 = watch.ElapsedMilliseconds;

在我的机器上并行执行的速度大约快 3 倍。而且处理器利用率不同的

【讨论】:

  • 我试过了,但我得到了不同的结果:不超过两倍 -------------- 开始并行..结束并行 7225 开始顺序..结束并行 12310 --------------
  • 因为你会得到不同的结果,这也取决于你的电脑,在目标平台上 x86 有时比 x64 快,如果你在调试或发布模式下运行测试......你也可以tweek AsParallel 和 enfore 并行,设置线程数等...所以我建议您尝试一下...如果您还有其他问题,请写一个新问题...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 2014-03-02
  • 2017-09-28
  • 1970-01-01
  • 2011-12-06
  • 2021-11-03
相关资源
最近更新 更多