Windows uses an HW timer that wakes the system every 15.6ms (default). Live Audio/Video streaming application (e.g., Teams) usually set it to 1ms using timeBeginPeriod
iperf2 does not change the timer resolution, which makes its isochronous TX scheduling inaccurate.
In the first capture below, you can see that iperf2 schedule only 49pps instead of the requested 60pps.
In the second capture, the timer resolution was set to 1ms by another application. As a result, iperf2 managed to schedules 60pps.
I suggest to add option for setting the timer resolution. The default value for isochronous should be 1ms
[rjmcmahon@ryzen3950iperf2-code]$gitdiffdiff--gita/include/headers.hb/include/headers.hindex12974e8..2234273100644---a/include/headers.h+++b/include/headers.h@@-175,6+175,9@@typedefbool_Bool;#include<winsock2.h>#include<ws2tcpip.h>#include<process.h>+#ifHAVE_ISOCHRONOUS+#include<mmsystem.h>+#endif/* define EINTR, just to help compile; it isn't useful */#ifndef EINTRdiff--gita/src/isochronous.cppb/src/isochronous.cppindexf1fd494..74389ec100644---a/src/isochronous.cpp+++b/src/isochronous.cpp@@-62,7+62,12@@FrameCounter::FrameCounter(doublevalue,constTimestamp&start):frequency(va}FrameCounter::FrameCounter(doublevalue):frequency(value){#ifdef WIN32-/* Create timer */+#ifHAVE_ISOCHRONOUS+// adjust the windows internal timer period to one millisecond+inttimeperiod=1;//units is milliseconds+timeBeginPeriod(timeperiod);+#endif+/* Create timer */my_timer=CreateWaitableTimer(NULL,TRUE,NULL);if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL))WARN_errno(1,"SetThreadPriority");@@-77,6+82,11@@FrameCounter::FrameCounter(doublevalue):frequency(value){FrameCounter::~FrameCounter(){#ifdef WIN32/* Clean resources */+#ifHAVE_ISOCHRONOUS+// undo the timeBeginPeriod+inttimeperiod=1;//units is milliseconds+timeEndPeriod(timeperiod);+#endifif(my_timer)CloseHandle(my_timer);#endif[rjmcmahon@ryzen3950iperf2-code]$make-jmakeall-recursivemake[1]:Enteringdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code'Makingallincompatmake[2]:Enteringdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/compat'make[2]:Nothingtobedonefor'all'.make[2]:Leavingdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/compat'Makingallindocmake[2]:Enteringdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/doc'make[2]:Nothingtobedonefor'all'.make[2]:Leavingdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/doc'Makingallinincludemake[2]:Enteringdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/include'make[2]:Nothingtobedonefor'all'.make[2]:Leavingdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/include'Makingallinsrcmake[2]:Enteringdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/src'i686-w64-mingw32-g++-DHAVE_CONFIG_H-I.-I..-I../include-I../include-Wall-O2-O2-MTisochronous.o-MD-MP-MF.deps/isochronous.Tpo-c-oisochronous.oisochronous.cppmv-f.deps/isochronous.Tpo.deps/isochronous.Poi686-w64-mingw32-g++-Wall-O2-O2-O2-pthread-DHAVE_CONFIG_H-oiperf.exeClient.oExtractor.oisochronous.oLaunch.oactive_hosts.oListener.oLocale.oPerfSocket.oReporter.oReports.oReportOutputs.oServer.oSettings.oSocketAddr.ognu_getopt.ognu_getopt_long.ohistogram.omain.oservice.osocket_io.ostdio.opacket_ring.otcp_window_size.opdfs.o../compat/libcompat.a-lws2_32-static-libstdc++-static/usr/lib/gcc/i686-w64-mingw32/10.3.1/../../../../i686-w64-mingw32/bin/ld:isochronous.o:isochronous.cpp:(.text+0x137):undefinedreferenceto`_imp__timeBeginPeriod@4'/usr/lib/gcc/i686-w64-mingw32/10.3.1/../../../../i686-w64-mingw32/bin/ld:isochronous.o:isochronous.cpp:(.text+0x1ff):undefinedreferenceto`_imp__timeEndPeriod@4'collect2:error:ldreturned1exitstatusmake[2]:***[Makefile:478:iperf.exe]Error1make[2]:Leavingdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code/src'make[1]:***[Makefile:597:all-recursive]Error1make[1]:Leavingdirectory'/home/rjmcmahon/Code/cross-compile/iperf2-code'make:***[Makefile:537:all]Error2
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Windows uses an HW timer that wakes the system every 15.6ms (default). Live Audio/Video streaming application (e.g., Teams) usually set it to 1ms using timeBeginPeriod
iperf2 does not change the timer resolution, which makes its isochronous TX scheduling inaccurate.
In the first capture below, you can see that iperf2 schedule only 49pps instead of the requested 60pps.
In the second capture, the timer resolution was set to 1ms by another application. As a result, iperf2 managed to schedules 60pps.
I suggest to add option for setting the timer resolution. The default value for isochronous should be 1ms
ok, thanks for this. Let me take a look.
Bob
I've opened a ticket for this. Did you happen to get it to compile and work?
Cross compile is failing - need to debug