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

<channel>
	<title>Coffee Powered &#187; performance</title>
	<atom:link href="http://www.coffeepowered.net/tag/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coffeepowered.net</link>
	<description>code and content</description>
	<lastBuildDate>Mon, 09 Jan 2012 18:32:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Announcing Scrap</title>
		<link>http://www.coffeepowered.net/2009/03/24/announcing-scrap/</link>
		<comments>http://www.coffeepowered.net/2009/03/24/announcing-scrap/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 10:02:09 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[metal]]></category>
		<category><![CDATA[objectspace]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=159</guid>
		<description><![CDATA[I do a lot of memory and garbage analysis on my Rails apps, and in upgrading to Rails 2.3, I discovered a practical use for the new Rails Metal middleware. Dumping memory stats to my log was just sorta unreadable in a practical scenario, and was more or less entirely unusable in production. Fortunately, Metal [...]]]></description>
			<content:encoded><![CDATA[<p>I do a lot of memory and garbage analysis on my Rails apps, and in upgrading to Rails 2.3, I discovered a practical use for the new <a href="http://weblog.rubyonrails.org/2008/12/17/introducing-rails-metal">Rails Metal</a> middleware. Dumping memory stats to my log was just sorta unreadable in a practical scenario, and was more or less entirely unusable in production. Fortunately, Metal provides a really easy way to output readable information to the browser without invoking the full Rails stack. (It&#8217;s also an excuse to write a Metal endpoint because it&#8217;s new and shiny, but that&#8217;s beside the point.)</p>
<p>It&#8217;s up at <a href="http://github.com/cheald/scrap/tree/master">github</a> &#8211; installation is dead easy (assuming you&#8217;re on Rails 2.3+, of course) &#8211; just install the plugin, restart your app, and hit <code>&lt;your url&gt;/stats/scrap</code> in your browser. Bam, instant juicy memory goodness about your app at your fingertips. If you&#8217;d like an example of the output, good news! Check it out at <a href="http://tachyonsix.com/scrap.htm">http://tachyonsix.com/scrap.htm</a>.</p>
<p>You can use it to troubleshoot heap leaks &#8211; just run a few requests, hit your Scrap URL, and see what your deltas look like. Seeing a huge growth in a certain type of object? Chances are pretty good that you have a heap leak, and can start tracking it down.</p>
<p>The request history can help you locate certain actions that might be causing spikes in memory usage. It&#8217;ll show the last N requests, along with memory and heap statistics before each request. If there&#8217;s a consistent memory usage leap after a certain action, chances are that it&#8217;s doing something naughty.</p>
<p>Want to get a bigger picture on what objects are hanging around? You can use the <code>config/scrap.yml</code> file to get Scrap to spit out more detailed reports on instances of a given class. There&#8217;s full documentation on it in the README.</p>
<p>Anyhow, give it a shot, let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/03/24/announcing-scrap/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Mass inserting data in Rails without killing your performance</title>
		<link>http://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/</link>
		<comments>http://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 03:55:59 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=82</guid>
		<description><![CDATA[Mass inserting is one of those operations that isn&#8217;t really well-supported by ActiveRecord, but which has to be done nonethless. You might say, &#8220;Well hey, I&#8217;ll just run a loop and create a bunch of AR objects, no sweat&#8221;. That&#8217;ll work, but if speed is a factor, it might not be your best option. ActiveRecord [...]]]></description>
			<content:encoded><![CDATA[<p>Mass inserting is one of those operations that isn&#8217;t really well-supported by ActiveRecord, but which has to be done nonethless. You might say, &#8220;Well hey, I&#8217;ll just run a loop and create a bunch of AR objects, no sweat&#8221;.</p>
<p>That&#8217;ll work, but if speed is a factor, it might not be your best option.</p>
<p>ActiveRecord makes interface to the DB very easy, but it doesn&#8217;t necessarily make it fast. Instantiating an ActiveRecord object is costly, and if you do a lot of &#8216;em, that&#8217;s going to cause you to bump up against the garbage collector, which will significantly hinder performance. There are several options, though, depending on how much speed you need.</p>
<p>There are benchmarks at the bottom of the post, so if you&#8217;re just interested in those, scroll down.<br />
<span id="more-82"></span></p>
<h2>Option 1: Use transactions</h2>
<p>This is definitely the easiest method, and while you&#8217;ll realize gains from it, you aren&#8217;t going to be breaking any speed records using only this method. However, it&#8217;s well worth it if you are doing mass inserts via ActiveRecord.</p>
<p>Instead of</p>
<pre class="brush: ruby; title: ; notranslate">
1000.times { Model.create(options) }
</pre>
<p>You want:</p>
<pre class="brush: ruby; title: ; notranslate">
ActiveRecord::Base.transaction do
  1000.times { Model.create(options) }
end
</pre>
<p>The net effect is that the database performs all of your inserts in a single transaction, rather than starting and committing a new transaction for every request.</p>
<h2>Options 2: Get down and dirty with the raw SQL</h2>
<p>If you know that your data is valid and can afford to skip validations, you can save a <b>lot</b> of time by just jumping directly to raw SQL.</p>
<p>Imagine, for example, that you&#8217;re running the following:</p>
<pre class="brush: ruby; title: ; notranslate">
1000.times {|i| Foo.create(:counter =&gt; i) }
</pre>
<p>That&#8217;s going to create 1000 ActiveRecord objects, run validations, generate the insert SQL, and dump it into the database. You can realize large performance gains by just jumping directly to the generated SQL.</p>
<pre class="brush: ruby; title: ; notranslate">
1000.times do |i|
  Foo.connection.execute &quot;INSERT INTO foos (counter) values (#{i})&quot;
end
</pre>
<p>You should use <code>sanitize_sql</code> and such as necessary to sanitize input values if they are not already sanitized, but with this technique you can realize extremely large performance gains. Of course, wrapping all those inserts in a single transaction, as in Option 1 gets you even more performance.</p>
<pre class="brush: ruby; title: ; notranslate">
Foo.transaction do
  1000.times do |i|
    Foo.connection.execute &quot;INSERT INTO foos (counter) values (#{i})&quot;
  end
end
</pre>
<h2>Option 3: A single mass insert</h2>
<p>Many databases support mass inserts of data in a single insert statement. They are able to significantly optimize this operation under the hood, and if you&#8217;re comfortable using it, will be your fastest option by far.</p>
<pre class="brush: ruby; title: ; notranslate">
inserts = []
TIMES.times do
  inserts.push &quot;(3.0, '2009-01-23 20:21:13', 2, 1)&quot;
end
sql = &quot;INSERT INTO user_node_scores (`score`, `updated_at`, `node_id`, `user_id`) VALUES #{inserts.join(&quot;, &quot;)}&quot;
</pre>
<p>No transaction block is necessary here, since it&#8217;s just a single statement, and the DB will wrap it in a transaction. We build an array of value sets to include, then just join them into the <code>INSERT</code> statement. We don&#8217;t use string concatenation, since it will result in significantly more string garbage generated, which could potentially get us into the GC, which we&#8217;re trying to avoid (and hey, memory savings are always good).</p>
<h2>Option 4: ActiveRecord::Extensions</h2>
<p>njero in <code>#rubyonrails</code> pointed me at <a href="http://www.continuousthinking.com/tags/arext/rdoc/index.html">this nifty little gem</a> and I decided to include it. It seems to try to intelligently do mass inserts of data. I wasn&#8217;t able to get it to emulate the single mass insert for a MySQL database, but it does provide a significant speed increase without much additional work, and can preserve your validations and such.</p>
<p>There&#8217;s the obvious added benefit that you stay in pure Ruby, and don&#8217;t have to get into the raw SQL.</p>
<pre class="brush: ruby; title: ; notranslate">
columns = [:score, :node_id, :user_id]
values = []
TIMES.times do
	values.push [3, 2, 1]
end

UserNodeScore.import columns, values
</pre>
<h2>Benchmarks</h2>
<p>I used a simple script to test each of the methods described here.</p>
<pre class="brush: ruby; title: ; notranslate">
require &quot;ar-extensions&quot;

CONN = ActiveRecord::Base.connection
TIMES = 10000

def do_inserts
	TIMES.times { UserNodeScore.create(:user_id =&gt; 1, :node_id =&gt; 2, :score =&gt; 3) }
end

def raw_sql
	TIMES.times { CONN.execute &quot;INSERT INTO `user_node_scores` (`score`, `updated_at`, `node_id`, `user_id`) VALUES(3.0, '2009-01-23 20:21:13', 2, 1)&quot; }
end

def mass_insert
	inserts = []
	TIMES.times do
		inserts.push &quot;(3.0, '2009-01-23 20:21:13', 2, 1)&quot;
	end
	sql = &quot;INSERT INTO user_node_scores (`score`, `updated_at`, `node_id`, `user_id`) VALUES #{inserts.join(&quot;, &quot;)}&quot;
	CONN.execute sql
end

def activerecord_extensions_mass_insert(validate = true)
	columns = [:score, :node_id, :user_id]
	values = []
	TIMES.times do
		values.push [3, 2, 1]
	end

	UserNodeScore.import columns, values, {:validate =&gt; validate}
end

puts &quot;Testing various insert methods for #{TIMES} inserts\n&quot;
puts &quot;ActiveRecord without transaction:&quot;
puts base = Benchmark.measure { do_inserts }

puts &quot;ActiveRecord with transaction:&quot;
puts bench = Benchmark.measure { ActiveRecord::Base.transaction { do_inserts } }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;Raw SQL without transaction:&quot;
puts bench = Benchmark.measure { raw_sql }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;Raw SQL with transaction:&quot;
puts bench = Benchmark.measure { ActiveRecord::Base.transaction { raw_sql } }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;Single mass insert:&quot;
puts bench = Benchmark.measure { mass_insert }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;ActiveRecord::Extensions mass insert:&quot;
puts bench = Benchmark.measure { activerecord_extensions_mass_insert }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)

puts &quot;ActiveRecord::Extensions mass insert without validations:&quot;
puts bench = Benchmark.measure { activerecord_extensions_mass_insert(true)  }
puts sprintf(&quot;  %2.2fx faster than base&quot;, base.real / bench.real)
</pre>
<p>And the results:</p>
<pre class="brush: ruby; title: ; notranslate">
Testing various insert methods for 10000 inserts
ActiveRecord without transaction:
 14.930000   0.640000  15.570000 ( 18.898352)
ActiveRecord with transaction:
 13.420000   0.310000  13.730000 ( 14.619136)
  1.29x faster than base
Raw SQL without transaction:
  0.920000   0.170000   1.090000 (  3.731032)
  5.07x faster than base
Raw SQL with transaction:
  0.870000   0.150000   1.020000 (  1.648834)
  11.46x faster than base
Single mass insert:
  0.000000   0.000000   0.000000 (  0.268634)
  70.35x faster than base
ActiveRecord::Extensions mass insert:
  6.580000   0.280000   6.860000 (  9.409169)
  2.01x faster than base
ActiveRecord::Extensions mass insert without validations:
  6.550000   0.240000   6.790000 (  9.446273)
  2.00x faster than base
</pre>
<p>The results are fairly self-explainatory, but of particular note is the specific single INSERT statement. At 70x faster than the non-transactional ActiveRecord insert, if you need speed, it&#8217;s hard to beat.</p>
<h2>Conclusions</h2>
<p>ActiveRecord is great, but sometimes it&#8217;ll hold you back. Finding the balance between ease of use (full ActiveRecord) and performance (bare metal mass inserts) can have a profound effect on the performance of your app.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Quick tip &#8211; use anonymous blocks!</title>
		<link>http://www.coffeepowered.net/2008/10/09/quick-tip-use-anonymous-blocks/</link>
		<comments>http://www.coffeepowered.net/2008/10/09/quick-tip-use-anonymous-blocks/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 05:30:21 +0000</pubDate>
		<dc:creator>Chris Heald</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.coffeepowered.net/?p=75</guid>
		<description><![CDATA[In tracking down a memory leak in one of our Rails apps today, I ran across an interesting post detailing the difference between anonymous and named blocks in Ruby, and the performance differences therein. It&#8217;s definitely worth a look, especially if you&#8217;re running in a complex environment, where new closures will be large and unwieldy. [...]]]></description>
			<content:encoded><![CDATA[<p>In tracking down a memory leak in one of our Rails apps today, I ran across an <a href="http://blog.pluron.com/2008/02/rails-faster-as.html">interesting post</a> detailing the difference between anonymous and named blocks in Ruby, and the performance differences therein.</p>
<p>It&#8217;s definitely worth a look, especially if you&#8217;re running in a complex environment, where new closures will be large and unwieldy. It&#8217;s very easy, too. Any time you use:</p>
<pre class="brush: ruby; title: ; notranslate">
def note(text, options = {}, &amp;block)
  options[:class] = ((options[:class] || &quot;&quot;) + &quot; form-note&quot;).strip
  content_tag(:div, text, options, &amp;block)
end
</pre>
<p>Instead, don&#8217;t explicitly name the block parameter; just yield to it, and you prevent all the messiness of creating a new Proc object.</p>
<pre class="brush: ruby; title: ; notranslate">
def note(text, options = {})
  options[:class] = ((options[:class] || &quot;&quot;) + &quot; form-note&quot;).strip
  content_tag(:div, text, options) {|*block_args| yield(*block_args) if block_given? }
end
</pre>
<p>I don&#8217;t have benchmarks just yet, but anecdotally it has definitely slowed instance memory consumption in my apps. It&#8217;s worth taking a look at!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coffeepowered.net/2008/10/09/quick-tip-use-anonymous-blocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

