Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Monthly Archives: January 2011

Adam Berlin

Don't Sweep It Under the Rug

Adam Berlin
Monday, January 31, 2011

Advice for Rails Performance Optimization

Upcoming Launch

Recently, our team releasing to a large set of users and needed to ensure that our application could meet the performance needs of the new users. Launch day was a month away. Months of steady Agile feature development needed to meet a healthy amount performance engineering.

We started with a few goals in mind. We wanted:

  • data-driven improvements
  • to prefer simple performant code to complex caching strategies
  • to use available tools to provide visualization for badly performing requests

Plan a Solution

We brainstormed for ideas on what would reliably lead us in the right direction. Requests per second (and seconds per request) were useful data points that we were able to get from Apache Benchmark (ab). Using AB we could make a change, run the benchmark, and be sure that the change made a positive performance impact. One obvious way to get requests per second to increase is to use caching. Our team was hesitant to use caching for several reasons:

  • there are many user-specific features
  • caching increases the complexity of your codebase when dealing with cache population and invalidation strategies
  • we felt that we could meet our performance needs without caching by employing a few other tools

To track down specific bottlenecks we used Ruby Benchmark. We could perform an Outside-in performance analysis of specific actions, benchmarking deeper and deeper, until specific methods or database calls stood out as obvious problems.

The Big Wins

A few things stood out as Big Wins for us:

  • Missing database indexes often came up as a cause for slowness. Often there were non-foreign key columns that had not been indexed but were being used in a WHERE or a JOIN. The MySQL slow query log led us to several major culprits.
  • We could see from our New Relic graphs that while iterating and rendering the same exact view with a different user, we would see a large spike of time spent rendering. This smelled to us of garbage collection. We turned on Rack::Bug and quickly noticed that we were performing 6 garbage collections during one request. We had read a blog article from Sam Coward about using Ruby Enterprise Edition Garbage Collection statistics gathering to track down object allocation and garbage collection problems. (http://pivotallabs.com/users/scoward/blog/articles/1411-identify-memory-abusing-partials-with-gc-stats) We installed his patch to Rack::Bug which displays memory usage information for each ActionView template that is rendered. From there we were able to use our outside-in benchmarking to find our offensive memory hogs and make them more friendly. We found out later that New Relic has released an RPM that also graphs time spent in garbage collection.
  • This led us to our final optimization. We had removed most of our GC time, but still had not taken advantage of the Ruby Enterprise GC variables. Our servers are hosted with Blue Box Group (http://www.blueboxgrp.com/) and their service staff helped us eek out the last bit of memory performance. They worked with us to tweak our Ruby Enterprise Edition garbage collection variables to the most optimum settings.

What We Learned

In the end, we learned a few things about optimization.

  • There are many things you can do easily to improve performance without resorting to complex solutions.
  • A data driven approach can lead you quickly to a good solution.
  • Use tools that can give you visibility into your performance bottlenecks.
  • Set a realistic performance goal to meet. Your site can always perform better. The real question is, how much performance do you need?

These are the obvious, well-covered topics of performance enhancement. There’s a reason. They can take your application a long way.

–
Thanks to Evan Farrar for much of the wisdom that went into our performance optimization thought process.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Kevin Fitzpatrick

Standup 1/31/2011: Don't Fear The Upload

Kevin Fitzpatrick
Monday, January 31, 2011

Ask for Help

“Does my Rails application on top of Passenger get blocked when I upload a file?”

Nope! Passenger uses plain old apache to buffer the file upload so your application instance is free to service other requests while the upload is finishing.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Mongoid Migrations using the Mongo Driver

Pivotal Labs
Saturday, January 29, 2011

In my last post, I modified a Mongoid::Document during a migration in order to access fields that where no longer defined in the class. This time I am using the mongo ruby driver directly to migrate data.

Since I am using Mongoid in this project, I will be using it to access the dependent mongo driver. This will prevent me from having to provide mongo with a connection string in my migration. I am also using mongoid_rails_migrations to roll out the change.

Initial Design

class User
  include Mongoid::Document
  field :first_name
  field :last_name
end

New Design

class User
  include Mongoid::Document
  field :name
end

Migration

class MergeUsersFirstAndLastName < Mongoid::Migration
  def self.up
    #get the mongo database instance from the Mongoid::Document
    mongo_db = User.db

    #query the collection for the fields needed for the migration
    user_hashes = mongo_db.collection("users").find({}, :fields => ["first_name", "last_name"])

    user_hashes.each do |user_hash|
      new_name = "#{user_hash['first_name']} #{user_hash['last_name']}"

      #update the new field
      mongo_db.collection("users").update({"_id" => user_hash["_id"]}, {"$set" => {"name" => new_name}})

      #remove old fields from collection
      mongo_db.collection("users").update({"_id" => user_hash["_id"]}, {"$unset" => { "last_name" => 1, "first_name" => 1}})
    end
  end
end

Resources

MongoDB Ruby Driver Tutorial

Querying with MongoDB Ruby Driver

Updating with MongoDB Ruby Driver

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Dan Podsedly

Changes to Pivotal Tracker Pricing

Dan Podsedly
Friday, January 28, 2011

Last week, we announced that we’re introducing pricing for Pivotal Tracker. Since then, we’ve received a great deal of thoughtful and constructive feedback, and we’re very grateful that the majority of you have shown support of Tracker’s move to be a paid product. We really appreciate all of your positive comments.

Continue reading below for details about changes to pricing that we’re making based on your suggestions, and clarification of some aspects of pricing that may not have been stated clearly, including what remains free.

Our goal was to come up with pricing that’s friendly for both small teams and startups as well as larger companies, and competitive with many other web-based project management and collaboration tools for software development. Given the wide variety of the users and situations (freelance developers and small startups to consulting shops and larger, more established companies), though, it’s understandable that the price plans weren’t a perfect fit for everyone.

We’re making the following changes to Tracker pricing.

  • More projects for the Startup plans: To help freelance developers and small consulting companies who might have a number of projects on the go at the same time, we’re increasing the project limit to 5 private projects for the $7 Startup plan, and 10 private projects for the $18 plan. The free individual plan will now allow up to 5 private projects (with no collaborators). As a reminder, archived projects do not count toward any plan limits.

  • Free for read only project members: We value and encourage transparency. To support that, read-only members of projects will no longer count toward plan limits. This will allow you to invite as many people to observe progress within projects as you would like.

  • All integrations included: We also heard from many small teams and individual developers that you rely on some of the external integrations, for example with Zendesk. We’ve decided to allow all integrations to be available for all plans, even the free individual plans, in addition to full access to the API and all notifications (email/RSS/Twitter/Campfire).

These changes will be reflected on the site within the next 24 hours.

We’ve done our best to accommodate as many of your suggestions as possible, but recognize that some of you may still find gaps between the updated pricing and what you might consider ideal. Please accept our apologies.

If you’ve already purchased a plan based on the original pricing, and would like to choose a different plan based on these changes, please let us know by emailing tracker@pivotallabs.com.

We’d like to also take this opportunity to clarify the various ways that Tracker can be used free of charge:

  • Free for individual use: Tracker is free for your own personal use, with no collaborators, with up to 5 of your own private projects, and 200MB of storage for story file attachments per account.

  • Free for you to participate in other users’ projects: Accepting a project invitation and participating in projects that belong to another user’s paid account is free.

  • Public projects are free: Projects that are publicly viewable, and the collaborators in these projects, do not count toward any plan limits.

  • Free for non-profits and educators: We provide free accounts for qualified non-profit organizations, as well as educators at academic institutions, by request.

Also, we’d like to restate the discounts that we’re offering:

  • The 20% introductory discount works as follows: buy a paid plan with the annual billing option on or before Feb 18, and you get 20% off the annual price for the first year. Your credit card will be billed immediately, but you will still receive the remainder of the extended free period, which ends on July 19, 2011, so you actually get a total of up to 18 months of use (until July 18, 2012).

  • Pricing with annual billing is the equivalent to paying for 10 months – for example, the $50 Pro S plan costs $500 per year, when you choose annual billing. The 20% introductory discount is off of the annual ($500) price – so if you purchase the Pro S plan on annual billing by Feb 18, you only pay $400 for the first year.

Please let us know if anything needs clarification in comments here or by emailing tracker@pivotallabs.com.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Gregg Van Hove

Standup 1/27/2011: Paperclip hangs?

Gregg Van Hove
Friday, January 28, 2011

Ask for Help

Some pivots are trying to import a large number of images into paperclip, and it seemed to hang when shelling out to convert at different images.

Suggestions for troubleshooting included:

  • look at the memory usage over the course of the import
  • try running one file many time to see if it’s just some bad images
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Gregg Van Hove

Standup 1/27/2011: Rails server eats your batteries

Gregg Van Hove
Thursday, January 27, 2011

Ask for Help

A pivot was looking for help with using mod_proxy on apache. It only seemed to want to proxy the root.

The only real suggestion available was to use HAProxy instead, but that wasn’t an option for this project

Some pivots were looking for help using bundler together with capistrano, but without rvm.

No real suggestions on what the problem could be.

Some pivots were wondering how long of a time-box they should set aside to get jasmine running in CI.

Consensus was that it should only take about a half-hour.

Interesting Things

  • A pivot noticed that the battery life on his MacBook Air seemed to suddenly drop from about 8 hours down to only 4 hours. After some digging through top, it turned out that running rails server and rake jasmine:ci were causing the machine to never be able to fully enter sleep/hibernate to save battery life. So remember to turn those off when you put your laptop away.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Pivotal Labs is proud to sponsor the OpenSource Women's Leadership Summit

Pivotal Labs
Wednesday, January 26, 2011

We’re pleased to be sponsoring the Open Source Women’s Leadership Summit this Friday. We think the work that the RailsBridge community has done is critical to making the Ruby community more diverse and more welcoming to everyone. We know women are significantly under-repesented in the development community as a whole, and in the Ruby community specifically, and we choose not to accept this as inevitable. It was Grace Hopper, after all, who developed this whole idea of programming languages.

Pragmatically, we also see this as an opportunity. Women hold up half the sky, but until recently held down only 3% of the seats at conferences. In a market where everyone is searching for developers, we ignore this large segment of potential developers to our great detriment. Where else are we going to find the potential to double our Ruby community?

And, as our economy slogs its way out of the deepest downturn since the Great Depression, we also see this as an opportunity to even out what has been a very uneven recovery. We have at once deep unemployment and many many unfilled jobs. The jobs are there but they have moved. We are hiring as fast as we find good people and we are certainly not alone. We see RailsBridge as a way to help people develop the skills they need to move to these new jobs, and they’re high-paying jobs, too! What better community to enter than one where employers fight to pay you above the median San Francisco income?

The work that RailsBridge started is very important, and is far from done. The work takes a great deal of effort. To that end, we want to celebrate the people who are making this happen. Pivotal Labs is honored to be a sponsor, and to continue to support these fantastic programs with space, time, money and our voice.

Those of you in the San Francisco area, we encourage you to attend and help us celebrate these inspiring leaders, and those of you elsewhere we encourage you to get involved: help get the word out about this exciting movement.

Event Details on EventBrite: OpenSource Women’s Leadership Summit

RailsBridge Blog Post

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

HTTP Basic Authentication and Devise

Pivotal Labs
Wednesday, January 26, 2011

Say you’re using Heroku to host a staging version of your app that uses Devise for authentication. You want to keep unwanted visitors out of your staging app, but your app only uses authentication for certain features. You want to block outsiders from accessing the app entirely. Since Heroku doesn’t allow you whitelist IP addresses in your webserver config, you might want to try HTTP basic access authentication to provide top-level authentication. Doing this in Rails is pretty straightforward. Let’s assume your staging app runs in the “staging environment.”

application_controller.rb:

before_filter :authenticate if Rails.env.staging?

protected

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
    end
end

See Ryan Bates’ Railscast #82 HTTP Basic Authentication for more info.

This will work for most cases. However, since we have Devise installed, this won’t work. Devise will enter an infinite loop of redirects unless we tell Warden to set the performed flag.

application_controller.rb:

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
    end
    warden.custom_failure! if performed?
end

But wait, we’re still not done. Devise has the ability to use your HTTP Basic Authentication credentials and use it to log into its own authentication system – a cool feature if you want to be able to pass your login credentials over HTTP, perhaps as a simple way to authenticate an API consumer. However, in our case, we want to keep the HTTP Basic Authentication that we require for the entire site separate from the Devise login that we use internal to the app, so we need to disable Devise’s ability to capture our HTTP Basic Authentication credentials. In some versions of Devise, this feature is on by default, and in others it is off by default. Check your devise.rb file and make sure you have uncommented the line that disables Devise’s http_authenticatable configuration setting.

devise.rb:

config.http_authenticatable = false

Be warned that HTTP Basic Authentication transmits the username and password in clear text, so you should not use this method for applications where a higher level of security is required.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Gregg Van Hove

Standup 1/26/2011: Rails bridge is cool

Gregg Van Hove
Wednesday, January 26, 2011

Ask for Help

Some pivots were looking for experts with google analytics.

A pivot or two has had experience. Splunk was also suggested as a way to get some potentially different analytics, but warnings were given that it can take a while to get everything set up for Splunk to work correctly.

Interesting Things

  • Typus allows easily adding the ability for admin users to edit structured content in your rails app.

  • OpenSource Women’s Leadership summit is this Friday. See here for tickets. And check this out for more info

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Gregg Van Hove

Standup: 1/25/2011:

Gregg Van Hove
Tuesday, January 25, 2011

Ask for Help

How do you customize the body of the email message in ActionMailer 3.0? Some pivots want an admin user to be able to edit the default version of the email to be sent, but ActionMailer 3.0 no longer allows the body to be set directly.*

One suggestion was to create a new model that has a default body, and allow the admin user to edit and save, and use that to render the body of the email.

Can you require Bundler inside of the same script that is installing it?

No real solutions other that probably trying to look into the Gem API

Interesting Things

  • Amazon has released an email API for sending emails using their servers. Prices start at 10 cents per 1000 messages sent, with breaks for messages coming from within EC2
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (778)
  • rails (113)
  • testing (86)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (53)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (21)
  • cucumber (20)
  • bloggerdome (19)
  • process (19)
  • pivotal tracker (19)
  • design (18)
  • jasmine (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • gem (13)
  • bdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • tdd (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • rubygems (9)
Subscribe to Community Feed
  1. 1
  2. 2
  3. 3
  4. 4
  5. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >