【问题标题】:Exception thrown: 'System.OutOfMemoryException' in ZeroMQ.dll抛出异常:ZeroMQ.dll 中的“System.OutOfMemoryException”
【发布时间】:2017-12-30 20:10:29
【问题描述】:

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

代码抛出以下错误:

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

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

但是,当我检查操作系统中的内存消耗时,它显示 8GB 中的 7.1GB。但是 801MB 仍然没有使用,这让我想知道 System.OutOfMemoryException 异常。

请看下面的截图:

计算机配备千兆以太网卡。卡片使用情况见下文:

请看下面的代码:

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,但是,上面的代码 sn -p 是示例代码,在此代码中,我将 FPS 从 15 更改为 10。一段时间后仍然会弹出错误。 最初,内存消耗较少,但随着时间的推移,它会不断增加。

我的问题如下:

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

【问题讨论】:

标签: c# zeromq


【解决方案1】:

Ad 2 ) 为什么会出现异常...虽然 801MB 内存仍然可用?

最好不要依赖静态数字。每个 JUMBO 消息(如上所示)必须存储在几个地方,其中一些在 ZeroMQ 控制域之外(通常是 O/S 和驱动程序缓冲区)。当然,ZeroMQ 在可能的情况下在零拷贝方面做得很好,但是将数据注入网络通常是一项 O/S 工作,因此任何可用空间在猛犸象大小的数据块上“蒸发”得非常快(我是比如说,ZeroMQ 要么提供整个数据块,无论大小如何,还是什么都不提供?)。

接下来,有 Context-类实例设置(High Water Marks 和其他)明确警告不要依赖XYZ [B] 免费且可用于消息数据(如果已设置) XYZ [B] 的非常值——由于任何内部缓冲区管理技巧,API 文档和 cmets 促进期望低于 2/3 的任何内容,如果不是该设置的 1/2,则实际上可用于任何消息相关数据(更不用说,如果碰巧有多个.connect()-ed 交易对手,那么缓冲区空间“消耗”会发生什么

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

Ad 1 ) ... 是否可以... 只保留一条消息 ( last )?

这个有一个干净的解决方案。它不仅适用于快速视频流,而且一般来说,对于任何过程监控、非刚性传感器网络甚至音频流来说都很酷,因为目标处理不需要“听到”数据的每个片段-flow,但希望继续关注 TimeDOMAIN 演变的“前沿”(获取最新数据,而不是为没有收到以前的“旧”读数而悲伤):

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


广告 3)

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

最后但同样重要的是,如果延迟抖动对 QoS 至关重要,我也会尽我所能控制 .setsockopt( ZMQ_TOS, <_TOS#_> ) 以实现 TypeOfService 端到端控制。

【讨论】:

  • 非常感谢。我喜欢ZMQ_AFFINITY 的想法。虽然我是 ZeroMQ 的新手,但我很快就会尝试一下。再次感谢。
猜你喜欢
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多