<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>time to bleed by Joe Damato</title>
	
	<link>http://timetobleed.com</link>
	<description>technical ramblings from a wanna-be unix dinosaur</description>
	<pubDate>Sun, 18 Oct 2009 20:21:48 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/TimeToBleed" type="application/rss+xml" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">TimeToBleed</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Defeating the Matasano C++ Challenge with ASLR enabled</title>
		<link>http://timetobleed.com/defeating-the-matasano-c-challenge-with-aslr-enabled/</link>
		<comments>http://timetobleed.com/defeating-the-matasano-c-challenge-with-aslr-enabled/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 11:59:29 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[bugfix]]></category>

		<category><![CDATA[debugging]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[security]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[testing]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[memory]]></category>

		<category><![CDATA[vulnerability]]></category>

		<category><![CDATA[x86_64]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=1152</guid>
		<description><![CDATA[

If you enjoy this article, subscribe (via RSS or e-mail) and follow me on twitter.
Important note
I am NOT a security researcher (I kinda want to be though). As such, there are probably way better ways to do everything in this article. This article is just illustrating my thought process when cracking this challenge.
The Challenge
The Matasano [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/computer_bug.jpg"  alt="" width="400" height="300"/></center><br />

<p>If you enjoy this article, <a rel="alternate" type="application/rss+xml" href="http://feeds.feedburner.com/TimeToBleed">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<h2>Important note</h2>
<p>I am <b>NOT</b> a security researcher (I kinda want to be though). As such, there are probably way better ways to do everything in this article. This article is just illustrating my thought process when cracking this challenge.</p>
<h2>The Challenge</h2>
<p>The <a href="http://chargen.matasano.com/chargen/2009/10/9/a-c-challenge.html">Matasano Security blog</a> recently posted an article titled <i>A C++ Challenge</i><sup>1</sup> which included a particularly ugly piece of C++ code that has a security vulnerability. The challenge is for the reader to find the vulnerability, use it execute arbitrary code, and submit the data to Matasano.</p>
<p>Sounds easy enough, let&#8217;s do this! <i>cue hacking music</i></p>
<h2>Making it harder</h2>
<p>Recent linux kernels have feature called Address Space Layout Randomization (ASLR) which can be set in <code>/proc/sys/kernel/randomize_va_space</code>. ASLR is a security feature which randomizes the start address of various parts of a process image. Doing this makes exploiting a security bug more difficult because the exploit cannot use any hard coded addresses.</p>
<p>The options you can set are:</p>
<ul>
<li>0 - ASLR off</li>
<li>1 - Randomize the addresses of the stack, mmap area, and VDSO page. <b>This is the default.</b></li>
<li>2 - Everything in option 1, but also randomize the <code>brk</code> area so the heap is randomized.</li>
</ul>
<p>Just for fun I decided to set it to <b>2</b> to make exploiting the challenge more difficult.</p>
<h2>Got the code, but now what?</h2>
<p>I decided to start attacking this problem by looking for a few common errors, in this order:</p>
<ol>
<li><code>strcpy()/strncpy()</code> bugs <b>No calls</b></li>
<li><code>memcpy()</code> bugs <b>A few calls</b></li>
<li>Off by one bugs <b>None obvious</b></li>
</ol>
<p>It turned out from a quick look that all calls to <code>memcpy()</code> included sane, hard-coded values. So, it had to be something more complex.</p>
<h2>Digging deeper - finding input streams the user can control</h2>
<p>Next, I decided to actually <b>read</b> the code and see what it was doing at a high level and what inputs could be controlled. Turns out that the program reads data from a file and uses the data from the file to determine how many objects to allocate.</p>
<p>Obviously, this portion of the code caught my interest so let&#8217;s take a quick look:</p>
<pre class="prettyprint">
/* ... */

fd.read(file_in_mem, MAX_FILE_SIZE-1);

/* ... */

struct _stream_hdr *s = (struct _stream_hdr *) file_in_mem;

if(s->num_of_streams >= INT_MAX / (int)sizeof(int)) {
    safe_count = MAX_STREAMS;
} else {
    safe_count = s->num_of_streams;
}

Obj *o = new Obj[safe_count];
</pre>
<p>
<p>OK, so clearly that <code>if</code> statement is suspect. At the <i>very least</i> it doesn&#8217;t check for negative values, so you could end up with <code>safe_count = -1</code> which might do something interesting when passed to the <code>new</code> operator. Moreover, it appears this <code>if</code> statement will allow values as large as 536870910 ([INT_MAX / sizeof(int)] - 1).</p>
<p>Maybe the exploit has something to do with values this <code>if</code> statement is allowing through?</p>
<h2>A closer look at the integer overflow in <code>new</code></h2>
<p>Let&#8217;s use GDB to take a closer look at what the compiler does before calling new. I&#8217;ve added a few comments in line to explain the assembly code:</p>
<pre class="prettyprint">
mov    %edx,%eax   ;  %edx and %eax store s->num_of_streams
add    %eax,%eax   ;  add %eax to itself (s->num_of_streams * 2)
add    %edx,%eax   ;  add  s->num_of_streams + %eax (s->num_of_streams*3)
shl    $0x2,%eax   ;  multiply (s->num_of_streams * 3) by 4  (s->num_of_streams * 12)
mov    %eax,(%esp) ;  move it into position to pass to new
call   0x8048a7c <_Znaj@plt> ; call new
</pre>
<p>
<p>The compiler has generated code to calculate: <code>s->num_of_streams * sizeof(Obj)</code>. <code>sizeof(Obj)</code> is 12 bytes. For large values of <code>s->num_of_streams</code> multiplying it by 12, causes an <b>integer overflow</b> and the value passed to new will actually be <i>less than</i> what was intended.</p>
<p>For my exploit, I ended up using the value 357913943. This value causes an overflow, because 357913943 * 12 is <i>greater than</i> the biggest possible value for an integer by 20. So the value passed to new is 20. Which is, of course, significantly less than what we actually wanted to allocate. Other people have written about integer overflow in <code>new</code> in other compilers<sup>2</sup> before.</p>
<p>Let&#8217;s see how this can be used to cause arbitrary code to execute. <b>Remember</b>, for arbitrary code execution to occur there <i>must</i> be a way to <i>cause the target program to write some data to a memory address that can be controlled</i>.</p>
<h2>Find the (possible) hand-off(s) to arbitrary code</h2>
<p>To find any hand-off locations, I looked for places where memory writes were occurring in the program. I found a few memory writes:</p>
<ul>
<li>2 calls to <code>memset()</code></li>
<li>2 calls to <code>memcpy()</code></li>
<li><code>parse_stream()</code> of <code>class Obj</code></li>
</ul>
<p>Unfortunately (from the attacker&#8217;s perspective) the calls to <code>memcpy()</code> and <code>memset()</code> <i>looked</i> pretty sane. The <code>parse_stream()</code> function caught my interest, though.</p>
<p>Take a look:</p>
<pre class="prettyprint">
class Obj {
    public:
    int parse_stream(int t, char *stream)
    {
      type = t;
      // ... do something with stream here ...
      return 0;
    }

    int length;
    int type;
/* ... */
</pre>
<p>
<p><b>REMEMBER:</b> In C++, member functions of <code>class</code>es have a <b>sekrit parameter</b> which is a pointer to the object the function is being called on. In the function itself, this parameter is accessed using <code>this</code>. So the line writing to the <code>type</code> variable is actually doing <code>this->type = t;</code> where <code>this</code> is supplied to the function <b>sektrily</b> by the compiler.</p>
<p><b>This is important</b> because this piece of code could be our hand-off! We need to find a way to control the value of <code>this</code> so we can cause a memory write to a location of our choice.</p>
<h2>Controlling <code>this</code> to cause arbitrary code to execute</h2>
<p>Take a look at an important piece of code in the challenge:</p>
<pre class="prettyprint">
struct imetad {
  int msg_length;
  int (*callback)(int, struct imetad *);
/* ... */
</pre>
<p>
<p>Nice! The <code>callback</code> field of <code>struct imetad</code> is offset by 4 bytes into the structure. The <code>type</code> field of <code>class Obj</code> is also offset by 4 bytes. See where I&#8217;m going?</p>
<p>If we can control the <code>this</code> pointer to point at the <code>struct imetad</code> on the heap when <code>parse_stream</code> is called, it will overwrite the <code>callback</code> pointer. We&#8217;ll then be able to set the pointer to any address we want and hand-off execution to arbitrary code!</p>
<p>But how can we manipulate <code>this</code>?</p>
<p>Take a look at this piece of code that calls <code>callback</code>:</p>
<pre class="prettyprint">
o[i].parse_stream(dword, stream_temp);
imd->callback(o[i].type, imd);
</pre>
<p>
<p>Since it is possible to overflow <code>new</code> and allocate fewer objects than <code>safe_count</code> is counting, that means that for some values of i, <i><code>o[i]</code> will be pointing at data that isn&#8217;t actually an <code>Obj</code> object, but just other data on the heap</i>. Infact, when <code>i = 2</code>, <b><code>o[i]</code> will be pointing at the <code>struct imetad</code> object on the heap</b>. The call to <code>parse_stream</code> will pass in a corrupted <code>this</code> pointer, that points at <code>struct imetad</code>. The write to <code>type</code> will actually overwrite <code>callback</code> since they are both offset equal amounts into their respective structures.</p>
<p>And with that, we&#8217;ve successfully exploited the challenge causing arbitrary code to execute.</p>
<p>Let&#8217;s now figure out how to beat ASLR!</p>
<h2>How to defeat address space layout randomization</h2>
<p>I <b>did NOT</b> invent this technique, but I read about it and thought it was cool. You can read a more verbose explanation of this technique <a href="http://sophsec.com/research/aslr_research.html">here</a>. The idea behind the technique is pretty simple:
</p>
<ul>
<li>When you call <code>exec</code>, the PID remains the same, but the image of the process in memory is changed.</li>
<li>The kernel uses the PID and the number of jiffies (jiffies is a fine-grained time measurement in the kernel) to pull data from the entropy pool.</li>
<li>If you can run a program which records stack, heap, and other addresses and then quickly call <code>exec</code> to start the vulnerable program, you can end up with the <b>same memory layout</b>.</li>
</ul>
<p>My exploit program is actually a <i>wrapper</i> which records an approximate location of the heap (by just calling <code>malloc()</code>), generates the exploit file, and then executes the challenge binary.</p>
<p>Take a look at the relevant pieces of my exploit to get an idea of how it works:
<pre class="prettyprint">
/* ... */

/* do a malloc to get an idea of where the heap lives */
void *dummy = malloc(10);

/* ... */

unsigned int shell_addr = reinterpret_void_ptr_as_uint(dummy);

/*
 * XXX TODO FIXME - on my platform, execl'ing from here to the challenge binary
 * incurs a constant offset of 0x3160, probably for changes in the environment
 * (libs linked for c++ and whatnot).
 */
shell_addr += 0x3160;

/*
 * a guess as to how far off the heap the shellcode lives.
 *
 * luckily we have a large NOP sled, so we should only fail when we miss
 * the current entropy cycle (see below).
 */
shell_addr += 700;

/* ... build exploit file in memory ... */

/* copy in our best guess as to the address of the shellcode, pray NOPs
 * take care of the rest! */
memcpy(entire_file+88, &#038;shell_addr, sizeof(shell_addr));

/* ... write exploit out to disk ... */

/* launch program with the generated exploit file!
*
* calling execl here inherits the PID of this process, and IF we get lucky
* ~85%+ of the time, we'll execute before the next entropy cycle and hit
* the shellcode, even with ASLR=2.
*/
execl("./cpp_challenge", "cpp_challenge", "exploit", (char *)0);
</pre>
<h2>My exploit for the C++ challenge</h2>
<p>My exploit comes with the following caveats:</p>
<ul>
<li>i386 system</li>
<li>The challenge binary is called &#8220;cpp_challenge&#8221; and lives in the same directory as the exploit binary.</li>
<li>The exploit binary can write to the directory and create a file called &#8220;exploit&#8221; which will be handed off to &#8220;cpp_challenge&#8221;</li>
</ul>
<p>Get the full code of my exploit <a href="http://timetobleed.com/files/exploit_gen.c">here</a>.</p>
<h2>Results</h2>
<p>Results on my i386 Ubuntu 8.04 VM running in VMWare fusion, for each level of randomize_va_space:</p>
<ul>
<li>0 - <b>100%</b> exploit hit rate</li>
<li>1 - <b>100%</b> exploit hit rate</li>
<li>2 - <b>~85%</b> exploit hit rate. Sometimes, my exploit code falls out of the time window and the address map changes before the challenge binary is run</li>
</ul>
<p>I could probably boost the hit rate for 2 a bit, but then I&#8217;d probably re-write the entire exploit in assembly to make it run as fast as possible. I didn&#8217;t think there was really a point to going to such an extreme, though. So, an 85% hit rate is good enough.</p>
<h2>Conclusion</h2>
<ol>
<li>Security challenges are fun.</li>
<li>More emphasis and more freely available information on secure coding would be very useful.</li>
<li>Like it or not developers need to be security conscious when writing code in C and C++.</li>
<li>As C and C++ change, developers need to carefully consider security implications of new features.</li>
</ol>
<p>
Thanks for reading and don&#8217;t forget to <a rel="alternate" type="application/rss+xml" href="http://feeds.feedburner.com/TimeToBleed">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<h2>References</h2>
<ol class="footnotes"><li id="footnote_0_1152" class="footnote"><a href="http://chargen.matasano.com/chargen/2009/10/9/a-c-challenge.html">Matasano Security LLC - Chargen - A C++ Challenge</a></li><li id="footnote_1_1152" class="footnote"><a href="http://blogs.msdn.com/oldnewthing/archive/2004/01/29/64389.aspx">Integer overflow in the new[] operator</a></li></ol><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=5J34pmGgoto:t-GfI5V7rLg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=5J34pmGgoto:t-GfI5V7rLg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=5J34pmGgoto:t-GfI5V7rLg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=5J34pmGgoto:t-GfI5V7rLg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=5J34pmGgoto:t-GfI5V7rLg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=5J34pmGgoto:t-GfI5V7rLg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=5J34pmGgoto:t-GfI5V7rLg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=5J34pmGgoto:t-GfI5V7rLg:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/5J34pmGgoto" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/defeating-the-matasano-c-challenge-with-aslr-enabled/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Extending ltrace to make your Ruby/Python/Perl/PHP apps faster</title>
		<link>http://timetobleed.com/extending-ltrace-to-make-your-rubypythonperlphp-apps-faster/</link>
		<comments>http://timetobleed.com/extending-ltrace-to-make-your-rubypythonperlphp-apps-faster/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 11:59:56 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[debugging]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[monitoring]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[debug]]></category>

		<category><![CDATA[ltrace]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[profiling]]></category>

		<category><![CDATA[strace]]></category>

		<category><![CDATA[system health]]></category>

		<category><![CDATA[x86_64]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=1058</guid>
		<description><![CDATA[

If you enjoy this article, subscribe (via RSS or e-mail) and follow me on twitter.
A few days ago, Aman (@tmm1) was complaining to me about a slow running process:

I want to see what is happening in userland and trace calls to extensions. Why doesn&#8217;t ltrace work for Ruby processes? I want to figure out which [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/trace.jpg" alt="" width="400" height="300" /></center><br />

<p>If you enjoy this article, <a rel="alternate" type="application/rss+xml" href="http://feeds.feedburner.com/TimeToBleed">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<p>A few days ago, Aman (<a href="http://twitter.com/tmm1">@tmm1</a>) was complaining to me about a slow running process:</p>
<p>
<blockquote>I want to see what is happening in userland and trace calls to extensions. Why doesn&#8217;t ltrace work for Ruby processes? I want to figure out which MySQL queries are causing my app to be slow.</p></blockquote>
<p>It turns out that <b>ltrace did not have support for libraries loaded with libdl</b>. This is a problem for languages like Ruby, Python, PHP, Perl, and others because in many cases extensions, libraries, and plugins for these languages are loaded by the VM using libdl. This means that ltrace is somewhat useless for tracking down performance issues in dynamic languages.</p>
<p>A couple late nights of hacking and I <b>managed to finagle libdl support in ltrace.</b> Since most people probably don&#8217;t care about the technical details of how it was implemented, I&#8217;ll start with showing how to use the patch I wrote and what sort of output you can expect. <b>This patch has made tracking down slow queries (among other things) really easy and I hope others will find this useful.</b></p>
<h2>How to use ltrace:</h2>
<p>After you&#8217;ve applied my patch (below) and rebuilt ltrace, let&#8217;s say you&#8217;d like to trace MySQL queries and have ltrace tell you when the query was executed and how long it took. There are two steps:</p>
<ol>
<li>Give ltrace info so it can pretty print - echo &#8220;int mysql_real_query(addr,string,ulong);&#8221;  > custom.conf</li>
<li>Tell ltrace you want to hear about <code>mysql_real_query</code>: <b><code>ltrace -F custom.conf -ttTgx mysql_real_query -p &lt;pid&gt;</code></b></li>
</ol>
<p>Here&#8217;s what those arguments mean:</p>
<ul>
<li><b>-F</b>  use a custom config file when pretty-printing (default: /etc/ltrace.conf, add your stuff there to avoid -F if you wish).</li>
<li><b>-tt</b>  print the time (including microseconds) when the call was executed</li>
<li><b>-T</b>   time the call and print how long it took</li>
<li><b>-x</b>   tells ltrace the name of the function you care about</li>
<li><b>-g</b>  <i>avoid</i> placing breakpoints on all library calls except the ones you specify with -x. <b>This is optional</b>, but it makes ltrace produce much less output and is a lot easier to read if you only care about your one function.</li>
</ul>
<h2>PHP</h2>
<h3>Test script</h3>
<pre class="prettyprint">
mysql_connect("localhost", "root");
while(true){
    mysql_query("SELECT sleep(1)");
}
</pre>
<p></p>
<h3>ltrace output</h3>
<pre class="prettyprint">
22:31:50.507523 zend_hash_find(0x025dc3a0, "mysql_query", 12) = 0 <0.000029>
22:31:50.507781 mysql_real_query(0x027bc540, "SELECT sleep(1)", 15) = 0 <1.000600>
22:31:51.508531 zend_hash_find(0x025dc3a0, "mysql_query", 12) = 0 <0.000025>
22:31:51.508675 mysql_real_query(0x027bc540, "SELECT sleep(1)", 15) = 0 <1.000926>
</pre>
<p></p>
<h3><code>ltrace</code> command</h3>
<pre class="prettyprint">
ltrace -ttTg -x zend_hash_find -x mysql_real_query -p [pid of script above]</pre>
<h2>Python</h2>
<h3>Test script</h3>
<pre class="prettyprint">
import MySQLdb
db = MySQLdb.connect("localhost", "root", "", "test")
cursor = db.cursor()
sql = """SELECT sleep(1)"""
while True:
	cursor.execute(sql)
	data = cursor.fetchone()
db.close()
</pre>
<p></p>
<h3><code>ltrace</code> output</h3>
<pre class="prettyprint">
22:24:39.104786 PyEval_SaveThread() = 0x21222e0 <0.000029>
22:24:39.105020 PyEval_SaveThread() = 0x21222e0 <0.000024>
22:24:39.105210 PyEval_SaveThread() = 0x21222e0 <0.000024>
22:24:39.105303 mysql_real_query(0x021d01d0, "SELECT sleep(1)", 15) = 0 <1.002083>
22:24:40.107553 PyEval_SaveThread() = 0x21222e0 <0.000026>
22:24:40.107713 PyEval_SaveThread()= 0x21222e0 <0.000024>
22:24:40.107909 PyEval_SaveThread() = 0x21222e0 <0.000025>
22:24:40.108013 mysql_real_query(0x021d01d0, "SELECT sleep(1)", 15) = 0 <1.001821>
</pre>
<p></p>
<h3><code>ltrace</code> command</h3>
<pre class="prettyprint">
ltrace -ttTg -x PyEval_SaveThread -x mysql_real_query -p [pid of script above]</pre>
<h2>Perl</h2>
<h3>Test script</h3>
<pre class="prettyprint">
#!/usr/bin/perl
use DBI;

$dsn = "DBI:mysql:database=test;host=localhost";
$dbh = DBI->connect($dsn, "root", "");
$drh = DBI->install_driver("mysql");
@databases = DBI->data_sources("mysql");
$sth = $dbh->prepare("SELECT SLEEP(1)");

while (1) {
  $sth->execute;
}
</pre>
<p></p>
<h3><code>ltrace</code> output</h3>
<pre class="prettyprint">
22:42:11.194073 Perl_push_scope(0x01bd3010) = <void> <0.000028>
22:42:11.194299 mysql_real_query(0x01bfbf40, "SELECT SLEEP(1)", 15) = 0 <1.000876>
22:42:12.195302 Perl_push_scope(0x01bd3010) = <void> <0.000024>
22:42:12.195408 mysql_real_query(0x01bfbf40, "SELECT SLEEP(1)", 15) = 0 <1.000967>
</pre>
<p></p>
<h3><code>ltrace</code> command</h3>
<pre class="prettyprint">
ltrace -ttTg -x mysql_real_query -x Perl_push_scope -p [pid of script above]</pre>
<h2>Ruby</h2>
<h3>Test script</h3>
<pre class="prettyprint">
require 'rubygems'
require 'sequel'

DB = Sequel.connect('mysql://root@localhost/test')

while true
  p DB['select sleep(1)'].select.first
  GC.start
end
</pre>
<p></p>
<h3>snip of <code>ltrace</code> output</h3>
<pre class="prettyprint">
22:10:00.195814 garbage_collect()  = 0 <0.022194>
22:10:00.218438 mysql_real_query(0x02740000, "select sleep(1)", 15) = 0 <1.001100>
22:10:01.219884 garbage_collect() = 0 <0.021401>
22:10:01.241679 mysql_real_query(0x02740000, "select sleep(1)", 15) = 0 <1.000812>
</pre>
<p></p>
<h3><code>ltrace</code> command used:</h3>
<pre class="prettyprint">
ltrace -ttTg -x garbage_collect -x mysql_real_query -p [pid of script above]</pre>
<h2>Where to get it</h2>
<ul>
<li>On github: <a href="http://github.com/ice799/ltrace/tree/libdl">http://github.com/ice799/ltrace/tree/libdl</a></li>
<li>Raw patch (<strong>NOTE:</strong> This should apply cleanly against ltrace 0.5.3): <a href="http://timetobleed.com/files/ltrace.patch">ltrace.patch</a></li>
</ul>
<h2>How ltrace works normally</h2>
<p><code>ltrace</code> works by setting <b>software breakpoints</b> on entries in a process&#8217; <b>Procedure Linkage Table</b> (PLT).</p>
<h2>What is a software breakpoint</h2>
<p>A software breakpoint is just a series of bytes (<code>0xcc</code> on the x86 and x86_64) that raise a debug interrupt (interrupt 3 on the x86 and x86_64). When interrupt 3 is raised, the CPU executes a handler installed by the kernel. The kernel then sends a signal to the process that generated the interrupt. (Want to know more about how signals and interrupts work? Check out an earlier blog post: <a href="http://timetobleed.com/a-few-things-you-didnt-know-about-signals-in-linux-part-1/">here</a>)</p>
<h2>What is a PLT and how does it work?</h2>
<p>A PLT is a table of absolute addresses to functions. It is used because the link editor doesn&#8217;t know where functions in shared objects will be located. Instead, a table is created so that the program and the dynamic linker can work together to find and execute functions in shared objects. I&#8217;ve simplified the explanation a bit<sup>1</sup>, but at a high level:</p>
<ol>
<li>Program calls a function in a shared object, the link editor makes sure that the program jumps to a slot in the PLT.</li>
<li>The program sets some data up for the dynamic linker and then hands control over to it.</li>
<li>The dynamic linker looks at the info set up by the program and fills in the absolute address of the function that was called in the PLT.</li>
<li>Then the dynamic linker calls the function.</li>
<li>Subsequent calls to the same function jump to the same slot in the PLT, but every time after the first call the absolute address is already in the PLT (because when the dynamic linker is invoked the first time, it fills in the absolute address in the PLT).</p>
</ol>
<p>Since all calls to library functions occur via the PLT, <code>ltrace</code> sets breakpoints on each PLT entry in a program.</p>
<h2>Why ltrace didn&#8217;t work with libdl loaded libraries</h2>
<p>Libraries loaded with libdl are loaded at run time and functions (and other symbols) are accessed by querying the dynamic linker (by calling <code>dlsym()</code>). The compiler and link editor don&#8217;t know anything about libraries loaded this way (they may not even exist!) and as such no PLT entries are created for them.</p>
<p>Since no PLT entries exist, <code>ltrace</code> can&#8217;t trace these functions.</p>
<h2>What needed to be done to make ltrace libdl-aware</h2>
<p>OK, so we understand the problem. <code>ltrace</code> only sets breakpoints on PLT entries and libdl loaded libraries don&#8217;t have PLT entries. How can this be fixed?</p>
<p><b>Luckily, the dynamic linker and ELF all work together to save your ass.</b></p>
<p>Executable and Linking Format (ELF) is a file format for executables, shared libraries, and more<sup>2</sup>. The file format can get a bit complicated, but all you really need to know is: ELF consists of different sections which hold different types of entries. There is a section called <code>.dynamic</code> which has an entry named <code>DT_DEBUG</code>. This entry stores the address of a debugging structure <i>in the address space of the process</i>. In Linux, this struct has type <code>struct r_debug</code>.</p>
<h2>How to use struct r_debug to win the game</h2>
<p>The debug structure is <b>updated by the dynamic linker at runtime</b> to reflect the current state of shared object loading. The structure contains 3 things that will help us in our quest:</p>
<ol>
<li>state - the current state of the mapping change taking place (begin add, begin delete, consistent)</li>
<li>brk - the address of a function <i>internal to the dynamic linker</i> that will be called when the linker maps, unmaps, or has completed mapping a shared object.</li>
<li>link map - Pointer to the start of a list of currently loaded objects. This list is called the <b>link map</b> and is represented as a <code>struct link_map</code> in Linux.</li>
</ol>
<h2>Tie it all together and bring it home</h2>
<p>To add support for libdl loaded libraries to <code>ltrace</code>, the steps are:</p>
<ol>
<li>Find the address of the debug structure in the <code>.dynamic</code> section of the program.</li>
<li>Set a software breakpoint on <code>brk</code>.</li>
<li>When the dynamic linker updates the link map, it will trigger the software breakpoint.</li>
<li>When the breakpoint is triggered, check <code>state</code> in the debug structure.</li>
<li>If a new library has been added, walk the link map and figure out what was added.</li>
<li>Search the added library&#8217;s symbol table for the symbols we care about.</li>
<li>Set a software breakpoints on whatever is found.</li>
<li>Steps 3-8 repeat.</li>
</ol>
<p>That isn&#8217;t too hard all thanks to the dynamic linker providing a way for us to hook into its internal events.</p>
<h2>Conclusion</h2>
<ul>
<li>Read the System V ABI for your CPU. It is filled with insanely useful information that can help you be a better programmer.</li>
<li>Use the source. A few times while hacking on this patch I looked through the source for GDB and glibc to help me figure out what was going on.</li>
<li>Understanding how things work at a low-level can help you build tools to solve your high-level problems.</li>
</ul>
<p>Thanks for reading and don&#8217;t forget to <a rel="alternate" type="application/rss+xml" href="http://feeds.feedburner.com/TimeToBleed">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<h2>References</h2>
<ol class="footnotes"><li id="footnote_0_1058" class="footnote"><a href="http://www.x86-64.org/documentation/abi.pdf">System V Application Binary Interface AMD64 Architecture Processor Supplement, p 78</a></li><li id="footnote_1_1058" class="footnote"><a href="http://refspecs.freestandards.org/elf/elf.pdf">Executable and Linking Format (ELF) Specification</a></li></ol><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=PEMSawbepss:10Fc7Kk5p7Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=PEMSawbepss:10Fc7Kk5p7Q:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=PEMSawbepss:10Fc7Kk5p7Q:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=PEMSawbepss:10Fc7Kk5p7Q:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=PEMSawbepss:10Fc7Kk5p7Q:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=PEMSawbepss:10Fc7Kk5p7Q:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=PEMSawbepss:10Fc7Kk5p7Q:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=PEMSawbepss:10Fc7Kk5p7Q:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/PEMSawbepss" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/extending-ltrace-to-make-your-rubypythonperlphp-apps-faster/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Ruby Hoedown Slides</title>
		<link>http://timetobleed.com/ruby-hoedown-slides/</link>
		<comments>http://timetobleed.com/ruby-hoedown-slides/#comments</comments>
		<pubDate>Sat, 29 Aug 2009 08:05:33 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[debugging]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[bugfix]]></category>

		<category><![CDATA[debug]]></category>

		<category><![CDATA[fibers]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[profiling]]></category>

		<category><![CDATA[ruby hoedown]]></category>

		<category><![CDATA[scaling]]></category>

		<category><![CDATA[strace]]></category>

		<category><![CDATA[syscall]]></category>

		<category><![CDATA[threading]]></category>

		<category><![CDATA[threads]]></category>

		<category><![CDATA[x86_64]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=1046</guid>
		<description><![CDATA[Below are the slides for a talk that Aman Gupta and I gave at Ruby Hoedown
Download the PDF here
Threaded Awesome



Thanks for reading and don&#8217;t forget to subscribe (via RSS or e-mail) and follow me on twitter.
]]></description>
			<content:encoded><![CDATA[<p>Below are the slides for a talk that <a href="http://twitter.com/tmm1">Aman Gupta</a> and I gave at <a href="http://rubyhoedown.com"/>Ruby Hoedown</a></p>
<h3>Download the PDF <a href="http://dl.getdropbox.com/u/1681973/threaded_awesome_small.pdf">here</a></h3>
<p><div style="width:425px;text-align:left" id="__ss_1922719"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/tmm1/threaded-awesome-1922719" title="Threaded Awesome">Threaded Awesome</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=threadedawesome-090829020831-phpapp02&#038;stripped_title=threaded-awesome-1922719" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=threadedawesome-090829020831-phpapp02&#038;stripped_title=threaded-awesome-1922719" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
<p>
</p>
<p>
<p>Thanks for reading and don&#8217;t forget to <a href="http://feeds.feedburner.com/TimeToBleed" rel="alternate" type="application/rss+xml">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=VVUhea4p8M4:FrfHkM_bAwc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=VVUhea4p8M4:FrfHkM_bAwc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=VVUhea4p8M4:FrfHkM_bAwc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=VVUhea4p8M4:FrfHkM_bAwc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=VVUhea4p8M4:FrfHkM_bAwc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=VVUhea4p8M4:FrfHkM_bAwc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=VVUhea4p8M4:FrfHkM_bAwc:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=VVUhea4p8M4:FrfHkM_bAwc:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/VVUhea4p8M4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/ruby-hoedown-slides/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Useful kernel and driver performance tweaks for your Linux server</title>
		<link>http://timetobleed.com/useful-kernel-and-driver-performance-tweaks-for-your-linux-server/</link>
		<comments>http://timetobleed.com/useful-kernel-and-driver-performance-tweaks-for-your-linux-server/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 10:20:21 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[linux]]></category>

		<category><![CDATA[monitoring]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[BIOS]]></category>

		<category><![CDATA[kernel]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[scaling]]></category>

		<category><![CDATA[system health]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[x86_64]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=1000</guid>
		<description><![CDATA[

This article is going to address some kernel and driver tweaks that are interesting and useful. We use several of these in production with excellent performance, but you should proceed with caution and do research prior to trying anything listed below.
Tickless System
The tickless kernel feature allows for on-demand timer interrupts. This means that during idle [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/kernel.jpg" width="400" height="300"/></center><br />

<p>This article is going to address some kernel and driver tweaks that are interesting and useful. We use several of these in production with <i>excellent</i> performance, but you should <b>proceed with caution</b> and do research <b>prior to trying anything listed below.</b></p>
<h2>Tickless System</h2>
<p>The tickless kernel feature allows for on-demand timer interrupts. This means that during idle periods, fewer timer interrupts will fire, which should lead to power savings, cooler running systems, and fewer useless context switches.</p>
<p><b>Kernel option:</b> CONFIG_NO_HZ=y</p>
<h2>Timer Frequency</h2>
<p>You can select the rate at which timer interrupts in the kernel will fire. When a timer interrupt fires on a CPU, the process running on that CPU is interrupted while the timer interrupt is handled. Reducing the rate at which the timer fires allows for fewer interruptions of your running processes.  This option is particularly useful for servers with multiple CPUs where processes are not running interactively.</p>
<p><b>Kernel options:</b> CONFIG_HZ_100=y  and CONFIG_HZ=100</p>
<h2>Connector</h2>
<p>The connector module is a kernel module which reports process events such as <code>fork</code>, <code>exec</code>, and <code>exit</code> to userland. This is <b>extremely</b> useful for process monitoring. You can build a simple system (or use an existing one like <a href="http://god.rubyforge.org/"/>god</a>) to watch mission-critical processes. If the processes die due to a signal (like <code>SIGSEGV</code>, or <code>SIGBUS</code>) or exit unexpectedly you&#8217;ll get an asynchronous notification from the kernel. The processes can then be restarted by your monitor keeping downtime to a minimum when unexpected events occur.</p>
<p><b>Kernel options:</b> CONFIG_CONNECTOR=y and CONFIG_PROC_EVENTS=y</p>
<h2>TCP segmentation offload (TSO)</h2>
<p>A popular feature among newer NICs is TCP segmentation offload (TSO). This feature allows the kernel to offload the work of dividing large packets into smaller packets to the NIC. This frees up the CPU to do more useful work and reduces the amount of overhead that the CPU passes along the bus. If your NIC supports this feature, you can enable it with <code>ethtool</code>:</p>
<p><pre class="prettyprint lang-sh">
[joe@timetobleed]% sudo ethtool -K eth1 tso on
</pre>
</p>
<p></p>
<p>Let&#8217;s quickly verify that this worked:</p>
<pre class="prettyprint lang-sh">
[joe@timetobleed]% sudo ethtool -k eth1
Offload parameters for eth1:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp segmentation offload: on
udp fragmentation offload: off
generic segmentation offload: on
large receive offload: off

[joe@timetobleed]% dmesg | tail -1
[892528.450378] 0000:04:00.1: eth1: TSO is Enabled
</pre>
</p>
<p></p>
<h2>Intel I/OAT DMA Engine</h2>
<p>This kernel option enables the Intel I/OAT DMA engine that is present in recent Xeon CPUs. This option increases network throughput as the DMA engine allows the kernel to offload network data copying from the CPU to the DMA engine. This frees up the CPU to do more useful work.</p>
<p>Check to see if it&#8217;s enabled:</p>
<p>
<pre class="prettyprint lang-sh">
[joe@timetobleed]% dmesg | grep ioat
ioatdma 0000:00:08.0: setting latency timer to 64
ioatdma 0000:00:08.0: Intel(R) I/OAT DMA Engine found, 4 channels, device version 0x12, driver version 3.64
ioatdma 0000:00:08.0: irq 56 for MSI/MSI-X
</pre>
<p></p>
<p>There&#8217;s also a sysfs interface where you can get some statistics about the DMA engine. Check the directories under <code>/sys/class/dma/</code>.</p>
<p><b>Kernel options</b>: CONFIG_DMADEVICES=y and CONFIG_INTEL_IOATDMA=y and CONFIG_DMA_ENGINE=y and CONFIG_NET_DMA=y and CONFIG_ASYNC_TX_DMA=y</p>
</p>
<h2>Direct Cache Access (DCA)</h2>
<p>Intel&#8217;s I/OAT also includes a feature called Direct Cache Access (DCA). DCA allows a driver to warm a CPU cache. A few NICs support DCA, the most popular (to my knowledge) is the Intel 10GbE driver (<code>ixgbe</code>). Refer to your NIC driver documentation to see if your NIC supports DCA. To enable DCA, a switch in the BIOS must be flipped. Some vendors supply machines that support DCA, but don&#8217;t expose a switch for DCA. If that is the case, see my last blog post for how to <a href="http://timetobleed.com/enabling-bios-options-on-a-live-server-with-no-rebooting/">enable DCA manually</a>.</p>
<p>You can check if DCA is enabled:</p>
<p>
<pre class="prettyprint lang-sh">
[joe@timetobleed]% dmesg | grep dca
dca service started, version 1.8
</pre>
<p></p>
<p>If DCA is possible on your system but disabled you&#8217;ll see:</p>
<p>
<pre class="prettyprint lang-sh">
ioatdma 0000:00:08.0: DCA is disabled in BIOS
</pre>
<p>
<p>
Which means you&#8217;ll need to enable it in the BIOS or manually.</p>
<p><b>Kernel option:</b> CONFIG_DCA=y</p>
<h2>NAPI</h2>
<p>The &#8220;New API&#8221; (NAPI) is a rework of the packet processing code in the kernel to improve performance for high speed networking. NAPI provides two major features<sup>1</sup>:</p>
<blockquote><p><b>Interrupt mitigation:</b> High-speed networking can create thousands of interrupts per second, all of which tell the system something it already knew: it has lots of packets to process. NAPI allows drivers to run with (some) interrupts disabled during times of high traffic, with a corresponding decrease in system load.</p>
<p><b>Packet throttling:</b> When the system is overwhelmed and must drop packets, it&#8217;s better if those packets are disposed of before much effort goes into processing them. NAPI-compliant drivers can often cause packets to be dropped in the network adaptor itself, before the kernel sees them at all. </p></blockquote>
<p>Many recent NIC drivers automatically support NAPI, so you don&#8217;t need to do anything. Some drivers need you to explicitly specify NAPI in the kernel config or on the command line when compiling the driver. If you are unsure, check your driver documentation. A good place to look for docs is in your kernel source under Documentation, available on the web here: <a href="http://lxr.linux.no/linux+v2.6.30/Documentation/networking/">http://lxr.linux.no/linux+v2.6.30/Documentation/networking/</a> but <b>be sure to select the correct kernel version, first!</b></p>
<p><b>Older e1000 drivers (newer drivers, do nothing)</b>: <code>make CFLAGS_EXTRA=-DE1000_NAPI install</code></p>
<h2>Throttle NIC Interrupts</h2>
<p>Some drivers allow the user to specify the rate at which the NIC will generate interrupts. The <code>e1000e</code> driver allows you to pass a command line option <code>InterruptThrottleRate</code></p>
<p> when loading the module with <code>insmod</code>. For the <code>e1000e</code> there are two dynamic interrupt throttle mechanisms, specified on the command line as 1 (dynamic) and 3 (dynamic conservative). The adaptive algorithm traffic into different classes and adjusts the interrupt rate appropriately. The difference between dynamic and dynamic conservative is the the rate for the &#8220;Lowest Latency&#8221; traffic class, dynamic (1) has a much more aggressive interrupt rate for this traffic class.</p>
<p>As always, check your driver documentation for more information.</p>
<p><b>With modprobe:</b><code> insmod e1000e.o InterruptThrottleRate=1</code></p>
<h2>Process and IRQ affinity</h2>
<p>Linux allows the user to specify which CPUs processes and interrupt handlers are bound.</p>
<ul>
<li><b>Processes</b> You can use <code>taskset</code> to specify which CPUs a process can run on</li>
<li><b>Interrupt Handlers</b> The interrupt map can be found in /proc/interrupts, and the affinity for each interrupt can be set in the file smp_affinity in the directory for each interrupt under /proc/irq/</li>
</ul>
<p>This is useful because you can pin the interrupt handlers for your NICs to specific CPUs so that when a shared resource is touched (a lock in the network stack) and loaded to a CPU cache, the next time the handler runs, it will be put on the <i>same</i> CPU avoiding costly cache invalidations that can occur if the handler is put on a different CPU.</p>
<p>However, reports<sup>2</sup> of up to a <b>24% improvement</b> can be had if processes and the IRQs for the NICs the processes get data from are pinned to the same CPUs. Doing this ensures that the data loaded into the CPU cache by the interrupt handler can be used (without invalidation) by the process; extremely high cache locality is achieved.</p>
<h2>oprofile</h2>
<p>oprofile is a system wide profiler that can profile both kernel and application level code. There is a kernel driver for oprofile which generates collects data in the x86&#8217;s Model Specific Registers (MSRs) to give very detailed information about the performance of running code. oprofile can also <b>annotate source code</b> with performance information to make fixing bottlenecks easy. See oprofile&#8217;s <a href="http://oprofile.sourceforge.net/examples/">homepage</a> for more information.</p>
<p><b>Kernel options:</b> CONFIG_OPROFILE=y and CONFIG_HAVE_OPROFILE=y</p>
<h2><code>epoll</code></h2>
<p><code>epoll(7)</code> is useful for applications which must watch for events on large numbers of file descriptors. The <code>epoll</code> interface is designed to easily scale to large numbers of file descriptors. <code>epoll</code> is <b>already enabled in most recent kernels</b>, but some strange distributions (which will remain nameless) have this feature disabled.</p>
<p><b>Kernel option:</b> CONFIG_EPOLL=y</p>
<h2>Conclusion</h2>
<ul>
<li>There are a lot of useful levers that can be pulled when trying to squeeze every last bit of performance out of your system</li>
<li>It is <b>extremely</b> important to read and understand your hardware documentation if you hope to achieve the maximum throughput your system can achieve</li>
<li>You can find documentation for your kernel online at the <a href="http://lxr.linux.no/linux+v2.6.30/Documentation/">Linux LXR</a>. <b>Make sure to select the correct kernel version</b> because docs change as the source changes!</li>
</ul>
<p>Thanks for reading and don&#8217;t forget to <a href="http://feeds.feedburner.com/TimeToBleed" rel="alternate" type="application/rss+xml">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<h2>References</h2>
<ol class="footnotes"><li id="footnote_0_1000" class="footnote"><a href="http://www.linuxfoundation.org/en/Net:NAPI">http://www.linuxfoundation.org/en/Net:NAPI</a></li><li id="footnote_1_1000" class="footnote"><a href="http://software.intel.com/en-us/articles/improved-linux-smp-scaling-user-directed-processor-affinity/">http://software.intel.com/en-us/articles/improved-linux-smp-scaling-user-directed-processor-affinity/</a></li></ol><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=XG0-Wk0b80M:S8klXDsmzsw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=XG0-Wk0b80M:S8klXDsmzsw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=XG0-Wk0b80M:S8klXDsmzsw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=XG0-Wk0b80M:S8klXDsmzsw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=XG0-Wk0b80M:S8klXDsmzsw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=XG0-Wk0b80M:S8klXDsmzsw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=XG0-Wk0b80M:S8klXDsmzsw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=XG0-Wk0b80M:S8klXDsmzsw:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/XG0-Wk0b80M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/useful-kernel-and-driver-performance-tweaks-for-your-linux-server/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Enabling BIOS options on a live server with no rebooting</title>
		<link>http://timetobleed.com/enabling-bios-options-on-a-live-server-with-no-rebooting/</link>
		<comments>http://timetobleed.com/enabling-bios-options-on-a-live-server-with-no-rebooting/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 13:00:16 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[linux]]></category>

		<category><![CDATA[scaling]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[BIOS]]></category>

		<category><![CDATA[kernel]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[x86_64]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=888</guid>
		<description><![CDATA[

This blog post is going to describe a C program that toggles some CPU and chipset registers directly to enable Direct Cache Access without needing a reboot or a switch in the BIOS. A very fun hack to write and investigate.
Special thanks&#8230; 
Special thanks going out to Roman Nurik for helping me make the code [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/bios.gif" height=200 width=300/></center><br />

<p>This blog post is going to describe a C program that toggles some CPU and chipset registers directly to enable Direct Cache Access without needing a reboot or a switch in the BIOS. A very fun hack to write and investigate.</p>
<h2>Special thanks&#8230; </h2>
<p>Special thanks going out to <a href="http://twitter.com/romannurik">Roman Nurik</a> for helping me make the code CSS much, much prettier and easier to read.</p>
<p>Special thanks going out to <a href="http://twitter.com/jakedouglas">Jake Douglas</a> for convincing me that I shouldn&#8217;t use a stupid sensationalist title for this blog article :)</p>
<h2>Intel I/OAT and Direct Cache Access (DCA)</h2>
<p>From the Linux Foundation I/OAT project page<sup>1</sup>:</p>
<blockquote><p>I/OAT (I/O Acceleration Technology) is the name for a collection of techniques by Intel to improve network throughput. The most significant of these is the DMA engine. The DMA engine is meant to offload from the CPU the copying of  [socket buffer] data to the user buffer. This is not a zero-copy receive, but does allow the CPU to do other work while the copy operations are performed by the DMA engine.</p></blockquote>
<p></p>
<p><b>Cool!</b> So by using I/OAT the network stack in the Linux kernel can offload copy operations to increase throughput. I/OAT also includes a feature called Direct Cache Access (DCA) which can <i>deliver data directly into processor caches</i>. This is particularly cool because when a network interrupt arrives and data is copied to system memory, the CPU which will access this data will <b>not</b> cause a cache-miss on the CPU because DCA has already put the data it needs in the cache. Sick.</p>
<p>Measurements from the Linux Foundation project<sup>2</sup> indicate a 10% reduction in CPU usage, while the Myri-10G NIC website claims they&#8217;ve measured a <i>40%</i> reduction in CPU usage<sup>3</sup>. For more information describing the performance benefits of DCA see this incredibly detailed paper: <a href="http://www.stanford.edu/group/comparch/papers/huggahalli05.pdf">Direct Cache Access for High Bandwidth Network I/O</a>.</p>
<h2>How to get I/OAT and DCA</h2>
<p>To get I/OAT and DCA you need a few things:</p>
<ul>
<li>Intel XEON CPU(s)</li>
<li>A NIC(s) which has DCA support</li>
<li>A chipset which supports DCA</li>
<li>The <code>ioatdma</code> and <code>dca</code> Linux kernel modules</li>
<li>And last but not least, a switch in your BIOS to turn DCA on</li>
</ul>
<p>That last item can actually be a bit more tricky than it sounds for several reasons:</p>
<ul>
<li>some BIOSes <i>don&#8217;t expose a way to turn DCA on even though it is supported by the CPU, chipset, and NIC!</i></li>
<li>Your hosting provider may not allow BIOS access</li>
<li>Your system might be up and running and you don&#8217;t want to reboot to enter the BIOS to enable DCA</li>
</ul>
<p><b>Let&#8217;s see what you can do to coerce DCA into working on your system if one of the above applies to you</b>.</p>
<h2>Build <code>ioatdma</code> kernel module</h2>
<p>This is pretty easy, just <code>make menuconfig</code> and toggle I/OAT as a module. You <b>must</b> build it as a module if you cannot or do not want to enable DCA in your BIOS.</p>
<p>The option can be found in <code>Device Drivers -> DMA Engine Support -> Intel I/OAT DMA Support</code>.</p>
<p>Toggling that option will build the <code>ioatdma</code> and <code>dca</code> modules. Build and install the new module.</p>
<h2>Enabling DCA without a reboot or BIOS access: Hack overview</h2>
<p>In order to enable DCA a few special registers need to be touched.</p>
<ul>
<li>The DCA capability bit in the PCI Express Control Register 4 in the configuration space for the PCI bridge your NIC(s) are attached to.</li>
<li>The DCA Model Specific Register on your CPU(s)</li>
</ul>
<p>Let&#8217;s take a closer look at each stage of the hack.</p>
<h2>Enable DCA in PCI Configuration Space</h2>
<p><b>PCI configuration space</b> is a memory region where control registers for PCI devices live. By changing register values, you can enable/disable specific features of that PCI device. The configuration space is addressable if you know the PCI bus, device, and function bits for a specific PCI device and the feature you care about.</p>
<p>To find the DCA register for the  Intel 5000, 5100, and 7300 chipsets, we need to consult the documentation<sup>4</sup>:</p>
<p><center><img src="http://timetobleed.com/images/dca_pci.png"/></center><br />

<p>Cool, so the register needed lives at offset 0&#215;64. To enable DCA, bit 6 needs to be set to 1.</p>
<p>Toggling these register can be a bit cumbersome, but luckily there is <code>libpci</code> which provides some simple APIs to scan for PCI devices and accessing configuration space registers.</p>
<pre class="prettyprint lang-c">
#define INTEL_BRIDGE_DCAEN_OFFSET   0x64
#define INTEL_BRIDGE_DCAEN_BIT      6
#define PCI_HEADER_TYPE_BRIDGE     1
#define PCI_VENDOR_ID_INTEL        0x8086 /* lol @ intel */
#define PCI_HEADER_TYPE             0x0e
#define MSR_P6_DCA_CAP             0x000001f8

void check_dca(struct pci_dev *dev)
{
  /* read DCA status */
  u32 dca = pci_read_long(dev, INTEL_BRIDGE_DCAEN_OFFSET);

  /* if it's not enabled */
  if (!(dca &#038; (1 << INTEL_BRIDGE_DCAEN_BIT))) {
    printf("DCA disabled, enabling now.\n");

    /* enable it */
    dca |= 1 << INTEL_BRIDGE_DCAEN_BIT;

    /* write it back */
    pci_write_long(dev, INTEL_BRIDGE_DCAEN_OFFSET, dca);
  } else {
    printf("DCA already enabled!\n");
  }
}

int main(void)
{
  struct pci_access *pacc;
  struct pci_dev *dev;
  u8 type;

  pacc = pci_alloc();
  pci_init(pacc);

  /* scan the PCI bus */
  pci_scan_bus(pacc);

  /* for each device */
  for (dev = pacc->devices; dev; dev=dev->next) {
    pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);

    /* if it's an intel device */
    if (dev->vendor_id == PCI_VENDOR_ID_INTEL) {

        /* read the header byte */
        type = pci_read_byte(dev, PCI_HEADER_TYPE);

        /* if its a PCI bridge, check and enable DCA */
        if (type == PCI_HEADER_TYPE_BRIDGE) {
          check_dca(dev);
        }
    }
  }

  msr_dca_enable();
  return 0;
}
</pre>
<h2>Enable DCA in the CPU MSR</h2>
<p>A <b>model specific register (MSR)</b> is a control register that is provided by a CPU to enable a feature that exists on a specific CPU. In this case, we care about the DCA MSR. In order to find it&#8217;s address, let&#8217;s consult the Intel Developer’s Manual 3B<sup>5</sup>.<br />
<center><img src="http://timetobleed.com/images/dca_msr.png"></center></p>
<p></p>
<p>This register lives at offset 0&#215;1f8. We just need to set it to 1 and we should be good to go.</p>
<p>Thankfully, there are device files in <code>/dev</code> for the MSRs of each CPU:</p>
<pre class="prettyprint lang-c">
#define MSR_P6_DCA_CAP      0x000001f8
void msr_dca_enable(void)
{
  char msr_file_name[64];
  int fd = 0, i = 0;
  u64 data;

  /* for each CPU */
  for (;i < NUM_CPUS; i++) {
    sprintf(msr_file_name, "/dev/cpu/%d/msr", i);

    /* open the MSR device file */
    fd = open(msr_file_name, O_RDWR);
    if (fd < 0) {
      perror("open failed!");
      exit(1);
    }

    /* read the current DCA status */
    if (pread(fd, &#038;data, sizeof(data), MSR_P6_DCA_CAP) != sizeof(data)) {
      perror("reading msr failed!");
      exit(1);
    }

    printf("got msr value: %*llx\n", 1, (unsigned long long)data);

    /* if DCA is not enabled */
    if (!(data &#038; 1)) {

      /* enable it */
      data |= 1;

      /* write it back */
      if (pwrite(fd, &#038;data, sizeof(data), MSR_P6_DCA_CAP) != sizeof(data)) {
        perror("writing msr failed!");
        exit(1);
      }
    } else {
      printf("msr already enabled for CPU %d\n", i);
    }
  }
}
</pre>
<h2>Code for the hack is on github</h2>
<p>Get it here: <a href="http://github.com/ice799/dca_force/tree/master">http://github.com/ice799/dca_force/tree/master</a></p>
<h2>Putting it all together to get your speed boost</h2>
<p>
<ol>
<li>Checkout the hack from github: <code>git clone git://github.com/ice799/dca_force.git</code></li>
<li>Build the hack: <code>make NUM_CPUS=whatever</code></li>
<li>Run it: <code>sudo ./dca_force</code></li>
<li>Load the kernel module: <code>sudo modprobe ioatdma</code></li>
<li>Check your dmesg: <code>dmesg | tail </code></li>
</ol>
<p>You should see:</p>
<p><pre>
[   72.782249] dca service started, version 1.8
[   72.838853] ioatdma 0000:00:08.0: setting latency timer to 64
[   72.838865] ioatdma 0000:00:08.0: Intel(R) I/OAT DMA Engine found, 4 channels, device version 0x12, driver version 3.64
[   72.904027]   alloc irq_desc for 56 on cpu 0 node 0
[   72.904030]   alloc kstat_irqs on cpu 0 node 0
[   72.904039] ioatdma 0000:00:08.0: irq 56 for MSI/MSI-X
</pre>
</p>
<p></p>
<p>in your dmesg.</p>
<p>You should <b>NOT SEE</b></p>
<p><pre>
[    8.367333] ioatdma 0000:00:08.0: DCA is disabled in BIOS
</pre>
</p>
<p></p>
<p>You can now enjoy the DCA performance boost your BIOS or hosting provider didn&#8217;t want you to have!</p>
<h2>Conclusion</h2>
<ul>
<li>Intel I/OAT and DCA is pretty cool, and enabling it can give pretty substantial performance wins</li>
<li>Cool features are sometimes stuffed away in the BIOS</li>
<li>If you don&#8217;t have access to your BIOS, you should ask you provider nicely to do it for you</li>
<li>If your BIOS doesn&#8217;t have a toggle switch for the feature you need, do a BIOS update</li>
<li>If all else fails and you know what you are doing, you can sometimes pull off nasty hacks like this in userland to get what you want</li>
</ul>
<p>Thanks for reading and don&#8217;t forget to <a href="http://feeds.feedburner.com/TimeToBleed" rel="alternate" type="application/rss+xml">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<h2>P.S.</h2>
<p>I know, I know. I skipped Part 2 of the signals post (<a href="http://timetobleed.com/a-few-things-you-didnt-know-about-signals-in-linux-part-1/">here&#8217;s Part 1</a> if you missed it). Part 2 is coming soon!</p>
<h2>References</h2>
<ol class="footnotes"><li id="footnote_0_888" class="footnote"><a href="http://www.linuxfoundation.org/en/Net:I/OAT">http://www.linuxfoundation.org/en/Net:I/OAT</a></li><li id="footnote_1_888" class="footnote"><a href="http://www.linuxfoundation.org/en/Net:I/OAT">http://www.linuxfoundation.org/en/Net:I/OAT</a></li><li id="footnote_2_888" class="footnote"><a href="http://www.myri.com/serve/cache/626.html">http://www.myri.com/serve/cache/626.html</a></li><li id="footnote_3_888" class="footnote"><a href="www.intel.com/assets/pdf/designguide/318086.pdf">Intel® 7300 Chipset Memory Controller Hub (MCH) Datasheet, Section 4.8.12.6</a></li><li id="footnote_4_888" class="footnote"><a href="http://www.intel.com/Assets/PDF/manual/253669.pdf">Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3B: System Programming Guide, Part 2, Appendix B-19</a></li></ol><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=rhoq-JbJa2Q:CYa7HlFN7c4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=rhoq-JbJa2Q:CYa7HlFN7c4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=rhoq-JbJa2Q:CYa7HlFN7c4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=rhoq-JbJa2Q:CYa7HlFN7c4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=rhoq-JbJa2Q:CYa7HlFN7c4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=rhoq-JbJa2Q:CYa7HlFN7c4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=rhoq-JbJa2Q:CYa7HlFN7c4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=rhoq-JbJa2Q:CYa7HlFN7c4:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/rhoq-JbJa2Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/enabling-bios-options-on-a-live-server-with-no-rebooting/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A Few Things You Didn’t Know about Signals in Linux Part 1</title>
		<link>http://timetobleed.com/a-few-things-you-didnt-know-about-signals-in-linux-part-1/</link>
		<comments>http://timetobleed.com/a-few-things-you-didnt-know-about-signals-in-linux-part-1/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 11:00:41 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[linux]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[debug]]></category>

		<category><![CDATA[kernel]]></category>

		<category><![CDATA[signal handling]]></category>

		<category><![CDATA[x86_64]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=783</guid>
		<description><![CDATA[
Another post about signal handling?
There are probably lots of people who have blogged about signal handling in Linux, but this series is going to be different. In this blog post, I&#8217;m going to unravel the signal handling code paths in the Linux kernel starting at the hardware level, working though the kernel, and ending in [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/signals.jpg" alt="" /></center></p>
<h2>Another post about signal handling?</h2>
<p>There are probably lots of people who have blogged about signal handling in Linux, but this series is going <strong>to be different</strong>. In this blog post, I&#8217;m going to unravel the signal handling code paths in the Linux kernel <strong>starting at the hardware level, working though the kernel, and ending in the userland signal handler</strong>. I&#8217;ve tried to use footnotes for code samples which have links to the code in the Linux lxr. Many of the code examples have been snipped for brevity.</p>
<p>
As always, this post is specific to the x86_64 CPU architecture and Linux kernel 2.6.29.</p>
<h2>Hardware or software generated</h2>
<p>Signals are not generated directly by hardware, but certain hardware states can cause the Linux kernel to generate signals. As such we can imagine two ways to generate signals:</p>
<ol>
<li>Hardware - the CPU does something bad (divides by 0, touches a bad address, etc) which causes the kernel to create and deliver (unless the signal is <code>SIGKILL</code> or <code>SIGSTOP</code>, of course) a signal (<code>SIGFPE</code>, <code>SIGSEGV</code>, etc) to the running process.</li>
<li>Software - an application executes a <code>kill()</code> system call and sends a signal to a specific process.</li>
</ol>
<p>Both types of signals share a common code path, but hardware generated signals have a very interesting birth. Let&#8217;s start there and as we work our way up to userland we&#8217;ll stumble into the software signal code path along the way.</p>
<h2>Exceptions on the x86</h2>
<p>Let&#8217;s start by first understanding what an x86 exception is. For that, we&#8217;ll turn to the documentation<sup>1</sup>:</p>
<blockquote><p>[...] exceptions are events that indicate that a condition exists somewhere in the system, the processor, or within the currently executing program or task that requires the attention of a processor. They typically result in a forced transfer of execution from the currently running program or task to a special software routine [...] or an exception handler.</p></blockquote>
<p>At a high level this is pretty simple to understand; the system gets in a <em>weird</em> state and the CPU immediately begins executing a predefined handler function to try to fix things (if it can) or die gracefully.</p>
<p>Let&#8217;s take a look at how the kernel creates and installs handler functions that the CPU executes when an exception occurs.</p>
<h2>Low-level exception handlers</h2>
<p>Low level exception handlers are specified in the Interrupt Descriptor Table (IDT). The IDT can hold up to 256 entries and it can live anywhere in memory. Each entry in the IDT is mapped to a different exception. For example, <code>#DE Divide Error</code> is the first entry in the IDT, <code>IDT[0]</code>; <code>#PF Page Fault</code> &#8217;s handler lives at <code>IDT[14]</code>. When a specific exception is encountered, the CPU looks up the handler function in the IDT, puts some data on the stack, and executes the handler.</p>
<p>What does an entry in the IDT look like? Let&#8217;s take a look at a picture<sup>2</sup> from Intel:</p>
<p><center><img src="http://timetobleed.com/images/idt.png" alt="" /></center><br />
</p>
<p>Take a look at the fields labeled &#8216;Offset&#8217; - this is field that contains the address of the function to execute. As you can see, there are three fields labeled &#8216;Offset.&#8217; Can you guess why?</p>
<p>In order to actually set the address of the function you want to execute, you&#8217;ll need to do some bit-shifting. Each &#8216;Offset&#8217; field is indicates which bits of the address of the handler function it wants. You need to be <em>really careful</em> when writing the code that is responsible for creating IDT entries. A bug here could cause your system to do really bizarre things.</p>
<p>We know what an IDT entry looks like, but what about the data that the CPU pushes on the stack before executing a handler? Unfortunately, I couldn&#8217;t track down a picture of what the x86_64 puts on the stack and I can&#8217;t draw. So, here is a picture of the data the x86 CPU puts on the stack from Intel<sup>3</sup>:</p>
<p><center><img src="http://timetobleed.com/images/exception_stack.png" height=300 width=550/></center></p>
<p>When an exception occurs, the CPU pushes the stack pointer, the CPU flags register value, the code and stack segment selectors, and the instruction pointer on to the stack before executing the handler.</p>
<p>Nice, but where does the IDT itself live?</p>
<p>The address of the IDT is stored in a CPU register that can be accessed with the instructions <code>lidt</code> and <code>sidt</code> to load and store (respectively) the address of the IDT. Usually, the address of the IDT is set during the initialization of the kernel.</p>
<p>Let&#8217;s see where this happens in Linux<sup>4</sup>:</p>
<pre class="prettyprint">void __init x86_64_start_kernel(char * real_mode_data)
{
        int i;

        /* [...] */

        for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
                set_intr_gate(i, early_idt_handler);
        }

        load_idt((const struct desc_ptr *)&#038;idt_descr);

	/* [...] */
}</pre>
<p>
<p>
Cool, so Linux creates a bunch of early handlers in case something goes bad during boot and then a few function calls later (not shown), Linux calls <code>start_kernel()</code><sup>5</sup>, which calls <code>trap_init()</code><sup>6</sup>  for your architecture which <em>actually</em> sets the handlers.</p>
<p>This is pretty important, so let&#8217;s take a look at the code for this. Thankfully, Linux includes some descriptive function names, so we can see which exceptions are being set.</p>
<pre class="prettyprint">void __init trap_init(void)
{
   /* ... */

	set_intr_gate(0, &#038;divide_error);

	/* ... */

        set_intr_gate(5, &#038;bounds);
        set_intr_gate(6, &#038;invalid_op);
        set_intr_gate(7, &#038;device_not_available);

	/* ... */

        set_intr_gate(13, &#038;general_protection);
 	set_intr_gate(14, &#038;page_fault);
 	set_intr_gate(15, &#038;spurious_interrupt_bug);
 	set_intr_gate(16, &#038;coprocessor_error);
 	set_intr_gate(17, &#038;alignment_check);

   /* ... */
}</pre>
<p></p>
<p>Awesome, now let&#8217;s try to track down where these exception handlers are defined. As it turns out, there is a little bit of C and assembly magic to string this all together.</p>
<p>The low-level exception handlers have a common entry and exit point and are &#8220;templated&#8221; with a macro. Let&#8217;s take a look at the macro<sup>7</sup> and some of the handlers<sup>8</sup> in the kernel:</p>
<pre class="prettyprint">.macro zeroentry sym do_sym
ENTRY(\sym)
        INTR_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $15*8,%rsp
        call error_entry
        DEFAULT_FRAME 0
        movq %rsp,%rdi          /* pt_regs pointer */
        xorl %esi,%esi          /* no error code */
        call \do_sym
        jmp error_exit          /* %ebx: no swapgs flag */
 ND(\sym)
.endm</pre>
<p></p>
<p>So the macro uses the first argument <code>sym</code> as the name of the function, and the second argument <code>do_sym</code> is a C function that is called from this assembly stub.</p>
<p>We also notice from the stub above a very important (and somewhat subtle) piece of code: <code>movq %rsp,%rdi</code> This piece of code puts the address of the stack pointer in <code>%rdi</code> and we&#8217;ll see why shortly. First, let&#8217;s look at how the macro is used to get a better idea how it works:</p>
<pre class="prettyprint">zeroentry divide_error do_divide_error
zeroentry overflow do_overflow
zeroentry bounds do_bounds
zeroentry invalid_op do_invalid_op
zeroentry device_not_available do_device_not_available</pre>
<p></p>
<p>This block of code uses the macro above to create symbols named <code>divide_error</code>, <code>overflow</code>, and more which call out to C functions named <code>do_divide_error</code>, <code>do_overflow</code>, etc. The craziness doesn&#8217;t end there. These C functions are also generated with macros<sup>9</sup>: </p>
<pre class="prettyprint">#define DO_ERROR(trapnr, signr, str, name)                              \
dotraplinkage void do_##name(struct pt_regs *regs, long error_code)     \
{                                                                       \
        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
                                                        == NOTIFY_STOP) \
                return;                                                 \
        conditional_sti(regs);                                          \
        do_trap(trapnr, signr, str, regs, error_code, NULL);            \
}
/*...*/
DO_ERROR(4, SIGSEGV, "overflow", overflow)
DO_ERROR(5, SIGSEGV, "bounds", bounds)</pre>
<p></p>
<p>Those last two lines get substituted with the macro above, creating <code>do_overflow</code>, <code>do_bounds</code>, and more. As you might have noticed, the functions generated have <code>dotraplinkage</code> which is a macro for a gcc attribute <code>regparm</code> which tells gcc to pass arguments to the function in registers and <b>not on the stack</b>.</p>
<p>Remember the <code>movq %rsp,%rdi</code> from the common assembly stub? That line of code exists to pass the address of the state the CPU dumped to the <code>do_*</code> functions via the <code>%rdi</code> register.
</p>
<p>The <code>do_*</code> functions notify interested parties about the exception, re-enable interrupts/exceptions if they were disabled, and finally tells the upper layer signal handling code of the kernel that a signal should be generated and hands over the associated CPU state at the time the exception was generated.</p>
<h2>Conclusion for Part 1</h2>
<p>Wow. What a <i>wild ride</i> that was. </p>
<ol>
<li>There is a lot of trickery and subtle hacks in the Linux kernel. Reading and understanding the code can make you a more clever programmer. Dig in!</li>
<li>It is pretty cool (imho) to understand how you actually converse with the CPU and how the CPU talks to the kernel, and how that data is pushed to the upper layers.</li>
<li>The Intel CPU manuals, the gcc man page, and the Linux lxr are a big time help for deciphering this code, which can be cryptic at times.</li>
<li><b>Understanding what information you have at your disposal can let you do pretty crazy things in userland, as we&#8217;ll see in the next piece of this series.</b></li>
</ol>
<p>
Stay tuned, in the next piece of this series I&#8217;ll walk through the signal handling code in the kernel and show some crazy non-portable tricks you can do in userland.</p>
<p>Thanks for reading and don&#8217;t forget to <a href="http://feeds.feedburner.com/TimeToBleed" rel="alternate" type="application/rss+xml">subscribe (via RSS or e-mail)</a> and <a href="http://twitter.com/joedamato">follow me on twitter.</a></p>
<h2>References</h2>
<ol class="footnotes"><li id="footnote_0_783" class="footnote"><a href="http://www.intel.com/Assets/PDF/manual/253668.pdf ">Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1, 5.1: Interrupt and Exception Overview</a></li><li id="footnote_1_783" class="footnote"><a href="http://www.intel.com/Assets/PDF/manual/253668.pdf ">Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1, 5.1: Interrupt and Exception Overview</a></li><li id="footnote_2_783" class="footnote"><a href="http://www.intel.com/Assets/PDF/manual/253668.pdf ">Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1, 5.12.1.1: Exception- or Interrupt-Handler Procedures</a></li><li id="footnote_3_783" class="footnote"><a href="http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/head64.c#L89">http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/head64.c#L89</a></li><li id="footnote_4_783" class="footnote"><a href="http://lxr.linux.no/linux+v2.6.29/init/main.c#L590">http://lxr.linux.no/linux+v2.6.29/init/main.c#L590</a></li><li id="footnote_5_783" class="footnote"><a href="http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/traps.c#L953">http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/traps.c#L953</a></li><li id="footnote_6_783" class="footnote"><a href="http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/entry_64.S#L1028">http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/entry_64.S#L1028</a></li><li id="footnote_7_783" class="footnote"><a href="http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/entry_64.S#L1121">http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/entry_64.S#L1121</a></li><li id="footnote_8_783" class="footnote"><a href="http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/traps.c#L236">http://lxr.linux.no/linux+v2.6.29/arch/x86/kernel/traps.c#L236</a></li></ol><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=I13_JrJuqk4:hyP1VX6eBFg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=I13_JrJuqk4:hyP1VX6eBFg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=I13_JrJuqk4:hyP1VX6eBFg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=I13_JrJuqk4:hyP1VX6eBFg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=I13_JrJuqk4:hyP1VX6eBFg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=I13_JrJuqk4:hyP1VX6eBFg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=I13_JrJuqk4:hyP1VX6eBFg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=I13_JrJuqk4:hyP1VX6eBFg:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/I13_JrJuqk4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/a-few-things-you-didnt-know-about-signals-in-linux-part-1/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Fixing Threads in Ruby 1.8: A 2-10x performance boost</title>
		<link>http://timetobleed.com/fixing-threads-in-ruby-18-a-2-10x-performance-boost/</link>
		<comments>http://timetobleed.com/fixing-threads-in-ruby-18-a-2-10x-performance-boost/#comments</comments>
		<pubDate>Mon, 18 May 2009 10:00:50 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[bugfix]]></category>

		<category><![CDATA[debugging]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[scaling]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[fibers]]></category>

		<category><![CDATA[kernel]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[patch]]></category>

		<category><![CDATA[patches]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[threading]]></category>

		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=685</guid>
		<description><![CDATA[
Quick notes before things get crazy
OK, things might get a little crazy in this blog post so let&#8217;s clear a few things up before we get moving.

I like the gritty details, and this article in particular has a lot of gritty info. To reduce the length of the article for the casual reader, I&#8217;ve put [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/ruby-threads.jpg" alt="" width="400" height="300" /></center></p>
<h2>Quick notes before things get crazy</h2>
<p>OK, things might get a little crazy in this blog post so let&#8217;s clear a few things up before we get moving.</p>
<ul>
<li>I like the gritty details, and this article in particular has a lot of gritty info. To reduce the length of the article for the casual reader, I&#8217;ve put a portion of the really gritty stuff in the Epilogue below. Definitely check it out if that is your thing.</li>
<li>This article, the code, and the patches below are for Linux and OSX for the x86 and x86_64 platforms, only.</li>
<li>Even though there are code paths for both x86 and x86_64, I&#8217;m going to use the 64bit register names and (briefly) mention the 64bit binary interface.</li>
<li>Let&#8217;s assume the binary is built with -fno-omit-frame-pointer, the patches don&#8217;t care, but it&#8217;ll make the explanation a bit simpler later.</li>
<li>If you don&#8217;t know what the above two things mean, don&#8217;t worry; I got your back chief.</li>
</ul>
<h2>How threads work in Ruby</h2>
<p>Ruby 1.8 implements pre-emptible userland threads, also known as &#8220;green threads.&#8221; (Want to know more about threading models? See <a href="http://timetobleed.com/threading-models-so-many-different-ways-to-get-stuff-done/">this post</a>.) The major performance killer in Ruby&#8217;s implementation of green threads is that the <strong>entire thread stack is copied</strong> to and from the heap <strong>every context switch</strong>. Let&#8217;s take a look at a high level what happens when you:</p>
<pre class="prettyprint lang-rb">Thread.new{
	10000.times {
		a &lt;&lt; "a"
		a.pop
	}
}</pre>
<p>

<ol>
<li>A thread control block (tcb) is allocated in Ruby.</li>
<li>The infamous thread timer is initialized, either as a pthread or as an itimer.</li>
<li>Ruby scope information is copied to the heap.</li>
<li>The new thread is added to the list of threads.</li>
<li>The current thread is set as the new thread.</li>
<li>rb_thread_yield is called to yield to the block you passed in.</li>
<li>Your block starts executing.</li>
<li>The timer interrupts the executing thread.</li>
<li>The current thread&#8217;s state is stored:
<ul>
<li><code>memcpy()</code> #1 (sometimes): If the stack has grown since the last save, <code>realloc</code> is called. If the allocator cannot extend the size of the current block in place, it may decide to move the data to a new block that is large enough. If that happens <code>memcpy()</code> is called to move the data over.</li>
<li><code>memcpy()</code> #2 (always): A copy of this thread&#8217;s <strong>entire stack</strong> (starting from the top of the interpreter&#8217;s stack) is put on the heap.</li>
</ul>
</li>
<li>The next thread&#8217;s state is restored.
<ul>
<li><code>memcpy()</code> #3 (always): A copy of this thread&#8217;s <strong>entire stack</strong> is placed on the stack.</li>
</ul>
</li>
</ol>
<p>Steps 9 and 10 <strong>crush performance</strong> when even small amounts of Ruby code are executed.</p>
<p>Many of the functions the interpreter uses to evaluate code are <em>massive</em>. They allocate a large number of local variables creating stack frames up to <strong>4 kilobytes</strong> per function call. Those functions also call themselves recursively many times in a single expression. This leads to huge stacks, huge <code>memcpy()s</code>, and an incredible performance penalty.</p>
<p>If we can eliminate the <code>memcpy()s</code> we can get a lot of performance back. So, let&#8217;s do it.</p>
<h2>Increase performance by putting thread stacks on the heap</h2>
<p><strong>[Remember: we are only talking about x86_64]</strong></p>
<h3>How stacks work - a refresher</h3>
<p>Stacks grow <strong>downward</strong> from high addresses to low addresses. As data is <code>push</code>ed on to the stack, it grows downward. As stuff is <code>pop</code>ped, it shrinks upward. The register <code>%rsp</code> serves as a pointer to the bottom of the stack. When it is decremented or incremented the stack grows or shrinks, respectively. The <strong>special property</strong> of the program stack is that <strong>it will grow</strong> until you run out of memory (or are killed by the OS for being bad). The operating system handles the automatic growth. See the Epilogue for some more information about this.</p>
<h3>How to actually switch stacks</h3>
<p>The <code>%rsp</code> register can be (and is) changed and adjusted directly by user code. So all we have to do is put the address of our stack in <code>%rsp</code>, and we&#8217;ve switched stacks. Then we can just call our thread start function. Pretty easy. A small blob of inline assembly should do the trick:</p>
<pre class="prettyprint lang-c">__asm__ __volatile__ ("movq %0, %%rsp\n\t"
                      "callq *%1\n"
                      :: "r" (th-&gt;stk_base),
                         "r" (rb_thread_start_2));</pre>
<p>
<p>
Two instructions, not too bad.</p>
<ol>
<li><code>movq %0, %%rsp</code> moves a quad-word (th-&gt;stk_base) into the %rsp. <em>Quad-word</em> is Intel speak for 4 words, where 1 Intel word is 2 bytes.</li>
<li><code>callq *%1</code> calls a function at the address &#8220;rb_thread_start_2.&#8221; This has a side-effect or two, which I&#8217;ll mention in the Epilogue below, for those interested in a few more details.</li>
</ol>
<p>The above code is called <em>once per thread</em>. Calling <code>rb_thread_start_2</code> spins up your thread and it never returns.</p>
<h3>Where do we get stack space from?</h3>
<p>When the tcb is created, we&#8217;ll allocate some space with <code>mmap</code> and set a pointer to it.</p>
<pre class="prettyprint lang-c">/* error checking omitted for brevity, but exists in the patch =] */
stack_area = mmap(NULL, total_size, PROT_READ | PROT_WRITE | PROT_EXEC,
			MAP_PRIVATE | MAP_ANON, -1, 0);

th-&gt;stk_ptr = th-&gt;stk_pos = stack_area;
th-&gt;stk_base = th-&gt;stk_ptr + (total_size - sizeof(int))/sizeof(VALUE *);</pre>
<p>
<p>
Remember, stacks <strong>grow downward</strong> so that last line: <code>th-&gt;stk_base = ... </code> is necessary because the base of the stack is actually at the <em>top</em> of the memory region return by <code>mmap()</code>. The ugly math in there is for alignment, to comply with the x86_64 binary interface. Those curious about more gritty details should see the Epilogue below.</p>
<p><strong>BUT WAIT, I thought stacks were supposed to grow automatically?</strong></p>
<p>Yeah, the OS does that for the normal program stack. Not gonna happen for our <code>mmap</code>&#8216;d regions. The best we can do is pick a good default size and export a tuning lever so that advanced users can adjust the stack size as they see fit.</p>
<p><strong>BUT WAIT, isn&#8217;t that dangerous? If you fall off your stack, wouldn&#8217;t you just overwrite memory below?</strong></p>
<p>Yep, but there is a fix for that too. It&#8217;s called a guard page. We&#8217;ll create a guard page below each stack that has its permission bits set to <code>PROT_NONE</code>. This means, if a thread falls off the bottom of its stack and tries to read, write, or execute the memory below the thread stack, a signal (usually <code>SIGSEGV</code> or <code>SIGBUS</code>) will be sent to the process.</p>
<p>The code for the guard page is pretty simple, too:</p>
<pre class="prettyprint lang-c">/* omit error checking for brevity */
mprotect(th-&gt;stk_ptr, getpagesize(), PROT_NONE);</pre>
<p>
<p>
Cool, let&#8217;s modify the SIGSEGV and SIGBUS signal handlers to check for stack overflow:</p>
<pre class="prettyprint lang-c">/* if the address which generated the fault is within the current thread's guard page... */
  if(fault_addr &lt;= (caddr_t)rb_curr_thread-&gt;guard &#038;&#038;
     fault_addr &gt;= (caddr_t)rb_curr_thread-&gt;stk_ptr) {
  /* we hit the guard page, print out a warning to help app developers */
  rb_bug("Thread stack overflow! Try increasing it!");
}</pre>
<p>
<p>
See the epilogue for more details about this signal handler trick.</p>
<h2>Patches</h2>
<p><strong>As always, this is super-alpha software.</strong></p>
<table style="height: 60px;" border="0" cellspacing="1" cellpadding="1" width="300" summary="”&quot;">
<tbody>
<tr>
<td>Ruby 1.8.6</td>
<td><a href="http://github.com/ice799/matzruby/tree/heap_stacks_186">github</a></td>
<td><a href="http://timetobleed.com/files/186-hs.patch">raw .patch</a></td>
</tr>
<tr>
<td>Ruby 1.8.7</td>
<td><a href="http://github.com/ice799/matzruby/tree/heap_stacks">github</a></td>
<td><a href="http://timetobleed.com/files/187-hs.patch">raw .patch</a></td>
</tr>
</tbody>
</table>
<h2>Benchmarks</h2>
<p>The <a href="http://shootout.alioth.debian.org/">computer language shootout</a> has a thread test called thread-ring; let&#8217;s start with that.</p>
<pre class="prettyprint lang-rb">require 'thread'
THREAD_NUM = 403
number = ARGV.first.to_i

threads = []
for i in 1..THREAD_NUM
   threads &lt;&lt; Thread.new(i) do |thr_num|
      while true
         Thread.stop
         if number &gt; 0
            number -= 1
         else
            puts thr_num
            exit 0
         end
      end
   end
end

prev_thread = threads.last
while true
   for thread in threads
      Thread.pass until prev_thread.stop?
      thread.run
      prev_thread = thread
   end
end</pre>
<p>
<p>
Results (ARGV[0] = 50000000):</p>
<table style="height: 60px;" border="0" cellspacing="1" cellpadding="1" width="300" summary="”&quot;">
<tbody>
<tr>
<td>Ruby 1.8.6</td>
<td>1389.52s</td>
</tr>
<tr>
<td>Ruby 1.8.6 w/ heap stacks</td>
<td>793.06s</td>
</tr>
<tr>
<td>Ruby 1.9.1</td>
<td>752.44s</td>
</tr>
</tbody>
</table>
<p>
<p>
A <strong>speed up of about 2.3x</strong> compared to Ruby 1.8.6. A bit slower than Ruby 1.9.1.
</p>
<p>
<p>
That is a pretty strong showing, for sure. Let&#8217;s modify the test slightly to illustrate the true power of this implementation.</p>
<p>
<p>Since our implementation does no <code>memcpy</code>()s we <i>expect</i> the cost of context switching to stay constant regardless of thread stack size. Moreover, the unmodified Ruby 1.8.6 should perform worse as thread stack size increases (therefore increasing the amount of time the CPU is doing <code>memcpy</code>()s).</p>
<p>
<p>Let&#8217;s <b>test this hypothesis</b> by modifying thread-ring slightly so that it increases the size of the stack after spawning threads.</p>
<pre class="prettyprint lang-rb">def grow_stack n=0, &#038;blk
  unless n &gt; 100
    grow_stack n+1, &#038;blk
  else
    yield
  end
end

require 'thread'
THREAD_NUM = 403
number = ARGV.first.to_i

threads = []
for i in 1..THREAD_NUM
  threads &lt;&lt; Thread.new(i) do |thr_num|
    grow_stack do
      while true
        Thread.stop
        if number &gt; 0
          number -= 1
        else
          puts thr_num
          exit 0
        end
      end
    end
  end
end

prev_thread = threads.last
while true
   for thread in threads
      Thread.pass until prev_thread.stop?
      thread.run
      prev_thread = thread
   end
end</pre>
<p>
<p>
Results (ARGV[0] = 50000000):</p>
<table style="height: 60px;" border="0" cellspacing="1" cellpadding="1" width="300" summary="”&quot;">
<tbody>
<tr>
<td>Ruby 1.8.6</td>
<td>7493.50s</td>
</tr>
<tr>
<td>Ruby 1.8.6 w/ heap stacks</td>
<td>799.52s</td>
</tr>
<tr>
<td>Ruby 1.9.1</td>
<td>680.92s</td>
</tr>
</tbody>
</table>
<p>
<p>
A <strong>speed up of about 9.4x</strong> compared to Ruby 1.8.6. A bit slower than Ruby 1.9.1.</p>
<p>Now, lets benchmark mongrel+sinatra.</p>
<pre class="prettyprint lang-rb">
require 'rubygems'
require 'sinatra'

disable :reload

set :server, 'mongrel' 

get '/' do
  'hi'
end
</pre>
<p>
<p>
Results:</p>
<table style="height: 60px;" border="0" cellspacing="1" cellpadding="1" width="400" summary="”&quot;">
<tbody>
<tr>
<td>Ruby 1.8.6</td>
<td>1395.43 request/sec</td>
</tr>
<tr>
<td>Ruby 1.8.6 w/ heap stacks</td>
<td>1770.26 request/sec</td>
</tr>
</tbody>
</table>
<p>
<p>
An <b>increase of about 1.26x</b> in the <i>most naive case possible</i>.</p>
<p>
<p> Of course, if the handler did anything more than simply write &#8220;hi&#8221; (like use memcache or make sql queries) there would be more function calls, more context switches, and <b>a much greater savings.</b></p>
<h2>Conclusion</h2>
<p>A couple lessons learned this time:</p>
<ul>
<li>Hacking a VM like Ruby is kind of like hacking a kernel. Some subset of the tricks used in kernel hacking are useful in userland.</li>
<li>The x86_64 ABI is a <em>must read</em> if you plan on doing any low-level hacking.</li>
<li>Keep your CPU manuals close by, they come in handy even in userland.</li>
<li>Installing your own signal handlers is really useful for debugging, even if they are dumping architecture specific information.</li>
</ul>
<p>Hope everyone enjoyed this blog post. I&#8217;m always looking for things to blog about. If there is something you want explained or talked about, send me an email or a tweet!</p>
<p>Don&#8217;t forget to <a href="http://feeds.feedburner.com/TimeToBleed">subscribe</a> and <a href="http://twitter.com/joedamato">follow me</a> and <a href="http://twitter.com/tmm1">Aman</a> on twitter.</p>
<h2>Epilogue</h2>
<h3>Automatic stack growth</h3>
<p>This can be achieved pretty easily with a little help from virtual memory and the programmable interrupt controller (PIC). The idea is pretty simple. When you (or your shell on your behalf) calls <code>exec()</code> to execute a binary, the OS will map a bunch of pages of memory for the stack and set the stack pointer of the process to the top of the memory. Once the stack space is exhausted, and the stack pointer is <code>push</code>ed onto un-mapped memory, a page fault will be generated.</p>
<p>The OS&#8217;s page fault handler (installed via the PIC) will fire. The OS can then check the address that generated the exception and see that you fell off the bottom of your stack. This works very similarly to the guard page idea we added to protect Ruby thread stacks. It can then just map more memory to that area, and tell your process to continue executing. Your process doesn&#8217;t know anything bad happened.</p>
<p>I hope to chat a little bit about interrupt and exception handlers in an upcoming blog post. Stay tuned!</p>
<h3><code>callq</code> side-effects</h3>
<p>When a <code>callq</code> instruction is executed, the CPU pushes the return address on to the stack and then begins executing the function that was called. This is important because when the function you are calling executes a <code>ret</code> instruction, a quad-word is popped from the stack and put into the instruction pointer (<code>%rip</code>).</p>
<h3>x86_64 Application Binary Interface</h3>
<p>The x86_64 ABI is an extension of the x86 ABI. It specifies architecture programming information such as the fundamental types, caller and callee saved registers, alignment considerations and more. It is a really important document for any programmer messing with x86_64 architecture specific code.<br />
The particular piece of information relevant for this blog post is found buried in section 3.2.2</p>
<blockquote><p>The end of the input argument area shall be aligned on a 16 &#8230; byte boundary.</p></blockquote>
<p>This is important to keep in mind when constructing thread stacks. We decided to avoid messing with alignment issues. As such we did not pass any arguments to rb_thread_start_2. We wanted to avoid mathematical error that could happen if we try to align the memory ourselves after pushing some data. We also wanted to avoid writing more assembly than we had to, so we avoided passing the arguments in registers, too.</p>
<h3>Signal handler trick</h3>
<p>The signal handler &#8220;trick&#8221; to check if you have hit the guard page is made possible by the <code>sigaltstack()</code> system call and the POSIX <code>sa_sigaction</code> interface.</p>
<p><code>sigaltstack()</code> lets us specify a memory region to be used as the stack when a signal is delivered. This extremely important for the signal handler trick because once we fall off our thread stack, we certainly cannot expect to handle a signal using that stack space.</p>
<p>POSIX provides two ways for signals to be handled:</p>
<ul>
<li>sa_handler interface: calls your handler and passes in the signal number.</li>
<li>sa_sigaction interface: calls your handler and passes in the signal number, a <code>siginfo_t</code> struct, and a <code>ucontext_t</code>. The <code>siginfo_t</code> struct contains (among other things), the address which generated the fault. Simply check this address to see if its in the guard page and if so let the user know they just overflowed their stack. Another useful, but <em>extremely non-portable</em> modification that was added to Ruby&#8217; signal handlers was a dump of the contents in <code>ucontext_t</code> to provide useful debugging information. This structure contains the register state at the time of signal. Dumping it can help debugging by showing which values are in what registers.</li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=pRfrLZilKxg:LLrf1btisBI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=pRfrLZilKxg:LLrf1btisBI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=pRfrLZilKxg:LLrf1btisBI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=pRfrLZilKxg:LLrf1btisBI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=pRfrLZilKxg:LLrf1btisBI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=pRfrLZilKxg:LLrf1btisBI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=pRfrLZilKxg:LLrf1btisBI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=pRfrLZilKxg:LLrf1btisBI:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/pRfrLZilKxg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/fixing-threads-in-ruby-18-a-2-10x-performance-boost/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Fix a bug in Ruby’s configure.in and get a ~30% performance boost.</title>
		<link>http://timetobleed.com/fix-a-bug-in-rubys-configurein-and-get-a-30-performance-boost/</link>
		<comments>http://timetobleed.com/fix-a-bug-in-rubys-configurein-and-get-a-30-performance-boost/#comments</comments>
		<pubDate>Tue, 05 May 2009 08:20:29 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[bugfix]]></category>

		<category><![CDATA[debugging]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[monitoring]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[scaling]]></category>

		<category><![CDATA[testing]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[debug]]></category>

		<category><![CDATA[kernel]]></category>

		<category><![CDATA[patch]]></category>

		<category><![CDATA[patches]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[strace]]></category>

		<category><![CDATA[syscall]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[threading]]></category>

		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=615</guid>
		<description><![CDATA[


Special thanks&#8230;
Going out to Jake Douglas for pushing the initial investigation and getting the ball rolling.
The whole --enable-pthread thing
Ask any Ruby hacker how to easily increase performance in a threaded Ruby application and they&#8217;ll probably tell you:

Yo dude&#8230; Everyone knows you need to configure Ruby with --disable-pthread.

And it&#8217;s true; configure Ruby with --disable-pthread and you [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/ruby_bug.jpg"/></center><br />
</p>
<p>
<h2>Special thanks&#8230;</h2>
<p>Going out to <a href="http://twitter.com/jakedouglas">Jake Douglas</a> for pushing the initial investigation and getting the ball rolling.</p>
<p><h2>The whole <code>--enable-pthread</code> thing</h2>
<p>Ask any Ruby hacker how to easily increase performance in a threaded Ruby application and they&#8217;ll probably tell you:<br />
<b><br />
Yo dude&#8230; <i>Everyone</i> knows you need to <code>configure</code> Ruby with <code>--disable-pthread</code>.<br />
</b><br />
And it&#8217;s true; <code>configure</code> Ruby with <code>--disable-pthread</code> and you get a ~30% performance boost. But&#8230; <b><i>why?</i></b></p>
<p> For this, we&#8217;ll have to turn to our handy tool <a href="http://timetobleed.com/hello-world/">strace</a>. We&#8217;ll also need a simple Ruby program to this one. How about something like this:</p>
<p>
<pre class="prettyprint lang-rb">
def make_thread
  Thread.new {
    a = []
    10_000_000.times {
      a << "a"
      a.pop
    }
  }
end

t = make_thread
t1 = make_thread 

t.join
t1.join</pre>
<p></p>
<p>Now, let&#8217;s run <code>strace</code> on a version of Ruby <code>configure</code>&#8216;d with <code>--enable-pthread</code> and point it at our test script. The output from <code>strace</code> looks like this:</p>
<p>
<pre class="prettyprint lang-c">
22:46:16.706136 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706177 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706218 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706259 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000005>
22:46:16.706301 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706342 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706383 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706425 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004>
22:46:16.706466 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000004></pre>
<p></p>
<p><b>Pages and pages and pages</b> of sigprocmask system calls (Actually, running with <code>strace -c</code>, I get about <b>20,054,180</b> calls to <code>sigprocmask</code>, <b>WOW</b>). Running the <i>same test script</i> against a Ruby built with <code>--disable-pthread</code> and the output does <b>not</b> have pages and pages of <code>sigprocmask</code> calls (only <b>3</b> times, a <b>HUGE</b> reduction).
</p>
<p><h2>OK, so let&#8217;s just set a breakpoint in GDB&#8230; right?</h2>
<p>OK, so we should just be able to set a <code>breakpoint</code> on <code>sigprocmask</code> and figure out who is calling it.</p>
<p><b>Well, not exactly.</b> You can try it, but the breakpoint <b>won&#8217;t trigger</b> (we&#8217;ll see why a little bit later).</p>
<p>Hrm, that kinda sucks and is confusing. This will make it harder to track down who is calling <code>sigprocmask</code> in the threaded case.</p>
<p> Well, we know that when you run <code>configure</code> the script creates a <code>config.h</code> with a bunch of <code>define</code>s that Ruby uses to decide which functions to use for what. So let&#8217;s compare <code>./configure --enable-pthread</code> with <code>./configure --disable-pthread</code>:</p>
<pre class="prettyprint lang-bsh">
[joe@mawu:/home/joe/ruby]% diff config.h config.h.pthread
> #define _REENTRANT 1
> #define _THREAD_SAFE 1
> #define HAVE_LIBPTHREAD 1
> #define HAVE_NANOSLEEP 1
> #define HAVE_GETCONTEXT 1
> #define HAVE_SETCONTEXT 1</pre>
</p>
<p>
<br />
OK, now if we <code>grep</code> the Ruby source code, we see that whenever <code>HAVE_[SG]ETCONTEXT</code> are set, Ruby uses the system calls <code>setcontext()</code> and <code>getcontext()</code> to save and restore state for context switching and for exception handling (via the <code>EXEC_TAG</code>). </p>
<p>What about when <code>HAVE_[SG]ETCONTEXT</code> are <b>not</b> <code>define</code>&#8216;d? Well in that case, Ruby uses <code>_setjmp/_longjmp</code>.</p>
<p><b>Bingo!</b></p>
<p>That&#8217;s what&#8217;s going on! From the <code>_setjmp/_longjmp</code> man page:</p>
<blockquote><p>&#8230; The _longjmp()  and  _setjmp()  functions  shall  be  equivalent  to  longjmp() and setjmp(), respectively, with the additional restriction that _longjmp() and _setjmp() shall not manipulate the signal mask&#8230;</p></blockquote>
<p>And from the <code>[sg]etcontext</code> man page:</p>
<blockquote><p>&#8230; uc_sigmask is the set of signals blocked in this context (see sigprocmask(2)) &#8230;</p></blockquote>
<p>
<br />The issue is that <code>getcontext</code> calls <code>sigprocmask</code> on <b>every invocation</b> but <code>_setjmp</code> does not.</p>
<p><b>BUT WAIT</b> if that&#8217;s true why didn&#8217;t <code>GDB</code> hit a <code>sigprocmask</code> breakpoint before?</p>
<p><h2>x86_64 assembly FTW, again</h2>
</p>
<p>
Let&#8217;s fire up <code>gdb</code> and figure out this breakpoint-not-breaking thing. First, let&#8217;s start by disassembling <code>getcontext</code> (snipped for brevity):<br />
<code><br />
(gdb) p getcontext<br />
$1 = {<text variable, no debug info>} 0&#215;7ffff7825100 <getcontext><br />
(gdb) disas getcontext<br />
&#8230;<br />
0&#215;00007ffff782517f <getcontext+127>:	mov    $0xe,%rax<br />
0&#215;00007ffff7825186 <getcontext+134>:	syscall<br />
&#8230;<br />
</code></p>
<p>Yeah, that&#8217;s pretty weird. I&#8217;ll explain why in a minute, but let&#8217;s look at the disassembly of <code>sigprocmask</code> first:<br />
<code><br />
(gdb) p sigprocmask<br />
$2 = {<text variable, no debug info>} 0&#215;7ffff7817340 <__sigprocmask><br />
(gdb) disas sigprocmask<br />
&#8230;<br />
0&#215;00007ffff7817383 <__sigprocmask+67>:	mov    $0xe,%rax<br />
0&#215;00007ffff7817388 <__sigprocmask+72>:	syscall<br />
&#8230;<br />
</code><br />
Yeah, this is a bit confusing, but here&#8217;s the deal.</p>
<p>
Recent Linux kernels implement a shiny new method for calling system calls called <code>sysenter/sysexit</code>. This new way was created because the old way (<code>int $0x80</code>) turned out to be pretty slow. So Intel created some new instructions to execute system calls without such huge overhead.</p>
<p> All you need to know right now (I&#8217;ll try to blog more about this in the future) is that the <code>%rax</code> register holds the system call number. The <code>syscall</code> instruction transfers control to the kernel and the kernel figures out which syscall you wanted by checking the value in <code>%rax</code>. Let&#8217;s just make sure that <code>sigprocmask</code> is actually 0xe:</p>
<pre class="prettyprint lang-c">
[joe@pluto:/usr/include]% grep -Hrn "sigprocmask" asm-x86_64/unistd.h
asm-x86_64/unistd.h:44:#define __NR_rt_sigprocmask                     14</pre>
<p>
<br />
<b>Bingo. It&#8217;s calling <code>sigprocmask</code> (albeit a bit obscurely).</b></p>
<p>
OK, so <code>getcontext</code> isn&#8217;t calling <code>sigprocmask</code> directly, instead it replicates a bunch of code that <code>sigprocmask</code> has in its function body. That&#8217;s why we didn&#8217;t hit the <code>sigprocmask</code> breakpoint; <code>GDB</code> was going to break if you landed on the address <code>0x7ffff7817340</code> but <b>you didn&#8217;t</b>. </p>
<p>Instead, <code>getcontext</code> reimplements the wrapper code for <code>sigprocmask</code> itself and <code>GDB</code> is none the wiser. </p>
<p><b>Mystery solved</b>.</p>
<p><h2>The patch</h2>
</p>
<p>
Get it <b><a href="http://github.com/ice799/matzruby/commit/0b9b69f9653782a33aee2b8937d405eae245b60c">HERE</a></b></p>
<p>
The patch works by adding a new configure flag called <code>--disable-ucontext</code> to allow you to specifically disable <code>[sg]etcontext</code> from being called, you <b>use this in conjunction with</b> <code>--enable-pthread</code>, like this:<br />
<code><br />
./configure --disable-ucontext --enable-pthread</code><br />
<br />
After you build Ruby configured like that, its performance is on par with (and sometimes slightly faster) than Ruby built with <code>--disable-pthread</code> for about a 30% performance boost when compared to <code>--enable-pthread</code>.</p>
<p>I added the switch because I wanted to preserve the original Ruby behavior, if you just pass <code>--enable-pthread</code> <b>without</b> <code>--disable-ucontext</code></b> Ruby will do the old thing and generate piles of sigprocmasks.</p>
<h2>Conclusion</h2>
<ol>
<li> Things aren&#8217;t always what they seem - GDB may lie to you. Be careful. </li>
<li> Use the source, Luke. Libraries can do unexpected things, debug builds of libc can help!</li>
<li> I know I keep saying this, assembly is useful. Start learning it today!</li>
</ol>
<p>
If you enjoyed this blog post, consider <a href="http://feeds.feedburner.com/TimeToBleed" rel="alternate" type="application/rss+xml">subscribing (via RSS)</a> or <a href="http://twitter.com/joedamato">following (via twitter)</a>.</p>
<p><b>You&#8217;ll want to stay tuned; <a href="http://twitter.com/tmm1">tmm1</a> and I have been on a roll the past week. Lots of cool stuff coming out!</b></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=yp5X51NzXdg:uQBF4U0SicQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=yp5X51NzXdg:uQBF4U0SicQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=yp5X51NzXdg:uQBF4U0SicQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=yp5X51NzXdg:uQBF4U0SicQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=yp5X51NzXdg:uQBF4U0SicQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=yp5X51NzXdg:uQBF4U0SicQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=yp5X51NzXdg:uQBF4U0SicQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=yp5X51NzXdg:uQBF4U0SicQ:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/yp5X51NzXdg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/fix-a-bug-in-rubys-configurein-and-get-a-30-performance-boost/feed/</wfw:commentRss>
		</item>
		<item>
		<title>6 Line EventMachine Bugfix = 2x faster GC, +1300% requests/sec</title>
		<link>http://timetobleed.com/6-line-eventmachine-bugfix-2x-faster-gc-1300-requestssec/</link>
		<comments>http://timetobleed.com/6-line-eventmachine-bugfix-2x-faster-gc-1300-requestssec/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 06:36:09 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[bugfix]]></category>

		<category><![CDATA[debugging]]></category>

		<category><![CDATA[ruby]]></category>

		<category><![CDATA[scaling]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[x86]]></category>

		<category><![CDATA[debug]]></category>

		<category><![CDATA[garbage collection]]></category>

		<category><![CDATA[GC]]></category>

		<category><![CDATA[memory]]></category>

		<category><![CDATA[patch]]></category>

		<category><![CDATA[patches]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[threading]]></category>

		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=554</guid>
		<description><![CDATA[



Nothing is possible without lunch
So Aman Gupta (tmm1) and I were eating lunch at the Oaxacan Kitchen on Tuesday and as usual, we were talking about scaling Ruby. We got into a small debate about which phase of garbage collection took the most CPU time.
Aman&#8217;s claim:

The mark phase, specifically the stack marking phase because of [...]]]></description>
			<content:encoded><![CDATA[<p><center><br />
<img src="http://timetobleed.com/images/oaxacan.jpg"/><br />
</center><br />
</p>
<p><h2>Nothing is possible without lunch</h2>
<p>So Aman Gupta (<a href="http://twitter.com/tmm1">tmm1</a>) and I were eating lunch at the <a href="http://www.theoaxacankitchen.com/">Oaxacan Kitchen</a> on Tuesday and as usual, we were talking about scaling Ruby. We got into a small debate about which phase of garbage collection took the most CPU time.</p>
<p>Aman&#8217;s claim:</p>
<ul>
<li>The mark phase, specifically the stack marking phase because of the huge stack frames created by rb_eval</li>
</ul>
<p>My claim:</p>
<ul>
<li>The sweep phase, because every single object has to be touched and some freeing happens.</li>
</ul>
<p>I told Aman that I didn&#8217;t believe the stack frames were that large, and we bet on how big we thought they would be. Couldn&#8217;t be more than a couple kilobytes, could it? <b>Little did we know how wrong our estimates were.</b>
</p>
<h2>Quick note about Ruby&#8217;s GC</h2>
<p>Ruby MRI has a mark-and-sweep garbage collector. As part of the mark phase, it <b>scans the process stack</b>. This is required because a pointer to a Ruby object can be passed to a C extension (like Eventmachine, or Hpricot, or whatever). If that happens, it isn&#8217;t safe to free the object yet. So Ruby does a simple scan and checks if <b>each word on the stack</b> is a pointer to the Ruby heap, if so, that item cannot be freed.<br />
</p>
<h2>GDB to the rescue</h2>
<p>We get back from lunch, launch our application, attach GDB and set a breakpoint. The breakpoint gets triggered and we see this seemingly innocuous stack trace [Note: To help with debugging, we compiled the EventMachine gem with -fno-omit-frame-pointer]:<br />
<code><br />
#0  0x00007ffff77629ac in epoll_wait () from /lib/libc.so.6<br />
#1  0x00007ffff6c0b220 in EventMachine_t::_RunEpollOnce (this=0x158d7e0) at em.cpp:461<br />
#2  0x00007ffff6c0b86c in EventMachine_t::_RunOnce (this=0x158d7e0) at em.cpp:423<br />
#3  0x00007ffff6c0bbd6 in EventMachine_t::Run (this=0x158d7e0) at em.cpp:404<br />
#4  0x00007ffff6c06638 in evma_run_machine () at cmain.cpp:83<br />
#5  0x00007ffff6c1897f in t_run_machine_without_threads (self=26066936) at rubymain.cpp:154<br />
#6  0x000000000041d598 in call_cfunc (func=0x7ffff6c1896e <t_run_machine_without_threads>, recv=26066936, len=0, argc=0, argv=0&#215;0) at eval.c:5759<br />
#7  0&#215;000000000041c92f in rb_call0 (klass=26065816, recv=26066936, id=29417, oid=29417, argc=0, argv=0&#215;0, body=0&#215;18dba10, flags=0) at eval.c:5911<br />
#8  0&#215;000000000041e0ad in rb_call (klass=26065816, recv=26066936, mid=29417, argc=0, argv=0&#215;0, scope=2, self=26066936) at eval.c:6158<br />
#9  0&#215;00000000004160d5 in rb_eval (self=26066936, n=0&#215;1940330) at eval.c:3514<br />
#10 0&#215;00000000004150b7 in rb_eval (self=26066936, n=0&#215;1941018) at eval.c:3357<br />
#11 0&#215;000000000041d196 in rb_call0 (klass=26065816, recv=26066936, id=5393, oid=5393, argc=0, argv=0&#215;0, body=0&#215;1941018, flags=0) at eval.c:6062<br />
#12 0&#215;000000000041e0ad in rb_call (klass=26065816, recv=26066936, mid=5393, argc=0, argv=0&#215;0, scope=0, self=47127864) at eval.c:6158<br />
#13 0&#215;0000000000415d01 in rb_eval (self=47127864, n=0&#215;2cf5298) at eval.c:3493<br />
#14 0&#215;00000000004148b2 in rb_eval (self=47127864, n=0&#215;2cf4380) at eval.c:3223<br />
#15 0&#215;000000000041d196 in rb_call0 (klass=47127808, recv=47127864, id=5313, oid=5313, argc=0, argv=0&#215;0, body=0&#215;2cf4380, flags=0) at eval.c:6062<br />
#16 0&#215;000000000041e0ad in rb_call (klass=47127808, recv=47127864, mid=5313, argc=0, argv=0&#215;0, scope=0, self=9606072) at eval.c:6158<br />
#17 0&#215;0000000000415d01 in rb_eval (self=9606072, n=0&#215;194b2a0) at eval.c:3493<br />
#18 0&#215;00000000004148b2 in rb_eval (self=9606072, n=0&#215;19587b0) at eval.c:3223<br />
#19 0&#215;000000000041072c in eval_node (self=9606072, node=0&#215;19587b0) at eval.c:1437<br />
#20 0&#215;0000000000410dff in ruby_exec_internal () at eval.c:1642<br />
#21 0&#215;0000000000410e4f in ruby_exec () at eval.c:1662<br />
#22 0&#215;0000000000410e72 in ruby_run () at eval.c:1672<br />
#23 0&#215;000000000040e78a in main (argc=3, argv=0&#215;7fffffffebd8, envp=0&#215;7fffffffebf8) at main.c:48<br />
</code><br />
Looks pretty normal, nothing to worry about, <i>right</i>?</p>
<p>We started checking the rb_eval frames because we assumed that those would be the largest stack frames. The rb_eval function inlines other functions and call itself recursively. So how big is one of the rb_eval frames?<br />
<code><br />
(gdb) frame 10<br />
#10 0x00000000004150b7 in rb_eval (self=26066936, n=0x1941018) at eval.c:3357<br />
3357		    result = rb_eval(self, node->nd_head);<br />
(gdb) p $rbp-$rsp<br />
$2 = 1904<br />
</code><br />
1,904 bytes - pretty large. If all the stack frames are that large, we are looking at <i>around</i> 47,600 bytes. Pretty serious. Let&#8217;s verify that Ruby thinks the stack is a sane size. There is a global in the Ruby interpreter called <code>rb_gc_stack_start</code>. It gets set when the Ruby stack is created in <code>Init_stack()</code>. When Ruby calculates the stack size it subtracts the current stack pointer from <code>rb_gc_stack_start</code> [<b>remember</b> on x86_64, the stack grows from high addresses to low addresses]. Let&#8217;s do that and see how big Ruby thinks the stack is.<br />
<code><br />
(gdb) p (unsigned int)rb_gc_stack_start - (unsigned int)$rsp<br />
$3 = 802688<br />
</code><br />
<b>Wait, wait, wait. 802,688 bytes with only 23 stack frames? WTF?!</b> Something is wrong. We started at the top and checked <i>all the rb_eval stack frames</i>, but none of them are larger than 2kb. We did find something <b>quite a bit larger than 2kb</b>, though.<br />
<code><br />
(gdb) frame 1<br />
#1  0x00007ffff6c0b220 in EventMachine_t::_RunEpollOnce (this=0x158d7e0) at em.cpp:461<br />
461		s = epoll_wait (epfd, ev, MaxEpollDescriptors, timeout == 0 ? 5 : timeout);<br />
(gdb) p $rbp-$rsp<br />
$28 = 786816<br />
</code><br />
Uh, the RunEpollOnce stack frame is <b>786,816 bytes</b>? That&#8217;s <i>got</i> to be wrong. <b>WTF?</b></p>
<p>Time to bring out the big guns.</p>
<h2>objdump + x86_64 asm FTW</h2>
<p>I pumped EventMachine&#8217;s shared object into <code>objdump</code> and captured the assembly dump:<br />
<code><br />
objdump -d rubyeventmachine.so > em.S<br />
</code><br />
I headed down to the <code>RunEpollOnce</code> function and saw the following:<br />
<code><br />
2f12b:       48 81 ec 78 01 0c 00    sub    $0xc0178,%rsp<br />
</code><br />
<b>Interesting</b>. So the code is moving <code>%rsp</code> down by 786,808 bytes to make room for something <b>big</b>. So, let&#8217;s see if the EventMachine code matches up with the assembly output.<br />
<code><br />
struct epoll_event ev [MaxEpollDescriptors];<br />
</code><br />
Where <code>MaxEpollDescriptors = 64*1024</code> and <code>sizeof(struct epoll_event) == 12</code>. That matches up with the assembly dump and the GDB output.</p>
<p>Usually, doing something like that in C/C++ is (usually) OK. Avoiding the heap whenever you can is a good idea because you avoid heap-lock contention, fragmenting the heap, and memory overhead for tracking the memory region. <b>When writing Ruby extensions, this isn&#8217;t necessarily true.</b> Remember, Ruby&#8217;s GC algorithm scans the <i>entire process stack</i> searching for references to Ruby objects. This EventMachine code causes Ruby to search an <i>extra</i> ~800,000 bytes drastically slowing down garbage collection.</p>
<h2>The patch</h2>
<p>Get the patch <a href="http://github.com/eventmachine/eventmachine/commit/1f6a4c912256b8110af94e270f7dde486f3c9d75">HERE</a></p>
<p> The patch simply moves the stack allocated <code>struct epoll_event ev</code> to the class definition so that it is allocated on the heap when an instance of the class is created with <code>new</code>. This <b>does not</b> change the memory usage of the process at all. It just moves the object off the stack. This makes all the difference because Ruby&#8217;s GC scans the <i>process stack</i> and <b>not</b> the process heap.</p>
<p>On top of all that, this patch helps with Ruby&#8217;s green threads, too. If the <code>epoll_wait</code> causes a Ruby event to fire and that event creates a Ruby thread, that Ruby thread gets an entire <b>copy</b> of the existing stack. Each time that thread is switched into and out of, that thread stack has to be memcpy&#8217;d into and out of place. Reducing those memcpys by ~800,000 bytes is a <b>HUGE</b> performance win. Want to learn more about threading implementations? Check out my threading models post: <a href="http://timetobleed.com/threading-models-so-many-different-ways-to-get-stuff-done/">here</a>.
</p>
<p>
Fixing this turned out to be pretty simple. A six (<b>6!!</b>) line patch:
</p>
<ul>
<li>Speeds up GC by <b>2-3x</b> because of the <i>huge</i> decrease in stack frame size.</li>
<li>Fixes an open bug in EventMachine where using threads with Epoll causes lots of slowness. The reason is that each thread will <b>inherit an ~800,000 byte stack</b> that gets copied in and out <b>every context switch</b>.</li>
<li>This results in an increase from <b>500 requests/sec to 7000 requests/sec</b> when using Sinatra+Thin+Epoll+Threads. <b>That is pretty ill.</b></li>
</ul>
<h2>Conclusion</h2>
<p>All in all, a productive debugging session lasting about an hour. The result was a simple patch, with 2 big performance improvements.
<p>A couple things to take away from this experience:</p>
<ul>
<li>Spend time learning your debugging tools because it pays off, especially <code>nm</code>, <code>objdump</code>, and of course <code>GDB</code>.</li>
<li>Getting familiar with x86_64 assembly is crucial if you hope to debug complex software and optimize it correctly.</li>
</ul>
<p>Keep your eyes open for up-coming blog posts about x86_64 assembly! Don&#8217;t forget to <a href="http://feeds.feedburner.com/TimeToBleed" rel="alternate" type="application/rss+xml">subscribe via RSS</a> or <a href="http://twitter.com/joedamato">follow me on twitter</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=ioo5GNN02CE:kqsOJc5mw7c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=ioo5GNN02CE:kqsOJc5mw7c:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=ioo5GNN02CE:kqsOJc5mw7c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=ioo5GNN02CE:kqsOJc5mw7c:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=ioo5GNN02CE:kqsOJc5mw7c:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=ioo5GNN02CE:kqsOJc5mw7c:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=ioo5GNN02CE:kqsOJc5mw7c:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=ioo5GNN02CE:kqsOJc5mw7c:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/ioo5GNN02CE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/6-line-eventmachine-bugfix-2x-faster-gc-1300-requestssec/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Yo Dawg: Using a package management system to install a package management system</title>
		<link>http://timetobleed.com/yo-dawg-using-a-package-management-system-to-install-a-package-management-system/</link>
		<comments>http://timetobleed.com/yo-dawg-using-a-package-management-system-to-install-a-package-management-system/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 05:21:37 +0000</pubDate>
		<dc:creator>Joe Damato</dc:creator>
		
		<category><![CDATA[scaling]]></category>

		<category><![CDATA[systems]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[package management]]></category>

		<category><![CDATA[patches]]></category>

		<guid isPermaLink="false">http://timetobleed.com/?p=183</guid>
		<description><![CDATA[

Consider the following scenario: You would like to run a common Linux distro (Debian Etch, Centos/RHEL, whatever) for stability, the large community surrounding it, and maybe even for third-party support.

There&#8217;s a catch though.

You also want to easily use and deploy a small number of custom packages. Why? Maybe you want to apply a patch for [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://timetobleed.com/images/packages.jpg" alt="" width="400" height="300" /></center><br />
</p>
<p>Consider the following scenario: You would like to run a common Linux distro (Debian Etch, Centos/RHEL, whatever) for stability, the large community surrounding it, and maybe even for third-party support.<br />
<br />
There&#8217;s a catch though.<br />
<br />
You also want to easily use and deploy a small number of custom packages. Why? Maybe you want to apply a patch for a library, compiler, interpreter, or something else you use. Sure, you could build a <code>.deb</code> or <code>.rpm</code>, but there is a bit of a learning curve; is that learning curve worth it just so you can apply a handful of patches?<br />
At Kickball Labs, we wanted to use the &#8220;stable&#8221; versions of packages that come bundled with Debian for the base system, but we also wanted to be able to use new packages that have features we are interested in. We decided to layer <code>pacman</code> on top of <code>apt</code> and install a small number of custom packages to a <code>/custom</code> directory on the filesystem. This enables us to use stable packages by default, but let&#8217;s us override them when we feel it is necessary.
</p>
<h2>What sucks about <code>RPM</code> and <code>APT</code> (imho)</h2>
<ol>
<li><b>Getting other people to use them</b> - OK, so you&#8217;ve bought in to <code>RPM</code> or <code>APT</code> and you don&#8217;t mind reading all the docs and cuddling up with the man pages. But what about the <b>rest of your team?</b> Unless there is only one person constantly cranking out custom packages, everyone is going to have to learn <code>RPM</code> or <code>APT</code>. Do you really want to waste valuable engineer brain cycles reading and debugging busted packages when instead you could be writing code?</li>
<li><b>Too much work to add 1 patch</b> - Let&#8217;s say I want to add one patch to fix a memory leak to <code>libX</code>. Here&#8217;s what I have to do for debian packages:
<ol>
<li>Download and unpack the library source.</li>
<li>Add a <code>debian/</code> sub-directory.</li>
<li>Create a <code>changelog</code>, <code>control</code>, and <code>files</code> file.</li>
<li>Create a file with a list of the patches that are being applied.</li>
<li>Drop in the patch.</li>
<li>Test the package.</li>
</ol>
<p><b>Wow.</b> <i>Extremely</i> painful. Especially for just one patch. Hell, you might even <b> throw the deb away</b> after if you decide you don&#8217;t like the patch.</p>
<li><b>Source control</b> - So you don&#8217;t mind the previous points. They don&#8217;t bother you all <i>that</i> much. But what about source control? How do you keep track of your Debian package files? You <i>could</i> keep an entire copy of the library&#8217;s source with your <code>debian/</code> sub-directory in your <code>git/svn/whatever</code>. That kind of sucks, though. What if you got your source code from the <code>git/svn</code> of the project instead of via a tarball? Yeah, I <i>guess</i> you could put all that into source control too. You could also check in your <code>debian/</code> sub-dirs into a repository and then symlink them into the source for the library&#8230;. <b>What a pain.</b>
</ol>
<h2><code>pacman</code> and the almighty <code>PKGBUILD</code></h2>
<p>
This is where <a href="http://www.archlinux.org/pacman/"><code>pacman</code></a> saves the day.</p>
<ol>
<li><a href="http://www.archlinux.org/pacman/pacman.8.html"><code>pacman</code></a> is simple - It doesn&#8217;t try to solve Global Warming. It just provides a dead simple set of command line switches for installing, removing, upgrading, and syncing packages. Not many options, but that is <b>exactly</b> what I want. You can just put a bunch of packages in a directory, point a webserver at it and its a <code>pacman</code> package server.</li>
<li><a href="http://www.archlinux.org/pacman/PKGBUILD.5.html"><code>PKGBUILD</code></a> files are simple - <code>PKGBUILD</code> files are just plain text files with a few fields. The fields are easy to understand and you can learn how to write your first PKGBUILD in 5 minutes.</li>
<li>Easily use with source control - Since the actual <code>PKGBUILD</code> file is plain text, your source control system should be able to easily keep track of changes. You don&#8217;t need to check in all the source, either. You can just point the PKGBUILD at a URL and it will automagically run wget and unpack the source. You can include a source tarball if you really want to, of course.</li>
<li>Quickly create create a new <code>PKGBUILD</code> or add a patch to an existing one - To add a new patch to an existing <code>PKGBUILD</code> I just add the filename to the <code>source = </code> line, and add a <code>patch -p N < file</code> line and I&#8217;m done. If the <code>PKGBUILD</code> doesn&#8217;t exist, I can easily create a new one because the file format is <b>dead simple</b></li>
</ol>
<h2>Getting it on Debian</h2>
<p>This part is kind of weird. We want to get <code>pacman</code> on Debian. There isn&#8217;t an <code>apt</code> package, so what now? Well, we can build a <code>.deb</code> file that installs <code>pacman</code> so we can use PKGBUILDs. Basically, we use a package management system to <i>install</i> a package management system.<br />
<br />
There&#8217;s gotta be a &#8220;Yo Dawg&#8221; in there somewhere.<br />
<br />
Get it <a href="http://timetobleed.com/files/pacman-arch_3.2.1-2_amd64.deb">here</a> and be sure to get its dependency (libdownload) <a href="http://timetobleed.com/files/libdownload_1.3-1_amd64.deb">here</a>.</p>
<h2>A look at some PKGBUILDs</h2>
<p>
Let&#8217;s take a look some PKGBUILDs that we use at Kickball Labs.
</p>
<p>The first is a simple PKGBUILD for ltrace, a program like <a href="http://timetobleed.com/hello-world/">strace</a> but for library calls. It just downloads the source, passes in some custom options to configure, builds the binary, and then installs to the package directory.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="re2">pkgname=</span>ltrace<br />
<span class="re2">pkgver=</span><span class="nu0">0.5</span><span class="nu0">.1</span><br />
<span class="re2">pkgrel=</span><span class="nu0">1</span><br />
<span class="re2">pkgdesc=</span><span class="st0">&quot;ltrace is a debugging program which runs a specified command until it exits&quot;</span><br />
<span class="re2">url=</span><span class="st0">&quot;http://packages.debian.org/unstable/utils/ltrace&quot;</span><br />
<span class="re2">arch=</span><span class="br0">&#40;</span><span class="st0">&#8216;x86_64&#8242;</span><span class="br0">&#41;</span><br />
<span class="re2">source=</span><span class="br0">&#40;</span>http://<span class="kw2">ftp</span>.debian.org/debian/pool/main/l/ltrace/<span class="re0">$<span class="br0">&#123;</span>pkgname<span class="br0">&#125;</span></span>_<span class="re0">$<span class="br0">&#123;</span>pkgver<span class="br0">&#125;</span></span>.orig.<span class="kw2">tar</span>.gz<span class="br0">&#41;</span></p>
<p>build<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw3">cd</span> <span class="re1">$startdir</span>/src/<span class="re1">$pkgname</span>-<span class="re1">$pkgver</span></p>
<p>&nbsp; ./configure &#8211;<span class="re2">prefix=</span>/custom &#8211;<span class="re2">sysconfdir=</span>/custom/etc<br />
&nbsp; <span class="kw2">make</span> || <span class="kw3">return</span> <span class="nu0">1</span><br />
&nbsp; <span class="kw2">make</span> <span class="re2">DESTDIR=</span><span class="re1">$startdir</span>/pkg <span class="kw2">install</span><br />
<span class="br0">&#125;</span></div>
<p>
<p>
Download it <a href="http://timetobleed.com/files/pkgbuild-ltrace">here.</a></p>
<p>This next PKGBUILD is a bit more intense. It is our PKGBUILD for Ruby, with a bunch of extra patches (<a href="http://timetobleed.com/fibers-implemented-for-ruby-1867/">fibers</a>, <a href="http://timetobleed.com/plugging-ruby-memory-leaks-heapstack-dump-patches-to-help-take-out-the-trash/">ruby GC patches</a>, and <a href="http://timetobleed.com/ruby-threading-bugfix-small-fix-goes-a-long-way/">ruby thread bugfixes</a>).</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="re2">pkgname=</span>ruby<br />
<span class="re2">pkgver=</span><span class="nu0">1.8</span>.7_p72<br />
<span class="re2">_pkgver=</span><span class="nu0">1.8</span><span class="nu0">.7</span>-p72<br />
<span class="re2">pkgrel=</span><span class="nu0">27</span><br />
<span class="re2">pkgdesc=</span><span class="st0">&quot;An object-oriented language for quick and easy programming&quot;</span><br />
<span class="re2">arch=</span><span class="br0">&#40;</span>i686 x86_64<span class="br0">&#41;</span><br />
<span class="re2">license=</span><span class="br0">&#40;</span><span class="st0">&#8216;custom&#8217;</span><span class="br0">&#41;</span><br />
<span class="re2">url=</span><span class="st0">&quot;http://www.ruby-lang.org/en/&quot;</span><br />
<span class="re2">depends=</span><span class="br0">&#40;</span>google-perftools<span class="br0">&#41;</span><br />
<span class="re2">provides=</span><span class="br0">&#40;</span>ruby<span class="br0">&#41;</span><br />
<span class="re2">conflicts=</span><span class="br0">&#40;</span>ruby<span class="br0">&#41;</span><br />
<span class="re2">source=</span><span class="br0">&#40;</span><span class="kw2">ftp</span>://<span class="kw2">ftp</span>.ruby-lang.org/pub/ruby/stable/ruby-<span class="re0">$<span class="br0">&#123;</span>_pkgver<span class="br0">&#125;</span></span>.<span class="kw2">tar</span>.bz2 thread_timer.<span class="kw2">patch</span> fibers.<span class="kw2">patch</span> ruby<span class="nu0">-186</span>-gc-new.<span class="kw2">patch</span> dump_heap.<span class="kw2">patch</span><span class="br0">&#41;</span></p>
<p><span class="re2">options=</span><span class="br0">&#40;</span><span class="st0">&#8216;!emptydirs&#8217;</span> <span class="st0">&#8216;force&#8217;</span><span class="br0">&#41;</span></p>
<p>build<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <span class="kw2">sudo</span> apt-get <span class="kw2">install</span> libreadline5-dev zlib1g-dev libncurses5-dev libssl-dev libgdbm-dev libdb4<span class="nu0">.4</span>-dev</p>
<p>&nbsp; <span class="kw3">cd</span> <span class="re0">$<span class="br0">&#123;</span>startdir<span class="br0">&#125;</span></span>/src/<span class="re0">$<span class="br0">&#123;</span>pkgname<span class="br0">&#125;</span></span>-<span class="re0">$<span class="br0">&#123;</span>_pkgver<span class="br0">&#125;</span></span></p>
<p>&nbsp; <span class="kw2">patch</span> -p1 &lt; <span class="re0">$<span class="br0">&#123;</span>startdir<span class="br0">&#125;</span></span>/src/fibers.<span class="kw2">patch</span> || <span class="kw3">return</span> <span class="nu0">1</span><br />
&nbsp; <span class="kw2">patch</span> -p0 &lt; <span class="re0">$<span class="br0">&#123;</span>startdir<span class="br0">&#125;</span></span>/src/thread_timer.<span class="kw2">patch</span> || <span class="kw3">return</span> <span class="nu0">1</span><br />
&nbsp; <span class="kw2">patch</span> -p1 &lt; <span class="re0">$<span class="br0">&#123;</span>startdir<span class="br0">&#125;</span></span>/src/ruby<span class="nu0">-186</span>-gc-new.<span class="kw2">patch</span> || <span class="kw3">return</span> <span class="nu0">1</span><br />
&nbsp; <span class="kw2">patch</span> -p1 &lt; <span class="re0">$<span class="br0">&#123;</span>startdir<span class="br0">&#125;</span></span>/src/dump_heap.<span class="kw2">patch</span> || <span class="kw3">return</span> <span class="nu0">1</span></p>
<p>&nbsp; <span class="re3"># include /custom <span class="kw1">in</span> cflags/ldflags so extensions compile</span><br />
&nbsp; <span class="kw3">export</span> <span class="re2">CFLAGS=</span><span class="st0">&quot;-I/custom/include -g3 -gdwarf-2 -ggdb -O0&quot;</span><br />
&nbsp; <span class="kw3">export</span> <span class="re2">LDFLAGS=</span><span class="st0">&quot;-L/custom/lib&quot;</span><br />
&nbsp; <span class="kw3">export</span> <span class="re2">LIBS=</span><span class="st0">&quot;-L/custom/lib -ltcmalloc_minimal&quot;</span></p>
<p>&nbsp; ./configure &#8211;<span class="re2">prefix=</span>/custom &#8211;enable-shared &#8211;disable-pthread<br />
&nbsp; <span class="kw2">make</span> || <span class="kw3">return</span> <span class="nu0">1</span><br />
&nbsp; <span class="kw2">make</span> <span class="re2">DESTDIR=</span><span class="re0">$<span class="br0">&#123;</span>startdir<span class="br0">&#125;</span></span>/pkg <span class="kw2">install</span><br />
<span class="br0">&#125;</span></div>
<p>
<p>
Download it <a href="http://timetobleed.com/files/pkgbuild-ruby">here.</a></p>
<h2>Conclusion</h2>
<p>Package management is painful. If you have any plans on building a service that scales to multiple machines, you had better have a good solution for creating and distributing packages. <code>pacman</code> is good for this because:</p>
<ol>
<li>It&#8217;s easy to learn and use, encouraging you to make everything (from libraries to configuration files and more) a PKGBUILD.</li>
<li>The simple plain text file format works great with your source control system of choice.</li>
<li>Applied a patch you didn&#8217;t like? Just roll the PKGBUILD file back with your package manager.</li>
<li>Create a <code>PKGBUILD</code> repository by just putting the tarballs generated from your <code>PKGBUILD</code> files in a directory and pointing a web server at it. This is great for bringing up new hardware in a datacenter - just install <code>pacman</code>, point it at your repository, and install your base package which sets up the all your <code>passwd</code>, <code>host</code>, or other config files. </li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=B2IF_L1GA84:gpepVjoloaQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=B2IF_L1GA84:gpepVjoloaQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=B2IF_L1GA84:gpepVjoloaQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=B2IF_L1GA84:gpepVjoloaQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=B2IF_L1GA84:gpepVjoloaQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=B2IF_L1GA84:gpepVjoloaQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TimeToBleed?a=B2IF_L1GA84:gpepVjoloaQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/TimeToBleed?i=B2IF_L1GA84:gpepVjoloaQ:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TimeToBleed/~4/B2IF_L1GA84" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://timetobleed.com/yo-dawg-using-a-package-management-system-to-install-a-package-management-system/feed/</wfw:commentRss>
		</item>
	</channel>
</rss><!-- Dynamic page generated in 0.764 seconds. --><!-- Cached page generated by WP-Super-Cache on 2009-11-10 08:31:04 -->
