I am new to SNMP++ lib and just got the snmpWalk example up and running and have been doing some testing and am experiencing what I would believe is a performance issue that I can not figure out. I am testing using my Win11 laptop and simply running the snmpWalk example, with version = v2 and BULK_MAX set to 10, against a Linux laptop. I then run a Walk of the same device with same settings (v2 and BULK_MAX =10) on the same laptop using the Java based iReasoning MibBrowser product. I captured both walks with Wireshark and confirmed that both Walks are effectively doing the exact same thing. The problem is that SNMP++ snmpWalk consistently takes ~31sec to complete while MibBrowser only takes ~5sec. Can anyone maybe shed some light on why I would be seeing this? I don’t see anything in the code, such as a sleep statement somewhere, that would account for this. The wireshark captures show that the time between when a response is received and the next request is sent out is significantly longer in SNMP++ than the MibBrowser, almost like there is a sleep statement in the code somewhere. I even disabled all logging thinking that maybe the logging of all received responses to the console might be the issue but that didn’t make any difference. Thanks in advance for any advice or insight anyone can provide.
Could be, I couldn’t find much info on how to build it and any in on any build options. I did rebuild it with _NO_LOGGING defined as detailed in the config_snmp_pp.h but that made no difference. Are you aware of any setting I should look for? Looks like anything that might have impact on performance is already defined/set in config_snmp_pp.h.
Sorry, I mixed something up. The settings about the event handling are in AGENT++ only and should be set automatically correct if the build environment is WIN32. For SNMP++ there are no special settings for this. Thus, it should work out of the box.
So, I am afraid that you will have to figure it out yourself using a profiling/debugging.
Can you tell us the times snmpWalk needs to process the response and to send out the next request? How many requests and objects are printed at the end?
Did you build snmp++ and snmpWalk in release mode?
I did rebuild the lib and app in release mode and disable all logging so no packets are being printed to the console. All data below is taken from wireshark capture of the walk
The walk took 1669 request ( Get Bulk) packets and for a total packet count of 3340
Time between received GetBulk response and next GetBulk request varies between .006sec and .08sec for the 1668 total requests. I don’t see any real trends or small group of sends that are significantly longer that might indicate a problem. Some of the longer times are following responses that have longer OctetString content but some longer ones are for int32 data types.
Thanks for the response. I simply build the SnmpWalk.cpp example, without v3 enabled, with BulkMax=10 and some minor modifications to disable logging to see if that was slowing things down. The SnmpWalk example code uses getBulk if version is 2C or greater and that is why I mention getBulk. After rebuilding to Release and without logging the execution time is down 5 sec to ~20 sec. I am building and running on Windows 11 machine and walking a networked Linux box. Looks like you are running/testing on a linux box, correct?
Hi, thanks for the clarification. When using v2c and getBulk requests time ./snmpWalk 127.0.0.1 -v2 is even consuming less CPU time:
Total # of Requests = 3815
Total # of Objects = 38150
real 0m0,921s
user 0m0,192s
sys 0m0,065s
I’m in fact running this test on a Linux system and the agent is running on the same system. So only the loopback network interface is used. But the snmpWalk example only uses 0,3 seconds CPU time of my pretty old CPU. On a newer system it should be way less time.
What compiler do you use? Can you check in TaskManager if the snmpWalk is consuming CPU time or if it is sleeping/waiting only?
I am building it using MS Visual Studio 2022 and have tested both 32 and 64bit builds and there is no difference in either. When it is running for the ~20 sec it takes to walk the mib the task manager basically shows 0 for CPU, it might register a 1 once or twice but basically 0.
When you run snmpWalk how long does it actually take to finish, is it really only be 0.3 sec is it? That seams way to fast, even with no latency due to loop back mode (127.0.0.1).
I now can confirm, that snmpWalk compiled with latest MS Visual Studio, running inside a Windows 11 VM on my Linux system is slow. It takes about 60 seconds to send 3800 requests and to receive the responses with about 38000 varbinds.
Until now I was only able to track this down to something around the network usage of snmp++. The TaskManager does not show any relevant CPU usage of snmpWalk and the Sysinternals tools show about 1 second of total CPU time used during this 60 seconds runtime.
Thanks for the update. Good to know I am not loosing my mind or doing something stupid. It’s almost like there is a sleep statement somewhere in the library code but I was unable to find anything that might be responsible for this behavior. What I found very interesting, and what led me to start this thread, is how the Java based browser from ireasoning is sooooo much faster than a c++ library/code. I did a similar test with the net-snmp bulkmibwalk utility and it was even much slower than the SNMP++ example we are testing, however I did not rebuild it, i just found a windows binary of it so can’t really be sure if what may be going on with that one.
Hi, it seems that select() on Windows is blocking much longer than the specified timeout. The function int EventListHolder::SNMPProcessPendingEvents() uses the following timeout settings for select():
// do not allow select to block; chosen a very small timeout
// in order to avoid busy looping but keep overall performance
fd_timeout.tv_sec = 0;
fd_timeout.tv_usec = 10;
If the tc_usec is set to 0, the snmpWalk is much faster.
The same function contains the following code, that can also sleep much longer than the specified 1 millisecond. This does not matter for your use case, as there is one open file descriptor.
/* On Win32 select immediately returns -1 if all fd_sets are empty */
if (maxfds == 0)
Sleep(1); /* prevent 100% CPU utilization */
I will replace both code parts for the next release.