抛出异常:ZeroMQ.dll中的“System.OutOfMemoryException”

问题描述 投票:2回答:1

我试图在Windows 10 64位操作系统中使用ZeroMQ传输大量字节(大小:12兆字节)。传输速率约为每秒15帧。

代码抛出以下错误:

Exception thrown: 'System.OutOfMemoryException' in ZeroMQ.dll

在使用Visual Studio进行调试期间,它显示4GB进程内存,如下面的屏幕截图所示:

enter image description here

但是,当我检查OS中的内存消耗时,它显示了8GB的7.1GB。但801MB仍未使用,这让我对System.OutOfMemoryException异常感到疑惑。

见下面的截图:

enter image description here

电脑配有千兆以太网卡。请参阅以下卡片使用情况:

enter image description here

请看下面的代码:

ZContext zmqContext;
ZSocket publisher;
Stopwatch watch;
readonly byte[] longByteArray = new byte[12000000];

Program()
{
    zmqContext = new ZContext();
    publisher = new ZSocket(zmqContext, ZSocketType.PUB);
    publisher.Bind("tcp://*:11111");

    var timer = new Timer();
    timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    timer.Interval = 1000.0 / 15;//15 FPS
    timer.Enabled = true;
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    var frame = new ZFrame(longByteArray);
    publisher.Send(frame);
    frame.Dispose();
}

以下是我的观察:

  1. 但是,虽然无法在实际代码中更改FPS,但上面的代码片段是示例代码,在此代码中,我将FPS从15更改为10.错误仍会在一段时间后弹出。最初,内存消耗较少,但随着时间的推移它会不断增加。

我的问题如下:

  1. 根据我上面的观察,似乎ZeroMQ发布者将消息保留在队列中,这会占用大量内存。我想知道是否有可能将ZeroMQ配置为仅保留队列中的一条消息(最后一条消息),以便ZeroMQ可以丢弃其他消息,从而减少内存消耗。
  2. 为什么抛出异常,即使801MB内存仍然可用?
  3. 还有其他解决方法可以使代码工作吗?
c# zeromq
1个回答
1
投票

广告2)为什么例外......虽然801MB内存仍然可用?

最好不要依赖静态数字。每个JUMBO消息(如上所述)必须存储在几个地方,其中一些位于ZeroMQ控制域之外(通常是O / S和驱动程序缓冲区)。当然,ZeroMQ在可能的情况下在零拷贝方面做得很好,但是将数据注入网络通常是一个O / S工作,因此任何自由空间在Mammoth大小的数据块上都“快速消失”(我是比方说,ZeroMQ既可以提供整体,也可以提供任何大小的数据块,或者什么都不提供?)。

接下来,有Context类实例设置(高水位标记和其他)明确警告不依赖于XYZ [B]免费和可用于消息数据如果设置了非常值的XYZ [B] - 由于任何内部缓冲管理技巧,API文档和注释促进预期2/3以下的任何内容,如果不是该设置的1/2,实际上可用于任何与消息相关的数据(不提及,如果存在缓冲空间“消耗”会发生什么)碰巧不只是一个单一的.connect()-ed交易对手

( 1-sends : {2,3,4,...}-receive )

广告1)...是否可以...只保留一条消息(最后一条)?

这个有一个干净的解决方案。它通常不仅适用于快速视频流,而且通常适用于任何过程监控,非刚性传感器网络甚至音频流,其中目标处理不需要“听到”数据的每个片段-flow,但会欣赏继续冲浪TimeDOMAIN演变的“前波”(获得相当最新的数据,而不是因为没有收到之前的“旧”读数而哀悼):

使用.setsockopt( ZMQ_CONFLATE, 1 );方法,你就完成了!


广告3)

如果确实需要获得最佳性能(并且如果端到端延迟允许),请尝试数据压缩步骤的效果(移动“较少”字节,在增加的本地/远程处理工作负载的折衷下)并且可以尝试移动一组“独立”处理/传输的“拆分”数据块,其中多个Context( <_nIOthreads_> )实例IO线程可以在多个Socket实例上提供几乎并行的较小块传输(IO线程可以进行负载平衡本地/偏远地区, 再次通过使用.setsockopt( ZMQ_AFFINITY, <_IOthreadORD#_> )方法

最后,但并非最不重要的是,如果延迟抖动对QoS变得至关重要,我也会尽力控制Qazxswpoi进行TypeOfService端到端控制。

© www.soinside.com 2019 - 2024. All rights reserved.