[Helix-server-dev] CR: Fix related to PR 258373: RHEL5 edge has much higher CPU usage than other OSes
Dean Collins <[email protected]> Thu, 4 Mar 2010 08:52:59 -0800
| Newsgroups | gmane.comp.multimedia.helix.devel |
|---|---|
| Message-ID | <[email protected]> |
Synopsis ======== Fix related to PR 258373: RHEL5 edge has much higher CPU usage than other OSes Branches: SERVER_14_0_RN, SERVER_CURRENT_RN (HEAD) Suggested Reviewer: Anyone Description =========== Profiling the server with VTune on Linux revealed a problem causing it to spin through the mainloop many hundreds of thousands of times per second or more. I determined that when calling epoll_wait() we were often passing in a timeout of zero. The Linux epoll is so wickedly fast that it would immediately pop out most of the time, often with no FDs to service. We would wind the stack back up to the mainloop(), check the FDs, scheduler, ischeculer and DispatchQ for callbacks to fire-off, find there were few if any to handle, then call back into epoll_wait(). The overhead of this spinning was accounting for a significant amount of user-space and kernel-space CPU time. The solution is to check the timeout before calling epoll_wait(). If it's zero, make it 1 so there's at least a small delay each time. This small change makes a huge difference. The timeout is in milliseconds. The interesting part is the code to implement this already existed, but was commented out! :-) All the diff does is uncomment the code. It had been commented-out since the code was originally checked-in. I don't see it mentioned in the CVS commit log, but I seem to recall discussing this and we were unsure whether it was the right thing to do so left it alone until we had time to test it. At the time, the server still had significant mutex contention that may have made the change degrade performance. Testing has shown that with the v14 server, at least on the two server-class systems it was tested on, this change is very necessary. In many scenarios it makes as much as a 8x or 10x improvement. Running an on-demand-only uptime test, based off the standard uptime configuration, the improvements were reducing overall CPU load from about 40% to 5%. MainLoopIterations were reduced from ~1,000,000/sec to 2,500/sec. Before: http://plots.coreqa.prognet.com/dcollins/archive/pr258373/servlab/defender/Logs.1-no-cloaking-demand-serveronly/server.html After: http://plots.coreqa.prognet.com/dcollins/archive/pr258373/servlab/defender/Logs.18-no-cloaking-demand-serveronly-vtune-testfix1/server.html A more isolated test easier to analyze that showed the problem more clearly was to just use the 3.3Mbps mp4 clip from the uptime, with 36 players. In this scenario, CPU usage was reduced from about 35% to 3%. MainLoopIterations were reduced from ~1,000,000/sec to ~2,000/sec. Mutex Collisions went from ~6,000/sec to ~1,000/sec. Before: http://plots.coreqa.prognet.com/dcollins/archive/pr258373/servlab/defender/Logs.13-no-cloaking-demand-serveronly-mp4-3320k_hinted-udp-36players-vtune/server.html After: http://plots.coreqa.prognet.com/dcollins/archive/pr258373/servlab/defender/Logs.17-no-cloaking-demand-serveronly-mp4-3320k_hinted-udp-36players-vtune-testfix1/server.html Lots of other stats also show significant improvements, as well as my VTune data. Despite the MP4 test above, there's nothing MP4-specific about the fix. It should improve just about anything the server does to varying degrees. Files Affected ============== server/engine/core/pub/platform/unix/servcallback.h Testing Performed ================= Unit Tests: - N/A Integration Tests: - Uptime tested in servlab (on-demand only) and in a full uptime in the QA rig. Leak Tests: - N/A Performance Tests: - N/A Platforms Tested: linux-rhel5-i686 Build verified: linux-rhel5-i686 QA Hints ======== * N/A _______________________________________________ Helix-server-dev mailing list [email protected] http://lists.helixcommunity.org/mailman/listinfo/helix-server-dev
2010_03_04-epoll_timeout.diff
(text/plain, 950 B)
Index: server/engine/core/pub/platform/unix/servcallback.h
===================================================================
RCS file: /cvsroot/server/engine/core/pub/platform/unix/servcallback.h,v
retrieving revision 1.16
diff -u -r1.16 servcallback.h
--- server/engine/core/pub/platform/unix/servcallback.h 28 Apr 2009 16:33:42 -0000 1.16
+++ server/engine/core/pub/platform/unix/servcallback.h 4 Mar 2010 16:04:07 -0000
@@ -1207,8 +1207,11 @@
return m_nReadyFDs;
}
- // if (!timeout)
- // timeout = 1;
+ // If timeout is zero epoll_wait() returns so fast, whether we have any fds
+ // to handle or not, that we often end up spinning through the mainloop many
+ // thousands or millions of times per second. epoll_wait() is quick!
+ if (!timeout)
+ timeout = 1;
m_nReadyFDs = epoll_wait(m_nPollFD, m_pEPollEvents, EPOLL_EVENTS_MAX, timeout);
if (m_nReadyFDs < 0 && errno != EINTR && errno != 0)