Snmp4j and virtual threads

Hi there,

we’d like to use snmp4j to scale to 1000s (potentially 10000s) parallel SNMP sessions. Each sessions fetches a rather large number of (mainly repeater) OIDs - e.g. MIB-2 ifTable.
We’re already on JDK21, so virtual threads are available. We use them in our application to schedule SNMP polls and process results.
When it comes to snmp4j, I’m aware of two areas where threading is involved for our use case:

  • TransportMapping (we use DefaultUdpTransportMapping)
  • Timers (for retransmission / timeout handling in sessions)

Current assumption is, that also using virtual threads for transport mappings and timers further enhances scaling capabilities.
A quick test with Thread factories using virtual threads instead of platform threads (using SNMP4JSettings.setThreadFactory and SNMP4JSettings.setTimerFactory) led to some locking issues. On first sight it seems like all platform threads acting as carrier threads (Fork-Join pool) are exhausted due to blocking I/O operations in synchronized blocks.
Does this seem like a reasonable explanation for SNMPSession.get() / SNMPSession.walk() not returning in finite time?
Are there any plans to make snmp4j “virtual thread ready” by using ReentrantLock or the like instead of synchronized locking?

thanks and best regards,
Stefan

Hi Stefan,
Why would you like to use 1000 or more ports (-> Snmp sessions) on a system?
Why not using a single Snmp session for that?

The next major version will use new locking mechanisms where possible.

Nevertheless I do not think that virtual threads will improve throughput by themselves.
Best regards,
Frank

Hi Frank,

thanks for your prompt response.

Very good and valid question :wink: To be honest I took it for granted that a snmp4j session maps to a single target, since a few wrapper classes in our app made that assumption. Should have questioned that to start with.

That’s good news, thanks. And I totally agree that virtual threads aren’t a silver bullet. They’re just good in waiting for blocking things to happen.
Since I’m a network guy I like the QoS analogy: QoS doesn’t create bandwidth, it’s just managed unfairness :slight_smile:
Will happily go ahead and refactor some wrapper classes …

Thanks for your help!
cheers,
Stefan

Hi Stefano,

Are you willing to share anything about your ability to leverage virtual threads to collect data from 1000s or 10000s of targets using SNMP4J? We are jus beginning to think about attempting to leverage virtual threads in an existing snmp-based management tool and would love to hear about your experience. Were you successful in being able to scale to concurrent collection from 1000s of targets?

Best regards,
Michael

Hi Michael,

sorry for the late response. Seems I missed the notification mail when we switched providers :wink:
Concerning scaling of SNMP polling using snmp4j using virtual threads:
Internal lab testing looks quite promising with a few hundred simulated devices (using snmpsim-lextudio).

What means promising? Low resource usage (CPU), no thread contention, low total poll times.

Current setup:

  • a single snmp4j UDP socket (DefaultUdpTransportMapping) served by DefaultThreadFactory
  • snmp4j timers served by DefaultTimerFactory
  • one virtual thread per polled devices to do actual polling. Processing of result is injected using Consumer (typically put in a BlockingQueue processed by another thread)
  • one virtual thread per polled devices to schedule next poll
  • jdk 25 (avoid carrier thread pinning in sync blocks which was a potential issue in jdk < 24)

In the real world we’re currently facing timing issues at a pilot customers site. We’re in the middle of debugging, so at the moment I cannot really judge if the root cause is in our implementation or the specific environment (massive IP fragmentation, huge poll results, …)
Can keep you updated if you’re interested.

cheers,
Stefan

Hello Stefano,

Thank you very much for the reply.

This is really helpful and promising, as you said.

I would love to hear what your troubleshooting reveals and if you are able to resolve any issues with your implementation.

I wasn’t aware of the thread pinning issues prior to idk 25 so that was really helpful to know.

It will likely be late in 2026 or early 2027 before we can upgrade our application to idk 25 but I am hoping to find some time to experiment before then.

Best regards,
Michael

Hey Michael,

to follow up on this one with some field experience gathered:

So far, our polling daemon scales really well (currently 1000+ polled agents) utilizing:
* (home grown) pipeline architecture for flexible and type-safe wiring of processing steps
* virtual threads for scheduling poll tasks and polling individual SNMP agents

The biggest struggle we faced were (receive) UDP socket drops with the default implementation of org.snmp4j.MessageDispatcher (single threaded). A lot of processing was done in the context of the thread serving the UDP socket, which led to quite a lot of drops since the thread couldn’t keep up with the load. We implemented a multithreaded variant of MessageDispatcher (using the decorator pattern in org.snmp4j.util.MultiThreadedMessageDispatcher) and also use very short lived virtual threads for message dispatching now. We didn’t observe any socket drops since then. Key metrics (e.g. socket stats, snmp4j stats) are monitored using opentelemetry metric instruments which was quite helpful during troubleshooting.

cheers,
Stefan