<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>wildpointer* &#187; apache</title>
	<atom:link href="http://wildpointer.org/category/tech/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://wildpointer.org</link>
	<description>referencing whatever comes to mind, by chet nichols</description>
	<lastBuildDate>Sun, 19 Jun 2011 07:27:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>apache mod_status: the misleading ReqPerSec metric</title>
		<link>http://wildpointer.org/2010/04/03/apache-mod_status-the-misleading-reqpersec-metric/</link>
		<comments>http://wildpointer.org/2010/04/03/apache-mod_status-the-misleading-reqpersec-metric/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 18:18:40 +0000</pubDate>
		<dc:creator>chet</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://chetnichols.org/?p=77</guid>
		<description><![CDATA[To be honest, I had never thought twice about it. At my past employer, we had implemented tracking request rate for the Apache hosts by parsing out Total Accesses (ie: Total Requests) from server-status (thanks to our friendly module mod_status), publish that every minute, and let our metrics collection subsystem do a delta between the [...]]]></description>
			<content:encoded><![CDATA[<p>To be honest, I had never thought twice about it. At my past employer, we had implemented tracking request rate for the Apache hosts by parsing out Total Accesses (ie: Total Requests) from server-status (thanks to our friendly module mod_status), publish that every minute, and let our metrics collection subsystem do a delta between the current and previous to determine a request rate to publish.</p>
<p>At my new employer, I put something together where the collection subsystem won&#8217;t refer to the previous total for deltas: it just takes whatever you give it and relays that to the metrics backend. Most applications provide you with a request/sec metric these days, so I figured I&#8217;d just use that. Instead of doing deltas on TotalAccesses, I started just relaying ReqPerSec instead. Simple enough, right? For those of you not familiar, here&#8217;s an example of server-status output:</p>
<pre>
Total Accesses: 400
Total kBytes: 800
CPULoad: 5
Uptime: 12345
ReqPerSec: 20
BytesPerSec: 20000
BytesPerReq: 1024
BusyWorkers: 15
IdleWorkers: 5
</pre>
<p>Well, amidst my metrics collection testing for the new system, I stumbled upon an interesting detail: I would be nailing the Apache instance with a flood of requests using my friend ab (aka: apachebench). However, I immediately noticed ReqPerSec wasn&#8217;t accurate at all. For example, I would be averaging a test of 300-400 req/s, but ReqPerSec would be displaying 21 req/s. It was as if I wasn&#8217;t sending it requests.</p>
<p>That being said, the TotalAccesses metric was reflecting the requests I was sending, so I knew the web server was receiving them. Interesting.</p>
<p>It got me thinking: &#8220;I wonder how Apache determines ReqPerSec?&#8221; Time for some source code action! Sure enough, here&#8217;s what I found:</p>
<pre language="c">
ap_rprintf(r, "ReqPerSec: %g\n",
    (float) count / (float) up_time);
</pre>
<p>Interesting! All Apache does to calculate ReqPerSec is take the total number of requests throughout the life of the parent (<b>count</b>) and divide that by the total uptime in seconds (<b>up_time</b>). So, really, ReqPerSec is just an *average* requests per second over the parent&#8217;s lifetime. That&#8217;s NOT what we want. Maybe it&#8217;s useful in some scenarios, but when you need a live metric to let you know what your server is ACTUALLY doing, this isn&#8217;t the one.</p>
<p>If you want an accurate request rate, <b>your best bet is going to be to collect Total Accesses and do deltas off of the previous collection</b>. I&#8217;m glad that&#8217;s how we did it before!</p>
<p>To a point, this goes into the expense of metrics. For Apache, Total Accesses is just a simple counter. It returns an accurate value live, on-the-fly, and makes it very easy for the sys admin to collect and process. Very little work is done on it&#8217;s end. Even the current implementation of ReqPerSec has very little cost: it just does some simple division on-demand, using counters it already tracks anyway.</p>
<p>To keep an actual average request rate, there would be some more resource involved. It would need to set a timer (ie: every 60 seconds), have a callback for the timer (to actually handle the calculation), and store counters in memory to calculate deltas. However, in reality, this will really have a very minimal impact on server performance and system load (a few extra CPU hits every minute, storing two little 64-bit counters, etc).</p>
<p><b>So what did I end up doing? I hacked up my own mod_status using shared memory!</b></p>
<p>Using the existing mod_status code, I pulled some code from a shared memory module example and smashed them together to calculate an accurate ReqPerSec metric on the fly, returned when you request server-status.</p>
<p><b>How does it work?</b></p>
<p>When you request server-status, it will go into shared memory, pull out the total accesses and uptime from the previous server-status request, do deltas on the current total accesses and uptime, then return the rate. It will then put the current total accesses and uptime back into shared memory for the next poll (<b>base</b> is our shared memory baseline).</p>
<pre>
ap_rprintf(r, "ReqPerSec: %g\n", (
    ( (float)count - (float)base->prev_req_count ) /
    ( (float)up_time - (float)base->prev_uptime ) )
);
</pre>
<p>There is of course all of the shared memory code, but the end result is the calculation above. We poll every 60 seconds, so we incur a small cost every minute, but, like I mentioned before, it&#8217;s not noticeable, and it gives us the view we need into the environment.</p>
<p><i>Some of you may also wonder what happens to the first request, since there isn&#8217;t any data in our shared memory space yet. For now, it will be inaccurate, but only for the first request in the lifetime of the parent, which I can deal with until I make it better</i>.</p>
<p>Well, that&#8217;s all for this one. It was an interesting discovery in the world of Apache metrics collection, and an interesting adventure to hack together the shared memory module. I&#8217;m sure there are other scenarios out there like this one; if you come across one, feel free to drop a comment!</p>
<p>I&#8217;m off to the Apple Store now- it&#8217;s iPad launch day <img src='http://wildpointer.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://wildpointer.org/2010/04/03/apache-mod_status-the-misleading-reqpersec-metric/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

