ZMQ message buffer exhaustion during high-frequency data updates
0 reputation · 05 May 2020, 17:55 UTC
0 reputation · 05 May 2020, 17:55 UTC
Spyder utilizes a client-server architecture where the GUI communicates with a remote Python kernel via ZeroMQ (ZMQ) messaging sockets. During long-running sessions involving high-frequency data updates to the console or complex plotting, the message buffer can experience exhaustion.
There is an uncertainty regarding how Spyder handles large de-serialized objects across these sockets and the resulting memory spikes in the client process. While a kernel restart is documented, it may fail to clear background processes if the kernel is hung, potentially leading to orphaned instances that consume system resources.
How does Spyder manage internal ZMQ buffer limits when the data production rate exceeds the UI rendering capacity? Is there a specific configuration to throttle metadata polling in the Variable Explorer to prevent UI lag during heavy computational tasks?
34775 reputation · 06 May 2020, 02:40 UTC
Spyder’s kernel‑frontend communication is built on ZeroMQ sockets. The kernel (Python) sends messages to the GUI via a REQ/REP pair and a PUSH/PULL stream for data. Each socket has a High Water Mark (HWM) that caps the number of queued messages. The default HWM for Spyder’s sockets is 1000 messages.
When the HWM is reached:
PUSH and REQ sockets block the sender until space frees up.PUB sockets drop messages (not applicable to Spyder’s kernel communication).Because the GUI thread processes all incoming messages, a burst of high‑frequency data can saturate the event loop. The kernel may block on send(), while the GUI accumulates a backlog of large objects. Deserialization (pickle, numpy, pandas) happens on the GUI thread, which can spike memory and freeze the UI even if the ZMQ buffer itself is within limits.
Typical symptoms:
These symptoms usually stem from the combination of:
The Variable Explorer refreshes automatically by polling the kernel for introspection data. The polling interval is configurable: Tools → Preferences → Variable Explorer → Refresh rate (ms). The default is 200 ms, which can be aggressive when many large objects are present.
Reducing the refresh rate (e.g., to 1000 ms) or disabling automatic refresh during heavy computation can dramatically cut the number of introspection requests, thereby reducing the load on the kernel and the GUI.
zmq.py introspection if available.
import zmq
ctx = zmq.Context()
sock = ctx.socket(zmq.REQ)
print('Send HWM:', sock.getsockopt(zmq.SNDHWM))
print('Recv HWM:', sock.getsockopt(zmq.RCVHWM))
SNDHWM and RCVHWM in the kernel’s socket creation code, but be aware that larger buffers increase RAM usage and latency.Tools → Preferences → Variable Explorer.Refresh rate (ms) from 200 to 1000.Refresh automatically and uncheck it while running heavy tasks.numpy or pandas operations on the kernel side and send only the result needed for plotting.psutil or system monitors to confirm whether spikes are due to ZMQ buffers or deserialization. A typical pattern is a rapid increase in rss followed by a plateau when the GUI thread finishes deserialization.If the kernel becomes unresponsive, a restart is usually sufficient. However, if background processes (e.g., long‑running threads) continue after a restart, you may need to kill the kernel process manually from the operating system or use Spyder’s Kernel → Restart command with the Force restart option.
Do you see any ZMQ warnings such as zmq::resource_limit or messages indicating that the HWM has been reached? This detail will help decide whether increasing the HWM is appropriate or if the issue is purely deserialization‑driven.
Use comments to ask for clarification. Post a solution as an answer.
6,570 reputation · 06 May 2020, 04:06 UTC
Spyder’s kernel uses ZeroMQ REQ/REP sockets with a default ZMQ_RCVHWM of 10 000 messages. When the kernel produces data faster than the GUI consumes it, the socket queue fills and the client’s memory spikes during deserialization.
zmq.SNDHWM and zmq.RCVHWM in the kernel’s zmq_context.py before launching the session.These changes keep the message queue bounded, preventing OOM crashes while still allowing interactive debugging.