<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: Performance tweaking of Ruby algorithms</title>
	<atom:link href="http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/feed/" rel="self" type="application/rss+xml" />
	<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/</link>
	<description>Our latest geek adventures!</description>
	<lastBuildDate>Tue, 16 Mar 2010 19:42:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: greg willits</title>
		<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/comment-page-1/#comment-749</link>
		<dc:creator>greg willits</dc:creator>
		<pubDate>Fri, 09 Oct 2009 17:04:45 +0000</pubDate>
		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=716#comment-749</guid>
		<description>quick thoughts -- 

log file ordering: assuming each request is stored into a single array of hashes, my first reaction would be to build an index based on request time. I&#039;d use a two-dimensional array [[time, position], [time, position]], then sort based on the time to give me an index into request data array. Even though there&#039;s forked processes, the original process is the one storing the results and creating the index.

gains from forking: depending on how much work you&#039;re doing for those 6 lines, the tradeoff does indeed need to be verified. But, you could also split the file by regex into requests, then send batches of requests to each fork. Send each fork 10, 50, 1000 requests or whatever.

code file is &quot;in the mail&quot;</description>
		<content:encoded><![CDATA[<p>quick thoughts &#8212; </p>
<p>log file ordering: assuming each request is stored into a single array of hashes, my first reaction would be to build an index based on request time. I&#8217;d use a two-dimensional array [[time, position], [time, position]], then sort based on the time to give me an index into request data array. Even though there&#8217;s forked processes, the original process is the one storing the results and creating the index.</p>
<p>gains from forking: depending on how much work you&#8217;re doing for those 6 lines, the tradeoff does indeed need to be verified. But, you could also split the file by regex into requests, then send batches of requests to each fork. Send each fork 10, 50, 1000 requests or whatever.</p>
<p>code file is &#8220;in the mail&#8221;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Willem van Bergen</title>
		<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/comment-page-1/#comment-743</link>
		<dc:creator>Willem van Bergen</dc:creator>
		<pubDate>Tue, 06 Oct 2009 06:11:19 +0000</pubDate>
		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=716#comment-743</guid>
		<description>Hey Greg,

What you suggest seems like an approach with potential as it uses processes instead of threads. I definitely going to try this out at some point when I have some more time available. Can you send me your test file (willem AT floorplanner DOR com)? And, if you have time to spare, please fork the project and try it out yourself ;-)

I do expect some problems though, all of which can probably be worked around. First of all: Rails log files are not always ordered correctly. R-l-a uses some heuristics to detect this, but this may not work when parsing is split out in different processes. Moreover, in production mode every request, every requests consists of about 6 lines. Is the overhead of forking not bigger than the gains that can be made? Interesting stuff to try out.</description>
		<content:encoded><![CDATA[<p>Hey Greg,</p>
<p>What you suggest seems like an approach with potential as it uses processes instead of threads. I definitely going to try this out at some point when I have some more time available. Can you send me your test file (willem AT floorplanner DOR com)? And, if you have time to spare, please fork the project and try it out yourself <img src='http://techblog.floorplanner.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>I do expect some problems though, all of which can probably be worked around. First of all: Rails log files are not always ordered correctly. R-l-a uses some heuristics to detect this, but this may not work when parsing is split out in different processes. Moreover, in production mode every request, every requests consists of about 6 lines. Is the overhead of forking not bigger than the gains that can be made? Interesting stuff to try out.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: greg willits</title>
		<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/comment-page-1/#comment-742</link>
		<dc:creator>greg willits</dc:creator>
		<pubDate>Mon, 05 Oct 2009 19:20:53 +0000</pubDate>
		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=716#comment-742</guid>
		<description>Parallelization--one of my projects involves data normalization and aggregation where parsing and transforming fields in GBs of data is one of the primary tasks. We developed delineations in the data and in the work flow where forking proved to be a huge aid to processing speed.

Looking at a log file (for Rails anyway), it&#039;s pretty easy to identify requests. They start with &quot;Processing...&quot; and have some empty lines between them. It would be pretty easy to fork processing on a per request basis. Assuming the organization of the rest of your processing wouldn&#039;t result in huge RAM duplication (our processes are organized to minimize this).

I can see a workflow like: load log file, split into requests, iterate requests forking for each one, parse request, when all requests are parsed, main thread starts analysis (probably forking for each one), save results of each analysis to file, when all forks completed, read the file, stitch the results together for group analysis / presentation.

I have a cheesy test file to show you how to do the forking if you&#039;re interested. I would expect it to speed up your processing quite a bit.</description>
		<content:encoded><![CDATA[<p>Parallelization&#8211;one of my projects involves data normalization and aggregation where parsing and transforming fields in GBs of data is one of the primary tasks. We developed delineations in the data and in the work flow where forking proved to be a huge aid to processing speed.</p>
<p>Looking at a log file (for Rails anyway), it&#8217;s pretty easy to identify requests. They start with &#8220;Processing&#8230;&#8221; and have some empty lines between them. It would be pretty easy to fork processing on a per request basis. Assuming the organization of the rest of your processing wouldn&#8217;t result in huge RAM duplication (our processes are organized to minimize this).</p>
<p>I can see a workflow like: load log file, split into requests, iterate requests forking for each one, parse request, when all requests are parsed, main thread starts analysis (probably forking for each one), save results of each analysis to file, when all forks completed, read the file, stitch the results together for group analysis / presentation.</p>
<p>I have a cheesy test file to show you how to do the forking if you&#8217;re interested. I would expect it to speed up your processing quite a bit.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Request-log-analyzer 1.4.0 &#124; Floorplanner Tech Blog</title>
		<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/comment-page-1/#comment-724</link>
		<dc:creator>Request-log-analyzer 1.4.0 &#124; Floorplanner Tech Blog</dc:creator>
		<pubDate>Wed, 30 Sep 2009 09:40:09 +0000</pubDate>
		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=716#comment-724</guid>
		<description>[...] improvements: we have profiled request-log-analyzer itself and significantly improved its [...]</description>
		<content:encoded><![CDATA[<p>[...] improvements: we have profiled request-log-analyzer itself and significantly improved its [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Willem van Bergen</title>
		<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/comment-page-1/#comment-720</link>
		<dc:creator>Willem van Bergen</dc:creator>
		<pubDate>Mon, 28 Sep 2009 09:14:30 +0000</pubDate>
		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=716#comment-720</guid>
		<description>I have tried the multithreaded variant of r-l-a with both Ruby 1.9.1 (source install) and JRuby (OSX package from website).

Ruby 1.9.1 does not make much difference, because all threads still block on IO operations. Of course, r-l-a does a lot of file-reading, so it needs to be rewritten using non-blocking IO to make a difference.

JRuby is actually a lot faster using the threaded approach, but is so much slower to begin with, that it is still slower than Ruby 1.8 in the end.

With the different approaches taken by the different interpreters, the different concurrency APIs that are available and the small speed gains to be made at this moment, I decided to not use threading for now.

Fortunately, the other tweaks did improve performance significantly, and they work with every Ruby version and interpreter. :-)</description>
		<content:encoded><![CDATA[<p>I have tried the multithreaded variant of r-l-a with both Ruby 1.9.1 (source install) and JRuby (OSX package from website).</p>
<p>Ruby 1.9.1 does not make much difference, because all threads still block on IO operations. Of course, r-l-a does a lot of file-reading, so it needs to be rewritten using non-blocking IO to make a difference.</p>
<p>JRuby is actually a lot faster using the threaded approach, but is so much slower to begin with, that it is still slower than Ruby 1.8 in the end.</p>
<p>With the different approaches taken by the different interpreters, the different concurrency APIs that are available and the small speed gains to be made at this moment, I decided to not use threading for now.</p>
<p>Fortunately, the other tweaks did improve performance significantly, and they work with every Ruby version and interpreter. <img src='http://techblog.floorplanner.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Michel Jansen</title>
		<link>http://techblog.floorplanner.com/2009/09/27/performance-tweaking-of-ruby-algorithms/comment-page-1/#comment-717</link>
		<dc:creator>Michel Jansen</dc:creator>
		<pubDate>Sun, 27 Sep 2009 19:25:07 +0000</pubDate>
		<guid isPermaLink="false">http://techblog.floorplanner.com/?p=716#comment-717</guid>
		<description>Nice article :)
Most of these apply to other programming languages as well, especially the &quot;Check the most common case is first&quot;, &quot;Calculate things that do not change only once&quot; and regex tips. 

What you say about Ruby not using multiple cores in a multiprocessor system is true for versions of Ruby prior to 1.9, when it still used so called &quot;Green Threads&quot;. If you want multicore performance with Ruby 1.8, you can use processes instead (or upgrade to 1.9 and benefit from native threading support).</description>
		<content:encoded><![CDATA[<p>Nice article <img src='http://techblog.floorplanner.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Most of these apply to other programming languages as well, especially the &#8220;Check the most common case is first&#8221;, &#8220;Calculate things that do not change only once&#8221; and regex tips. </p>
<p>What you say about Ruby not using multiple cores in a multiprocessor system is true for versions of Ruby prior to 1.9, when it still used so called &#8220;Green Threads&#8221;. If you want multicore performance with Ruby 1.8, you can use processes instead (or upgrade to 1.9 and benefit from native threading support).</p>
]]></content:encoded>
	</item>
</channel>
</rss>
