Feeds : Too-biased blog


      view feed content Passenger (Too-biased blog)   16 d and 3 h ago

So there is a lot of talk about Phusion Passenger lately and I feel the need to chime in here. David pointed out that Shopify is running on passenger which is something I announced on Twitter a few months ago.

Some context on Shopify’s installation: We launched Shopify originally on Lighttpd with FastCGI and later migrated to nginx with mongrels. Obviously we had to use HAProxy between Nginx and mongrels to avoid the dreaded “queue behind long running process” problem. We also added Monit to the mix which observed all mongrels to make sure that everything is running according to plan. After a process reaches 260 mb of memory we signal it to shut down after the next request so that a new one can start out with less memory. For this we added runit to the mix which supervises the mongrels and starts them up quickly once they hit the ground.

It’s important to note that we are not talking about a memory leak here. The reason for the 260mb ceiling comes from two issues with Ruby’s garbage collector:

  1. It allocates memory in very large chunks once the available memory gets low. This means a 140mb process increases to 260mb in a single go. It also never gives memory back to the operating system because Ruby’s GC is not able to move objects. Once it adds an object into the newly allocated space and that object remains alive, it cannot yield memory back to the OS.
  2. Because Ruby’s garbage collector uses mark and sweep it has to traverse the entire memory space in search of pointers. There are no generations that help with that. It means that GC cycles become longer and longer the more memory is available. -Rails mitigates these issues by moving a full GC run behind a HTTP response, into the time period when the process is waiting for a new request (Update: Rails doesn’t do this anymore) but performance monitoring tools such as NewRelic clearly show that average response times is directly correlated with the amount of memory used across the server farm.

Now why did we switch to Passenger? Simple: the keyword is remove moving parts.

Every additional tool you add will come with it’s own bugs. Many people I talked to over the past years considered haproxy to be the most solid piece of infrastructure in their stack but even there was a really nasty bug recently (search for request queue handling).

We treat our server farm very similar to Shopify’s codebase. We are in this for the long haul and we cannot accept complex solutions when simple ones present themselves. Maintainability of our code and servers is paramount to the long term success of our product. Yes the Mongrel setup worked very well but Passenger allowed us to remove: Nginx, Haproxy, Runit and Monit. That’s a nice refactoring!

At the same time Passenger introduced some tangible improvements. We switched to enterprise ruby to get the full benefit of the COW memory characteristics and we can absolutely confirm the memory savings of 30% some others have reported. This is many thousand dollars of savings even at today’s hardware prices. We allow Passenger to adaptively spawn more processes with demand but most of the time our application servers are running about 40 processes to handle more than a million dynamic requests a day. However, because passenger constantly despawns and respawns rails processes they always stay fresh, run short GC cycles and are generally a lot more responsive. All this means that the total amount of memory that is used by Shopify during normal operations went from average of 9GB to an average of 5GB. We evenly distributed the savings amongst more Shopify processes and more memcached space which moved our average response time from 210ms to 130ms while traffic grew 30% in the last few months.

In conclusion: I cannot see any reason to choose a different deployment strategy at this point. Its simple, complete, fast and well documented.


[Code Rails ]
View original post|Add to del.icio.us | Share

      view feed content Passenger (Too-biased blog)   [2 views] 16 d and 4 h ago

So there is a lot of talk about Phusion Passenger lately and I feel the need to chime in here. David pointed out that Shopify is running on passenger which is something I announced on Twitter a few months ago.

Some context on Shopify’s installation: We launched Shopify originally on Lighttpd with FastCGI and later migrated to nginx with mongrels. Obviously we had to use HAProxy between Nginx and mongrels to avoid the dreaded “queue behind long running process” problem. We also added Monit to the mix which observed all mongrels to make sure that everything is running according to plan. After a process reaches 260 mb of memory we signal it to shut down after the next request so that a new one can start out with less memory. For this we added runit to the mix which supervises the mongrels and starts them up quickly once they hit the ground.

It’s important to note that we are not talking about a memory leak here. The reason for the 260mb ceiling comes from two issues with Ruby’s garbage collector:

  1. It allocates memory in very large chunks once the available memory gets low. This means a 140mb process increases to 260mb in a single go. It also never gives memory back to the operating system because Ruby’s GC is not able to move objects. Once it adds an object into the newly allocated space and that object remains alive, it cannot yield memory back to the OS.
  2. Because Ruby’s garbage collector uses mark and sweep it has to traverse the entire memory space in search of pointers. There are no generations that help with that. It means that GC cycles become longer and longer the more memory is available. -Rails mitigates these issues by moving a full GC run behind a HTTP response, into the time period when the process is waiting for a new request (Update: Rails doesn’t do this anymore) but performance monitoring tools such as NewRelic clearly show that average response times is directly correlated with the amount of memory used across the server farm.

Now why did we switch to Passenger? Simple: the keyword is remove moving parts.

Every additional tool you add will come with it’s own bugs. Many people I talked to over the past years considered haproxy to be the most solid piece of infrastructure in their stack but even there was a really nasty bug recently (search for request queue handling).

We treat our server farm very similar to Shopify’s codebase. We are in this for the long haul and we cannot accept complex solutions when simple ones present themselves. Maintainability of our code and servers is paramount to the long term success of our product. Yes the Mongrel setup worked very well but Passenger allowed us to remove: Nginx, Haproxy, Runit and Monit. That’s a nice refactoring!

At the same time Passenger introduced some tangible improvements. We switched to enterprise ruby to get the full benefit of the COW memory characteristics and we can absolutely confirm the memory savings of 30% some others have reported. This is many thousand dollars of savings even at today’s hardware prices. We allow Passenger to adaptively spawn more processes with demand but most of the time our application servers are running about 40 processes to handle more than a million dynamic requests a day. However, because passenger constantly despawns and respawns rails processes they always stay fresh, run short GC cycles and are generally a lot more responsive. All this means that the total amount of memory that is used by Shopify during normal operations went from average of 9GB to an average of 5GB. We evenly distributed the savings amongst more Shopify processes and more memcached space which moved our average response time from 210ms to 130ms while traffic grew 30% in the last few months.

In conclusion: I cannot see any reason to choose a different deployment strategy at this point. Its simple, complete, fast and well documented.


[Code Rails ]
View original post|Add to del.icio.us | Share

      view feed content Interview (Too-biased blog)   24 d and 5 h ago

openvista posted their interview with me in which I talk about entrepreneurship and the early days of Shopify.



View original post|Add to del.icio.us | Share

      view feed content Interview (Too-biased blog)   24 d and 5 h ago

openvista posted their interview with me in which I talk about entrepreneurship and the early days of Shopify.



View original post|Add to del.icio.us | Share

      view feed content Rockstar Memcaching (video) (Too-biased blog)   34 d and 4 h ago

InfoQ posted the video to my rockstar memcaching presentation from ruby fringe.

Rockstar Memcaching Video



View original post|Add to del.icio.us | Share

      view feed content Rockstar Memcaching (video) (Too-biased blog)   34 d and 4 h ago

InfoQ posted the video to my rockstar memcaching presentation from ruby fringe.

Rockstar Memcaching Video



View original post|Add to del.icio.us | Share

      view feed content Rockstar Memcaching (Too-biased blog)   34 d and 4 h ago

I’m back from Rubyfringe which was hands down the best conference i’ve been to.

Pete Forde asked me to present on memcached (mem-cache-dee) after my popular blog article Secret to memcached. The talk covers different use cases such as simple html snippet stores to advanced expiry systems such as generational cache keys.

Every talk at rubyfringe was taped so I’ll update this space with the video once its online. In the meantime enjoy the slides which probably make zero sense on their own.

Download the PDF or watch it on slideshare:

Rubyfringe<object height="355" width="425"><param /><param /><param /><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=rubyfringe-1216650794678661-8" height="355" width="425"></embed></object>view presentation (tags: memcached ruby code talk)

P.S: 30 minute is the ideal length for talks at a Tech Conference.

Update: The video was posted here



View original post|Add to del.icio.us | Share

      view feed content Mobile Development (Too-biased blog)   39 d ago

I’ve been playing around with mobile development lately which is a nice change of pace. Before Shopify and Rails I used to count myself amongst the ranks of the C++ desktop developers ( go WTL!! ) so in many ways the concepts of mobile development feel like the good’ old times—without all the things that drive you up the walls.

What’s so fun about it is the innocence of it all. It’s the gold rush all over again. For example that bastard Hampton managed to sell his Wikipedia browser iPedia 50k times. Check out www.mobileorchard.com which just published an interview with him.



View original post|Add to del.icio.us | Share

      view feed content test (Too-biased blog)   44 d ago

test


[test ]
View original post|Add to del.icio.us | Share

      view feed content LHC Rap (Too-biased blog)   51 d ago

via youtube

<object height="344" width="425"><param></param><param></param><embed src="http://www.youtube.com/v/j50ZssEojtM&#38;hl=en&#38;fs=1" height="344" width="425"></embed></object>



View original post|Add to del.icio.us | Share

      view feed content Shopify Blogging (Too-biased blog)   56 d ago

Brand and community development where always the guiding principles behind Shopify and today we launched an important aspect of this: Your visitors can now comment on blog posts.

Read more about it on the shopify blog

We will provide an import tool for wordpress and other blogging systems soon (implemented as an open source shopify api app. )



View original post|Add to del.icio.us | Share

      view feed content Liquid JS (Too-biased blog)   3 months ago

Color me impressed.

Matt Mccray ported Liquid to javascript. Go here to get the gist of it (yea, bad pun)

Pretty awesome work Matt :-)

<script> Liquid.readTemplateFile = function(path) { var elem = $(path); if(elem) { return elem.innerHTML; } else { path +" can't be found."; // Or throw and error, or whatever you want... } } var tmpl = Liquid.parse("{% include 'myOtherTemplate' with current_user %}"); alert( tmpl.render({ current_user:'M@' })); </script> <script type="text/liquid" id="myOtherTemplate"> Hello, {{ current_user }}! </script>



View original post|Add to del.icio.us | Share

      view feed content Competitor Comedy (Too-biased blog)   3 months ago

Shopify got profiled last week in Practical E-Commerce as cart of the week . According to them they found 300 different Shopping cart packages, I know our market was big but that’s pretty insane.

Anyways, their Cart of the Week feature pits one Cart against another by asking a competitor to comment on the software, CNN style. In our case they asked Rick Wilson of Miva Merchant to comment on Shopify. Here is what he dislikes:

The obvious weaknesses I saw were the limits on what they called ‘enterprise’ level offering of only 10,000 SKUs. The other major weakness is the product is built using Ruby On Rails. Ruby On Rails seems to be a development environment with a lot of future possibilities, but as a general rule you don’t want your revenue-generating product to be based on cutting edge technology. There’s a lot of unforeseeable pitfalls in that area.

(emphasis mine).

So to deconstruct the first part of this argument let me just say that we have millions of products in Shopify right now and it’s a pure business decision to limit SKUs to 10k and has nothing to do with the software. There are millions of products in the database. In fact i’d buy Rick lunch if Shopify isn’t right now handling twice the traffic any given Miva Merchant store has ever sustained.

What’s left is the advice that you shouldn’t run a revenue-generating web site based on cutting edge technology. I don’t think I have to point out how ridiculous that statement is. First of all I presume that perl was pretty cutting edge ( definitely more than ruby is today ) in 1998 when Miva was written and also we are talking about bloody Miva Merchant here, the e-commerce system that runs on a proprietary closed source database that is known for corruption issues after several hundred products. Not only that, it seems to be one of their main sources of revenue: For 129$ setup + 20$ a month you can get some support and basic database recovery. Unfortunately:

** Due to the nature of database problems not all database corruption can be covered under this package

Isn’t it nice that you never have to worry about such tactics with hosted systems and SaaS packages like Shopify?



View original post|Add to del.icio.us | Share

      view feed content Rockstar Memcaching (Too-biased blog)   4 months ago

I’m back from Rubyfringe which was hands down the best conference i’ve been to.

Pete Forde asked me to present on memcached (mem-cache-dee) after my popular blog article Secret to memcached. The talk covers different use cases such as simple html snippet stores to advanced expiry systems such as generational cache keys.

Every talk at rubyfringe was taped so I’ll update this space with the video once its online. In the meantime enjoy the slides which probably make zero sense on their own.

Download the PDF or watch it on slideshare:

Rubyfringe<object height="355" width="425"><param /><param /><param /><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=rubyfringe-1216650794678661-8" height="355" width="425"></embed></object>view presentation (tags: memcached ruby code talk)

P.S: 30 minute is the ideal length for talks at a Tech Conference.

Update: The video was posted here



View original post|Add to del.icio.us | Share

      view feed content Shopify Sys Admin (Too-biased blog)   [1 views] 4 months ago

If you love servers you should consider applying for our system administrator position . Flexible work hours and you get to work with all the coolest and latest technologies and a fantastic team.



View original post|Add to del.icio.us | Share

      view feed content One million integers?! (Too-biased blog)   4 months ago

This is a great general purpose interview tip:

If you don’t know how to answer a question because it’s way outside of your expertise simply give it your best guess and negate the question.

via youtube:

<object height="344" width="425"><param></param><param></param><embed src="http://www.youtube.com/v/k4RRi_ntQc8&#38;hl=en&#38;fs=1" height="344" width="425"></embed></object>

This can sometimes have pretty impressive results.



View original post|Add to del.icio.us | Share

      view feed content Gecko/Webkit Screenshots (Too-biased blog)   [9 views] 6 months ago

For our Shopify Product Search we needed a good way to Screenshot web pages. There are some services on the web for this but we ended up building it but none of them fit our needs. They were either way to expensive, they didn’t produce nearly the quality we needed or they didn’t offer an API at all.

Our solution was to install a headless X server in our server farm which runs firefox 2.0. We used a python GTK automation script which navigates the Firefox instance to the page and then dumps the framebuffer into a png file when done. This works well enough but i’d like something more robust for a different project.

Ideally I’d like someone to build a screenshot tool based on Gecko or Webkit which can simply take an url and spit out an png. A dependency on an running X server is acceptable but I’d rather not have it running all the time because it complicates deployment a lot. It has to run on Linux and must not depend on a shared global resource, i.e. you should be able to take two screenshots at the same time.

If you know of a tool like the one I describe or if you think you could build something like this for me please contact me. This may be paid open source work.



View original post|Add to del.icio.us | Share

      view feed content Twitter (Too-biased blog)   [1 views] 6 months ago

I need more followers on twitter :-)



View original post|Add to del.icio.us | Share

      view feed content Canadian Citizenship (Too-biased blog)   7 months ago

Today I got my Canadian citizenship.

Both Germany and Canada allow multiple citizenships so I’m allowed to carry both. Geographical redundancy accomplished. Next step is to apply for my Canadian passport so that I can instant failover :-)



View original post|Add to del.icio.us | Share

      view feed content Database situps (Too-biased blog)   7 months ago

Todd Hoff in his love letter to Amazon’s SimpleDB

SimpleDB shifts work out of the database and onto programmers which is why the SimpleDB programming model sucks: it requires a lot more programming to do simple things. I’ll argue however that this is the kind of suckiness programmers like. Programmers like problems they can solve with more programming. We don’t even care how twisted and inelegant the code is because we can make it work. And as long as we can make it work we are happy.

I can’t think of what drove him to write this. This argument is directly contradicted by the success of Rails.



View original post|Add to del.icio.us | Share

      view feed content Active Shipping (Too-biased blog)   7 months ago

James released his development version of Active Shipping to github

Active Shipping does what Active Merchant did for payment gateways: Provide one unified API to talk to all the Parcel Services on the web. Given a weight, a to and a from address you can calculate the Shipping costs of every supported Shipping Service. All the complexity of the task is handled by the library.

Active Shipping has been in production use with Shopify since the beginning of the year.

API: require 'active_shipping' include ActiveMerchant::Shipping # Package up a poster and a Wii for your nephew. packages = [ Package.new( 100, # 100 grams [93,10], # 93 cm long, 10 cm diameter :cylinder => true), # cylinders have different volume calculations Package.new( (7.5 * 16), # 7.5 lbs, times 16 oz/lb. [15, 10, 4.5], # 15x10x4.5 inches :units => :imperial) # not grams, not centimetres ] # You live in Beverly Hills, he lives in Ottawa origin = Location.new( :country => 'US', :state => 'CA', :city => 'Beverly Hills', :zip => '90210') destination = Location.new( :country => 'CA', :province => 'ON', :city => 'Ottawa', :postal_code => 'K1P 1J1') # Find out how much it'll be. ups = UPS.new(:login => 'auntjudy', :password => 'secret', :key => 'xml-access-key') response = ups.find_rates(origin, destination, packages) ups_rates = response.rates.sort_by(&:price).collect {|rate| [rate.service_name, rate.price]} # => [["UPS Standard", 3936], # ["UPS Worldwide Expedited", 8682], # ["UPS Saver", 9348], # ["UPS Express", 9702], # ["UPS Worldwide Express Plus", 14502]] # Check out USPS for comparison... usps = USPS.new(:login => 'developer-key') response = usps.find_rates(origin, destination, packages) usps_rates = response.rates.sort_by(&:price).collect {|rate| [rate.service_name, rate.price]} # => [["USPS Priority Mail International", 4110], # ["USPS Express Mail International (EMS)", 5750], # ["USPS Global Express Guaranteed Non-Document Non-Rectangular", 9400], # ["USPS GXG Envelopes", 9400], # ["USPS Global Express Guaranteed Non-Document Rectangular", 9400], # ["USPS Global Express Guaranteed", 9400]]



View original post|Add to del.icio.us | Share

      view feed content Git and Capistrano (Too-biased blog)   7 months ago

Git support in the latest capistrano works very well but there are two gotcha’s I ran into, i’ll document them here so that Google can pick it up.

The first problem was the bizarre error message I got when I forgot to push my changes to the deployment repository:

** [err] Needed a single revision ** [err] Needed a single revision [...]

Needed a single revision, well then. Git seems to use the rare other meaning of “single” which means “existing” or “valid”.

The other problem was harder to track down. Capistrano would simply hang forever after the update_code task. It would also leave the cached_copy directories in a totally invalid state on some servers which required manual rm -rf. Thanks go to Scott Raymond on Twitter for pointing me in the right direction. It seems that we have too many App servers for a stock sshd_config and It triggers some kind of throttling logic which git cannot deal with.

If you are deploying to medium to large server farms better head over to your git box and increase the MaxStartups now.

MaxStartups 10000:1:10000

This solves the problem.



View original post|Add to del.icio.us | Share

      view feed content Work on Shopify (Too-biased blog)   7 months ago

Are you in Ottawa, Canada or willing to relocate? Want to work in the coolest office in town? Would you like to work on a high profile rails application with millions of users? Do you want to work with some of the best rails programmers out there?

Please email me at tobi@jadedpixel.com. Please include a piece of code you are especially proud of or point me to some of your open source work. If you include a CV please attach it as PDF.



View original post|Add to del.icio.us | Share

      view feed content Wtf? (Too-biased blog)   7 months ago
if false var = nil end p var.nil? #=> true ???



View original post|Add to del.icio.us | Share

      view feed content On Return (Too-biased blog)   8 months ago

ActiveSupport has this really nice returning tool. It allows you to rewrite the common pattern of initialization and returning a object from am method like this:

returning something = Thing.new do something.this something.that end

We were wondering if there may be a performance issue with the tool so a quick benchmark showed the following:

user system total real def n; i = 0; return i; end 0.510000 0.000000 0.510000 ( 0.520417) def n; i = 0; i ; end 0.340000 0.000000 0.340000 ( 0.344569) def n; returning i = 0 do; end; end 0.730000 0.000000 0.730000 ( 0.726853)

Those numbers are after 1m runs on a core 2 duo laptop. As you can see the difference is very minor. Code vanity can safely prevail. Full Benchmark



View original post|Add to del.icio.us | Share

      view feed content Shopify stores are gorgeous (Too-biased blog)   8 months ago

The quality of Shopify stores being launched every day really boggles my mind. Just look at those 3 most recent examples:

ClothMoth

ZipRC

Destinative

If you like pretty stores, i recommend subscribing to the Shop of the moment feature or head over to our http://www.shopify.info/screenshots/ page.

Speaking of which, our screenshot page is actually powered from the RSS feed of the Shop of the moment category on our blog. Shopify.info is powered by radiant and we use the RSS Reader extension with some minor modifications and some clever CSS. This is a great example of how we can reduce content production work by re-using various RSS feeds. Another example of this is our feature page where we list all the Payment gateways Shopify currently supports. This comes straight from a RSS feed generated by the Shopify application and so it’s automatically always up-to-date.



View original post|Add to del.icio.us | Share

      view feed content Money as debt (Too-biased blog)   8 months ago

Paul Grignon’s 47-minute animated presentation of “Money as Debt” tells in very simple and effective graphic terms what money is and how it is being created.

via google video :

<embed src="http://video.google.com/googleplayer.swf?docId=-9050474362583451279&#38;hl=en-CA"> </embed>



View original post|Add to del.icio.us | Share

      view feed content many many DJs (Too-biased blog)   [10 views] 8 months ago

I just checked in a new version of the delayed_job plugin which handles background processing of long running tasks in Shopify.

DJ is now fully parallelizable and does not require any global locking anymore. This means that you can run as many worker processes as you want across your server farm if you need to speed up the queue processing.

This became necessary when we kicked off a full search server reindex recently and realized that a single worker process would require 48 hours to complete the task. Such is the burden of success.

This feature is DB independent and doesn’t rely on row level locking. I found that row level locking lead to a lot of unnecessary lock timeout waits. If you are updating from the previous version of the plugin please be advised that there are two new columns you have to add.

Grab the latest version form http://github.com/tobi/delayed_job/tree/master



View original post|Add to del.icio.us | Share

      view feed content Mysql Locking (Too-biased blog)   9 months ago

Small plugin for using the global lock service of mysql in your rails app: Locking plugin

Great if you have long running cron tasks or require exclusive access to some resources.

Example: Invoice.aquire_lock("Shopify billing") do # Can only run once across your server farm Invoice.find_all_due.each { |invoice| invoice.collect_payment! } end



View original post|Add to del.icio.us | Share

      view feed content Shopify SCM (Too-biased blog)   9 months ago

So we went from Darcs -> SVN -> Mercurial -> Git in just over 3 years and without losing a single commit in the process. 4th one is a real winner though. If you don’t use git yet you should really check it out.

If you are unfamiliar with GIT, I recommend watching Peepcode’s introduction. We have a site-license for peepcode at jadedPixel and often run the latest screencasts on the big LCD in the office during lunch break. Its great.



View original post|Add to del.icio.us | Share