Posted by Chris Blackburn Tue, 10 Jun 2008 17:31:00 GMT

Regarding Ruby strings, surprisingly, embedding substitutions in double quoted strings perform better than using the single-quoted strings and the array append operator

require 'profilings'
include PeepcodeProfiler

MAX = 900000

###
# Quoted Strings
###

time_this("Single Quotes (append):") {
  x = ''
  (0..MAX).each do |i|
    x = 'This is a test ' << i.to_s
  end
}
Timings for Single Quotes (append):
Thread ID: 218880
Total: 11.150243

 %self     total     self     wait    child    calls  name
 58.47     11.15     6.52     0.00     4.63        1  Range#each (ruby_runtime:0}
 20.99      2.34     2.34     0.00     0.00   900001  String#<< (ruby_runtime:0}
 20.55      2.29     2.29     0.00     0.00   900001  Fixnum#to_s (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        1  <Class::Object>#allocate (ruby_runtime:0}
  0.00     11.15     0.00     0.00    11.15        0  PeepcodeProfiler#time_this (./profilings.rb:8}

... and the faster double-quotes append:

time_this("Double Quotes (append):") {
  x = ""
  (0..MAX).each do |i|
    x = "This is a test #{i}"
  end
}
Timings for Double Quotes (append):
Thread ID: 218880
Total: 7.385500

 %self     total     self     wait    child    calls  name
 66.64      7.39     4.92     0.00     2.46        1  Range#each (ruby_runtime:0}
 33.36      2.46     2.46     0.00     0.00   900001  Fixnum#to_s (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        1  <Class::Object>#allocate (ruby_runtime:0}
  0.00      7.39     0.00     0.00     7.39        0  PeepcodeProfiler#time_this (./profilings.rb:8}

Even more interesting, is how the string substitution barely blinks when it is in the middle of the string vs. at the end. To get the same effect using 2 appends with single-quoted strings, takes twice as long as double-quoted strings with substitution in the middle:

# Very slow
# BEGIN single_quotes_middle
time_this("Single Quotes: (in middle)") {
  x = ''
  (0..MAX).each do |i|
    x = 'This is a test ' << i.to_s << 'x'
  end
}
# END single_quotes_middle
Timings for Single Quotes: (in middle)
Thread ID: 218880
Total: 15.146328

 %self     total     self     wait    child    calls  name
 56.51     15.15     8.56     0.00     6.59        1  Range#each (ruby_runtime:0}
 28.00      4.24     4.24     0.00     0.00  1800002  String#<< (ruby_runtime:0}
 15.49      2.35     2.35     0.00     0.00   900001  Fixnum#to_s (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        1  <Class::Object>#allocate (ruby_runtime:0}
  0.00     15.15     0.00     0.00    15.15        0  PeepcodeProfiler#time_this (./profilings.rb:8}
# BEGIN double_quotes_middle
time_this("Double Quotes (in middle):") {
  x = ""
  (0..MAX).each do |i|
    x = "This is a test #{i}x"
  end
}
# END double_quotes_middle
Timings for Double Quotes (in middle):
Thread ID: 218880
Total: 7.410465

 %self     total     self     wait    child    calls  name
 65.51      7.41     4.85     0.00     2.56        1  Range#each (ruby_runtime:0}
 34.49      2.56     2.56     0.00     0.00   900001  Fixnum#to_s (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00        1  <Class::Object>#allocate (ruby_runtime:0}
  0.00      7.41     0.00     0.00     7.41        0  PeepcodeProfiler#time_this (./profilings.rb:8}

Look for my, soon-to-be-published, Peepcode book for more tips and recipes on how to scale Ruby on Rails.

Posted by admin Fri, 29 Sep 2006 08:00:00 GMT

Working on shopping cart abandonment solutions every day allows me to see the best and worst cart designs and everything in between. Here are six tips that I would give to every shopping cart designer to help them stay out of the latter category.

  1. Remove Obstacles – Remove as many obstacles, and steps, as possible in the process from product selection to order completion. This is pretty general but sometimes it is not so obvious. The concept of a shopping cart is not complex. It should be a mechanism to allow a shopper to select multiple products then purchase them with a single transaction. The process should be as quick and painless as possible for both anonymous and registered shoppers. Think of every click and keypress, selecting product to checkout process, as an obstacle. Remove the ones that are not absolutely necessary.
  2. Enable the Anonymous Shopper – Don’t require the shopper to register with the site in order to purchase something. If we visit our local drugstore to purchase a birthday card for a relative, does the clerk ask us to register for an account first? Probably not. Many online stores ask the shopper to register for an account before completing their order— and while there are benefits to promoting shopper registration (see next tip), requiring it raises cart abandonment rates.
  3. Empower the Registered Shopper – Optional user registration is a good thing, but probably not for the reasons most people think. The registration process should first and foremost provide benefits to the shopper, vendor (site owner) benefits are secondary. Make registration appealing by allowing registered users to complete purchases quicker. After all, if a registered user logs in, we already have much of their information and email address. Amazon does a great job in this category. Not only do they provide a “one-click” ordering option for registered shoppers, they keep track of the types of things we buy and present cross-sell/up-sell product as we shop. Most brick-and-mortar stores offer a discount if we have a “frequent-shopper” (data-mining) card. E-commerce can do the same thing for registered users.
  4. Streamline the Registration Process – Make the registration process part of the shopping cart. We are collecting billing and shipping information from the shopper anyway. Ask them if they want to save it so they don’t have to enter it again. If they agree, store their information. The next time they login to purchase we use their information to fill-in billing and shipping details by default, which they can change if desired.
  5. Provide a Persistent Cart – If the shopper puts items in their cart, closes the browser without completing a purchase, then comes back to the site later, their shopping cart should contain the same items. Cart persistence can be accomplished through the use of persistent cookies. It may also be beneficial to look for the shopping cart id within the HTTP request itself. In this way we can send an email to the shopper containing a link back to the cart with an embedded cart id. This emailed link can even be used from a different computer or browser that doesn’t contain the cookie.
  6. Collect Email Address First – Too often anonymous users are asked for their email address last. This is a mistake because the email address is the only “single piece” of information we can use to contact the shopper after they abandon their cart. If we collect email address up front, the shopper may abandon but we can send them an email prompting them to return to complete their purchase. We can even offer them a discount.