Archive for the ‘Coding Tips’ Category

If you’re getting a failure from ‘rvm install rbx’ during the ‘Configuring rbx’ stage, and your logfile looks like:

[2011-05-20 23:22:41] /Users/austinmills/.rvm/wrappers/ruby-1.8.7-p302/rake install
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems.rb:827:in `report_activate_error': Could not find RubyGem rake (>= 0) (Gem::LoadError)
	from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems.rb:261:in `activate'
	from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems.rb:68:in `gem'
	from /usr/bin/rake:18

Then you just need to make sure that rake is installed in your global gemset (‘rvm use 1.8.7@global’ and ‘gem install rake’).

Read Full Post »

After trying some other load-testing tools, I found Tsung, a load-testing application written in Erlang to take advantage of that language’s concurrency support. It scales well (it’s been used to simulate tens of thousands of users), it supports forms and HTTP sessions, and includes some niceties like proxy recording, ‘thinktime’ support, and a choice of random or ordered traffic.

Not having a physical server handy to run Tsung isn’t a big obstacle; I just used an Amazon EC2 instance (an xlarge turned out to be more than enough, you could probably get 100s of users on a medium), which due to being rentable by the hour is great for a short-term need like occasional load-testing. I put one of Alestic’s Ubuntu images on the EC2 instance, and then it’s just a few short steps to install Tsung on the machine (we’ll call it ‘tsunghost’):

  1. sudo apt-get install erlang
  2. sudo apt-get install erlang-src
  3. sudo apt-get install gnuplot-nox sudo apt-get install libtemplate-perl libhtml-template-perl libhtml-template-expr-perl
  4. Download the latest from http://tsung.erlang-projects.org/dist/ and install it (the usual configure, make, make install). I prefixed it into /opt/tsung just to keep it a little cleaner, so the following will reflect that.

Update: Ben says in the comments, “Tsung now has Ubuntu packages, so you don’t need to compile. You can grab the latest deb at http://tsung.erlang-projects.org/dist/ubuntu/ .  Then just sudo dpkg -i on it.”

The first thing you’ll want to do is record a sample web session. Start Tsung in record mode with ‘/opt/bin/tsung -L 9000 recorder’ (the -L bit indicates the port number that the proxy will listen on). Now, you can set tsunghost:9000 as the HTTP proxy in your web browser and all the web activity will be recorded by Tsung for playback later.

With Tsung recording, exercise your web application — but keep in mind that all of your actions will be repeated later, so for example, don’t make comments on a web page that only allows a max of 10 comments, or else you’ll get a high percentage of errors when it fails every time it’s hit after the 10th.

When you’re done with your web session, stop Tsung with ‘/opt/bin/tsung stop_recorder’. If you look in your home directory, you should now have a .tsung directory with a log of your session, something like ~/.tsung/tsung_recorderYYYMMDD-HH:MM.xml. That file contains the log of all the activity you did while sending traffic through the Tsung proxy, and will be used to drive the simulated user sessions during the load testing.

With the session file in hand, we can create a very simplified file to drive Tsung’s testing. There are some examples that were installed for you at /opt/tsung/share/doc/tsung/examples, but even the simplest example was more complicated than what I ended up using for my testing.

The only thing you must change here is the path to the session file that you recorded earlier, and possibly the hostname — although in my case it appeared to be overridden by the host defined in the session file. Apart from that, you might want to configure some details of the load testing, and set a maxusers value that’s somewhat reasonable for the test you have in mind.

  <!DOCTYPE tsung SYSTEM "/opt/tsung/share/tsung/tsung-1.0.dtd" [  ] >

  <!-- set dumptraffic="true" to dump all received and sent packets -->
  <!-- set loglevel="debug" for maximum verbosity -->

    <!-- Client side setup -->
      <!-- maxusers is the max number of simultaneous clients. Don't set it too high because you can run out of file descriptors. Remember that ssl_esock use 2 fds by connection. -->

    <!-- Server side setup -->

    <!-- several arrival phases can be set: for each phase, you can set the mean inter-arrival time between new clients and the phase duration -->

    <!-- Options. -->
     <!-- Thinktime value overrides those set in the session nodes if override=true. -->

      <!-- HTTP parameters -->
        Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.8) Gecko/20050511
    <!-- ********************************************** --> <!-- start your recorded session --> <!-- ********************************************** -->

In this case, we’re using clients on the local machine only, with a new user arriving every 5 seconds for 10 minutes, and with each user pausing for 3 seconds between requests to simulate thinking time. All clients claim to be Firefox, but that didn’t really matter to me — you may want to change it depending on how much browser-specific code you have.

When you have your tsung.xml file the way you like it, start Tsung with /opt/tsung/bin/tsung start. It will start and run until the last user session has completed (so a test defined to run for 10 minutes might take much longer than 10 minutes to complete if the server was heavily loaded). When the test is completed, Tsung will exit and write out a log file in ~/.tsung/log with the timestamp included in the filename.

Tsung has a tool included to generate HTML formatted reports that summarize the test, but they have to be generated by running /opt/tsung/lib/tsung/bin/lib_stats.pl in that test run’s directory. It will generate several html files and charts in png and ps format. Open up report.html or graphs.html in a browser to view an array of data from the test run. The Tsung home page has some samples of what the report will look like.

One last thing — by default, the charts are pretty low-res PNG files, but if you want to, you can create higher-resolution images from the PS (PostScript) files that each chart links to using a tool like GSView.

As resources, both the Tsung documentation and this post by 21 croissants were very useful to me as I was getting started.

Read Full Post »

So, if you were going to do some load-testing on your Rails app, you might think, hey, Siege is pretty cool. It supports load-testing multiple URLs at once (either sequential or in random order), with a delay in-between, with lots of options for setting the duration and characteristics of the load. Plus, there’s a tool that works with Siege, Sproxy, that lets you generate that list of URLs automatically by using Sproxy as a web proxy, recording your actions on the site.

Siege doesn’t support sessions (of course, that’s not clear from the docs, but I assure you it’s the case), which at first might be a deal-breaker if your app handles security by authenticating the session… but then you remember that you can pass in the _session_id parameter, and think all will be well.

Complication #1: In recent Rails versions, the session id can only be pulled from the cookie. However, we remember that you can set

ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:cookie_only] = false

And allow the session id to be taken from the parameter as well. However, if you’re running Rails 2, this won’t work. See Complication #2.

Complication #2: Thanks to a fix intended to prevent session fixation attacks, but which had some unintended consequences, the ability to override the cookie_only setting is broken. There is a monkey patch attached as a comment to that bug, but that’s not something I want to do when load-testing code. I do feel bad for the people out there (mainly mobile browsers and other non-traditional clients) that depend on parameter-passed session IDs.

So, time to look for a new tool, initial candidates are httperf/autobench, Flood, ab, and Tsung.

Thanks to JL2003 for the image.

Read Full Post »

Mirror Egg

Thought I’d put this out there in case anyone was interested in doing this, as I had to recently. The short version is: there is no shortcut, you’ll have to re-bundle it from a running instance.

So, we had some EC2 images (Amazon Machine Images, or AMIs) that had been stored under a developer’s personal S3 account and were running as an EC2 instance under his userid. Since we were about to change these from occasional, as-needed instances to constantly running ones (which would hit the dev’s credit card for about $72/month/instance + bandwidth&storage), I wanted to move the images and instances under our company account.

My first thought was to simply move the image to my account. As all EC2 AMIs are stored in S3, I thought it would be trivial (especially with the ruby EC2/S3 scripts found here) to just copy the AMIs to local storage on a machine using his credentials and then copy them into the corp S3 account. To make it cheap and easy, I would do this from within a vanilla EC2 image (one of the fedora ones provided by Amazon) , taking advantage of the fact that EC2<–>S3 data transfer is free (and usually fast). I was able to copy the buckets over pretty quickly… but then realized that I would need to let EC2 know there was an AMI there. I tried doing this with the ec2-register command, but that failed with a “Server returned HTTP response code: 403 for URL” error. Some searching showed that this was a permissioning error due to the fact that I didn’t use the ec2-upload-bundle command to store the image in EC2. After using that command, I received a new error from ec2-register: “Client.AuthFailure: User is not AMI creator”. Well, I couldn’t argue with that, as I wasn’t.

The reason that was important? When the image is created in the first place (in this case, via the ec2-bundle-vol command), the private key and certificate files provided are used to sign some of the fields in the image.manifest.xml file, thus ensuring that only the creator will be able to upload and register it with EC2. So, once I accepted that I wasn’t going to be able to copy the instance but instead would have to rebundle it, I came up with two options, and we used both:

  1. Re-bundle the image. Since we have an image that was already running as an instance, it wasn’t too hard to log into that instance as root and re-bundle the image. Then the act of uploading and registering the image were pretty simple, and it’s just a matter of transitioning from one image/instance to the other.
  2. Share the instance and run it under the corp account. We used this strategy for an instance that was undergoing relatively often changes, each change requiring a new AMI to be created and uploaded. Since 99% of the costs for the developer were from the EC2 runtime hours, an acceptable solution here was to add an attribute to the dev’s image stating that my particular userid was also allowed to run an instance of the image (via ec2-modify-image-attribute <ami id> -l -a <my EC2 userid>) and then start an instance under the corp EC2 account. Since that image is likely to change in not too long, we’ll just ignore the fact that the old image is on the dev’s S3 account for now and start storing it under the corp account when we upload the next version of that image.

Photo by LollyKnit

Read Full Post »

A friend of mine said this on the way back from lunch today and I had to preserve it for posterity.

Read Full Post »

Test Early points out a nice feature of JUnit 4 that I had overlooked — parameterized tests. If you’ve ever found yourself writing multiple repetitive test methods just so you could call the same method with various combinations of arguments, you should check it out.

Read Full Post »

So, if you’re like me and reinstalling Eclipse and Subversion (or switching to Subversion from the built-in CVS plugin), you’ll find yourself thinking, “Hey… something’s missing. I just edited a file, but why doesn’t it look right?”

Subclipse Undecorated

Eventually, you’ll remember, “Hey… I used to see a greater-than sign (>) in front of all my edited files, and an asterisk before newly created files — where did that go?” Personally, while I like the icon decorators, I find that they’re not quite as noticeable and with some of the icons getting decorated 3 times — a warning decorator, source decorator, and source control decorator (like the two source folders do) — it’s just not as obvious when you have files changed as when you have the text decorators set up:

Subclipse Decorated

To me, it’s much more obvious that src/tests has a modified file underneath it. Ex-Eclipse CVS users will especially miss it.

So how do you turn that functionality on for SVN? It’s in the Preferences, under Team->SVN->Label Decorators. In the Text tab, “Label decoration for outgoing” and “Label decoration for added” are both blank by default. To get the text decorator functionality, just put in a ‘>’ and ‘*’, respectively.

Read Full Post »

Older Posts »