<?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>Idle Hacking &#187; Curb</title>
	<atom:link href="http://www.idle-hacking.com/tag/curb/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.idle-hacking.com</link>
	<description>Ruby, XUL/Javascript, C/C++, and more...</description>
	<lastBuildDate>Tue, 11 May 2010 02:15:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>ANN &#8211; Curb 0.3.1 magic multi release</title>
		<link>http://www.idle-hacking.com/2009/03/ann-curb-031-magic-multi-release/</link>
		<comments>http://www.idle-hacking.com/2009/03/ann-curb-031-magic-multi-release/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 02:42:11 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/?p=577</guid>
		<description><![CDATA[It&#8217;s been nearly 8 months, since I decided to add multi interface support to curb.  Now we have a new release on rubyforge (0.3.1) The major changes includes: Add multi interface support Avoid blocking other ruby threads while in a easy perform Add support for HTTP DELETE Requests Add basic support for HTTP PUT Requests [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been nearly 8 months, since I decided to add multi interface support to curb.  Now we have a new release on rubyforge (0.3.1)</p>
<p><strong>The major changes includes:</strong></p>
<ul>
<li>Add multi interface support</li>
<li>Avoid blocking other ruby threads while in a easy perform</li>
<li>Add support for HTTP DELETE Requests</li>
<li>Add basic support for HTTP PUT Requests (not from a file)</li>
<li>Ruby 1.9.1 Support</li>
<li>Upgraded packaging and dependencies for build and package</li>
<li>Upgraded test harness to run stressing the libcurl http code base</li>
<li>Incorporated 8 months of testing and development through github contributors</li>
</ul>
<p><span id="more-577"></span></p>
<p>The addition of Multi interface means it&#8217;s now possible to issue thousands of request simultaneously with a single ruby thread.</p>
<p>To highlight the added support of the Multi interface here is an example that makes 5 requests to some major sites in parallel.</p>
<pre lang="ruby">require 'rubygems'
require 'curb'
responses = {}
requests = ["http://www.google.com/",
            "http://www.yahoo.com/",
            "http://www.ebay.com/",
            "http://www.amazon.com/",
            "http://www.msn.com/",
            "http://www.google.co.uk/",
            "http://www.ruby-lang.org/"]
m = Curl::Multi.new
# add a few easy handles
requests.each do |url|
  responses[url] = ""
  c = Curl::Easy.new(url) do|curl|
    curl.follow_location = true
    curl.on_body{|data| responses[url] &lt;&lt; data; data.size }
    curl.on_complete{|cl| puts "done #{curl.last_effective_url}" }
  end
  m.add(c)
end
idle_count = 0
m.perform do
  idle_count += 1
end

requests.each do|url|
  puts "#{url} responded with #{responses[url].size} bytes"
end
puts "idled: #{idle_count} times"</pre>
<p>To install:</p>
<pre>gem install curb</pre>
<p>Enjoy!</p>
<p><strong>Update:</strong></p>
<p>Removed a GC.start inside the perform loop, was only there to verify objects were being correctly collected e.g. testing purposes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2009/03/ann-curb-031-magic-multi-release/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Curb gits Forked</title>
		<link>http://www.idle-hacking.com/2008/08/curb-gits-forked/</link>
		<comments>http://www.idle-hacking.com/2008/08/curb-gits-forked/#comments</comments>
		<pubDate>Mon, 25 Aug 2008 11:41:07 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/?p=411</guid>
		<description><![CDATA[Git has really made it much easier to share code.  ~23 days after posting curb to github, it now has a fork that&#8217;s added direct methods for making a PUT and DELETE request.]]></description>
			<content:encoded><![CDATA[<p>Git has really made it much easier to share code.  ~23 days after posting <a href="http://github.com/taf2/curb/tree/master">curb to github</a>, it now has a fork that&#8217;s added direct methods for making a PUT and DELETE request.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/08/curb-gits-forked/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding ruby thread scheduling to curb</title>
		<link>http://www.idle-hacking.com/2008/08/adding-ruby-thread-scheduling-to-curb/</link>
		<comments>http://www.idle-hacking.com/2008/08/adding-ruby-thread-scheduling-to-curb/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 02:17:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2008/08/adding-ruby-thread-scheduling-to-curb/</guid>
		<description><![CDATA[Ruby threads require care when writing an extension &#8211; especially when the extension does anything over a network. In the case of curb, it&#8217;s often used as a replacement to the built in ruby net/http library. The basic experiment goes, you use a web service like, amazon or google within your web application. Let&#8217;s say [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://ruby-doc.org/core/classes/Thread.html">Ruby threads</a> require care when writing an extension &#8211; especially when the extension does anything over a network.   In the case of <a href="http://curb.rubyforge.org/">curb</a>, it&#8217;s often used as a replacement to the <a href="http://www.ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html">built in ruby net/http library</a>.<br />
<span id="more-139"></span><br />
The basic experiment goes, you use a web service like, amazon or google within your web application.   Let&#8217;s say you&#8217;ve just started porting some parts of your <a href="http://rubyonrails.com/">rails</a> application to <a href="http://merbivore.com/">merb</a>, or even just a <a href="http://mongrel.rubyforge.org/web/mongrel/classes/Mongrel/HttpHandler.html">simple mongrel handler</a>.  You&#8217;re hoping to increase the throughput of this application by taking advantage of the increased concurrency gain by using less locking.  This works great testing locally.  Only one thing we forgot, the threads in ruby are cooperative.  This means, any-one thread can block all other threads from running.  So, while we spent this extra time and energy to rewrite specific parts of our application to increase its concurrency &#8211; we forgot that ruby threads don&#8217;t always mix well with native extensions.  Occasionally,  one of these service calls will take a bit longer then normal.  When this happens, all our threads are blocked.  To make matters worse, we&#8217;re actually not seeing too much of a throughput improvement after making our changes.  When an extension is running it&#8217;s execution is blocking all other ruby threads, unless it calls rb_thread_select or other thread scheduling methods.</p>
<p>The few tests we did show a speed improvement for a single request, but multiple concurrent requests or throughput has stayed about the same, because the Curl::Easy.perform call is blocking all other ruby threads from running at the same time.  Meaning, we mightiest well just leave our calls in the rails controller and move on right?</p>
<p>Well, by now you probably realized I&#8217;m not that kind of programmer&#8230;  Giving up like this isn&#8217;t why I like to write code&#8230; Doing a little more digging I realized the answer is rb_thread_select.</p>
<p>Using rb_thread_select in place of select and making calls to libcurl&#8217;s multi interface instead of curl_easy_perform, I&#8217;ve made it possible to run multiple Curl::Easy.perform calls concurrently.   You&#8217;ll still probably see much higher throughput using the Curl::Multi interface, but this should help those using the more direct Curl::Easy interface.  I also updated the Curl::Multi interface to use ruby&#8217;s rb_thread_select, meaning it can be used within multiple ruby threads as well.</p>
<p>Remember this does not mean I made Curl::Easy or Curl::Multi thread safe, but it means multiple instances of those objects can be used within multiple threads, running in parallel.</p>
<p>You can get <a href="http://github.com/taf2/curb/tree/master">my curb changes from github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/08/adding-ruby-thread-scheduling-to-curb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>curb to github</title>
		<link>http://www.idle-hacking.com/2008/07/curb-to-github/</link>
		<comments>http://www.idle-hacking.com/2008/07/curb-to-github/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 15:35:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[github]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2008/07/curb-to-github/</guid>
		<description><![CDATA[I&#8217;ve made a few more improvements to curb and decided keeping track of all these patches is too much. I&#8217;m now tracking my changes on github, and hopefully the curb author will reappear to review the changes soon, so we can get them released in gem form.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve made a few more improvements to <a href="http://curb.rubyforge.org">curb</a> and decided keeping track of all these patches is too much.  I&#8217;m now tracking my changes on <a href="http://github.com/taf2/curb/tree/master">github</a>, and hopefully the curb author will reappear to review the changes soon, so we can get them released in gem form.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/07/curb-to-github/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New curb patch, on_success, and on_failure</title>
		<link>http://www.idle-hacking.com/2008/07/new-curb-patch-on_succes-and-on_failure/</link>
		<comments>http://www.idle-hacking.com/2008/07/new-curb-patch-on_succes-and-on_failure/#comments</comments>
		<pubDate>Thu, 10 Jul 2008 19:50:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[libcurl]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2008/07/new-curb-patch-on_succes-and-on_failure/</guid>
		<description><![CDATA[I added a new callback hook to curb on_success and on_failure. They work as advertised and are esspecially useful when using the Curl::Multi interface from my last patch. gc = Curl::Easy.new("http://www.google.com/") gc.on_success{&#124;curl&#124; puts curl.body_str } yc = Curl::Easy.new("http://www.yahoo.com/") yc.on_success{&#124;curl&#124; puts curl.body_str } mc = Curl::Multi.new mc.add(gc) mc.add(yc) mc.perform What&#8217;s nice about this, is imagine you [...]]]></description>
			<content:encoded><![CDATA[<p>I added a new callback hook to <a href="http://curb.rubyforge.org/">curb </a>on_success and on_failure.  They work as advertised and are esspecially useful when using the Curl::Multi interface from my <a href="http://taf2-patches.s3.amazonaws.com/curb-multi.patch">last patch</a>.</p>
<pre lang="ruby">gc = Curl::Easy.new("http://www.google.com/")
gc.on_success{|curl| puts curl.body_str }
yc = Curl::Easy.new("http://www.yahoo.com/")
yc.on_success{|curl| puts curl.body_str }

mc = Curl::Multi.new
mc.add(gc)
mc.add(yc)

mc.perform</pre>
<p><span id="more-137"></span><br />
What&#8217;s nice about this, is imagine you have some process running and want to add requests to it.  When you add the request you also want to register a callback to handle the success or failure cases.  Before this patch you&#8217;d have to check the content length and listen to the on_body handler.  The problem with that, is the content length header is not always correct.  These callbacks are guaranteed, because they happen during the cleanup process for each handle.</p>
<p>As an aside they&#8217;ll work using the Easy handle diretly.</p>
<p>Here&#8217;s the <a href="http://taf2-patches.s3.amazonaws.com/curb-multi-with-callbacks">patch</a>, enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/07/new-curb-patch-on_succes-and-on_failure/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Updated curb multi interface patch</title>
		<link>http://www.idle-hacking.com/2008/07/updated-curb-multi-interface-patch/</link>
		<comments>http://www.idle-hacking.com/2008/07/updated-curb-multi-interface-patch/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 14:34:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[libcurl]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2008/07/updated-curb-multi-interface-patch/</guid>
		<description><![CDATA[I&#8217;ve updated my patch for curb multi interface and tested against valgrind for memory leaks. So far the patch looks stable. I&#8217;m still waiting to hear from the curb author. In the meantime here&#8217;s how to apply the patch if you&#8217;re interested. Check out curb trunk svn co svn://rubyforge.org/var/svn/curb/TRUNK/curb Grab my latest patch wget http://taf2-patches.s3.amazonaws.com/curb-multi.patch [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve updated my patch for curb multi interface and tested against valgrind for memory leaks.  So far the patch looks stable.  I&#8217;m still waiting to hear from the curb author.  In the meantime here&#8217;s how to apply the patch if you&#8217;re interested.</p>
<h4>Check out curb trunk</h4>
<pre lang="bash">svn co svn://rubyforge.org/var/svn/curb/TRUNK/curb</pre>
<h4>Grab my latest patch</h4>
<pre lang="bash">wget http://taf2-patches.s3.amazonaws.com/curb-multi.patch</pre>
<h4>Apply the patch</h4>
<pre lang="bash">patch -p0 &lt; curb-multi-3.patch</pre>
<p><span id="more-135"></span></p>
<h4>Rebuild and test curb</h4>
<pre lang="bash">rake test</pre>
<h4>Package and install</h4>
<pre lang="bash">
rake package
sudo gem install pkg/curb-0.2.0.gem</pre>
<p>In the patch I updated the curb version number.  This may of course change, based on whether the patch is accepted or not.  In the meantime, would be great to get a few people to try the patch and provide feedback and or bugs. Thanks!</p>
<p>Update (example usage):</p>
<pre lang="ruby">
  responses = {}
  requests = ["http://www.google.co.uk/", "http://www.ruby-lang.org/"]
  m = Curl::Multi.new
  # add a few easy handles
  requests.each do |url|
    responses[url] = ""
    c = Curl::Easy.new(url) do|curl|
      curl.follow_location = true
      curl.on_body{|data| responses[url] << data; data.size }
    end
    m.add(c)
  end

  m.perform do
    puts "idling... can do some work here, including add new requests"
  end

  requests.each do|url|
    puts responses[url]
  end
</pre>
<p>Here's a performance comparison using ruby's native threads vs curb multi interface to make up to 400 concurrent requests. You can see a huge pay off in performance at the 50 concurrent requests.</p>
<p><a href="http://bp3.blogger.com/_noMZrsXccGg/SGzspOAlLOI/AAAAAAAAAIE/ReFWOt2rdR4/s1600-h/benchmark10.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5218806261094886626" style="cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_noMZrsXccGg/SGzspOAlLOI/AAAAAAAAAIE/ReFWOt2rdR4/s400/benchmark10.png" border="0" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/07/updated-curb-multi-interface-patch/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>curb meet multi interface</title>
		<link>http://www.idle-hacking.com/2008/07/curb-meet-multi-interface/</link>
		<comments>http://www.idle-hacking.com/2008/07/curb-meet-multi-interface/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 21:04:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[libcurl]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2008/07/curb-meet-multi-interface/</guid>
		<description><![CDATA[I spent the day working on adding multi interface support to curb. I really like the curb ruby interface and with a little work can now use the same Curb::Easy interface and run the handles through the asynchronous Curb::Multi interface. The patch hasn&#8217;t been rigorously tested, but hey not bad for my first day. Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I spent the day working on adding multi interface support to curb.  I really like the curb ruby interface and with a little work can now use the same Curb::Easy interface and run the handles through the asynchronous Curb::Multi interface.  The patch hasn&#8217;t been rigorously tested, but hey not bad for my first day.<br />
<a href="http://xullicious.com/curb_multi.patch">Here&#8217;s the patch</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/07/curb-meet-multi-interface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>benchmarking curb/net::http/evdispatch</title>
		<link>http://www.idle-hacking.com/2008/06/benchmarking-curbnethttpevdispatch/</link>
		<comments>http://www.idle-hacking.com/2008/06/benchmarking-curbnethttpevdispatch/#comments</comments>
		<pubDate>Wed, 04 Jun 2008 16:51:00 +0000</pubDate>
		<dc:creator>taf2</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Curb]]></category>
		<category><![CDATA[libcurl]]></category>
		<category><![CDATA[libev]]></category>
		<category><![CDATA[Net/HTTP]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.idle-hacking.com/2008/06/benchmarking-curbnethttpevdispatch/</guid>
		<description><![CDATA[I started to put together some benchmarks to validate my work on evdispatch. Here&#8217;s what I have so far&#8230; Curb as a pure C extension runs on the main ruby thread, meaning no ruby threads can be schedule while it&#8217;s blocking. It uses the easy curl interface meaning it&#8217;s all blocking. This makes it very [...]]]></description>
			<content:encoded><![CDATA[<p>I started to put together some benchmarks to validate my work on <a href="http://evdispatch.rubyforge.org/">evdispatch</a>.  Here&#8217;s what I have so far&#8230;</p>
<p><a href="http://curb.rubyforge.org/">Curb</a> as a pure C extension runs on the main ruby thread, meaning no ruby threads can be schedule while it&#8217;s blocking.  It uses the easy curl interface meaning it&#8217;s all blocking.  This makes it very easy to use and for single requests it&#8217;s great.  For multiple requests, it&#8217;s as though all the requests are made one after the other in serial.<br />
<span id="more-122"></span><br />
Net::HTTP + Thread is really good, it runs fast and really doesn&#8217;t start to show performance issues until it starts to exceed 20 concurrent requests.</p>
<p>Evdispatch is good for when you start to pass the 50 concurrent requests.  It suffers from some stability issues at the moment, as time permits I&#8217;ll work on fixing them.</p>
<h3>Net::HTTp vs Evdispatch vs Curb for 50 concurrent requests.</h3>
<p><a href="http://bp2.blogger.com/_noMZrsXccGg/SEbMEd2Z8II/AAAAAAAAAFE/-LuXKsH5-po/s1600-h/benchmark10.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5208074396204920962" style="cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_noMZrsXccGg/SEbMEd2Z8II/AAAAAAAAAFE/-LuXKsH5-po/s400/benchmark10.png" border="0" alt="" /></a></p>
<h3>Net::HTTP vs Evdispatch for 50 concurrent requests</h3>
<p><a href="http://bp3.blogger.com/_noMZrsXccGg/SEbMmfuup8I/AAAAAAAAAFM/vqb9rVLyZRw/s1600-h/benchmark10.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5208074980825147330" style="cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_noMZrsXccGg/SEbMmfuup8I/AAAAAAAAAFM/vqb9rVLyZRw/s400/benchmark10.png" border="0" alt="" /></a></p>
<h3>Net::HTTP vs Evdispatch for 400 concurrent requests</h3>
<p><a href="http://bp2.blogger.com/_noMZrsXccGg/SEbM1j0wMnI/AAAAAAAAAFU/04MzjrTUsjA/s1600-h/benchmark100.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img id="BLOGGER_PHOTO_ID_5208075239622193778" style="cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_noMZrsXccGg/SEbM1j0wMnI/AAAAAAAAAFU/04MzjrTUsjA/s400/benchmark100.png" border="0" alt="" /></a></p>
<p>The x axis is number of requests and the y axis is time per request.  <a href="http://evdispatch.rubyforge.org/svn/trunk/test/load_test.rb">My benchmark code is here.</a>.  For most uses Net::HTTP should be plenty fast when making concurrent requests.   I would definitely  keep an eye on the <a href="http://rev.rubyforge.org/rdoc/">rev.rubyforge.org</a> project.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.idle-hacking.com/2008/06/benchmarking-curbnethttpevdispatch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
