We'll respond shortly.
Works for Engineyard. Getting to Rails 2.3, will be at RailsConf. Engineyard is hiring.
Yes. So does LOLCODE.
Scaling != Speed
Rub/Jruby around 23-30 in the Great Language Shootout.
In reality, Ruby is fast enough for the vast majority of use cases. Odds are slow code is your fault.
Step 1. Write Slow Code
Don’t worry about performance the first time around. Odds are you don’t know what will be slow. Just write the codebase
Step 2. Use Science
Don’t stab in the dark. Use the scientific method. It is the most important tool science gives us, we should use it.
Step 1. Define the Question (It needs to be specific)
Step 2. Gather Information
Step 3. Form a Hypothesis
Step 4. Perform experiment and collect data
Step 5. Analyze interpret
Step 6. Publish results and retest
“My app feels slow” is not specific enough.
“Why is action X taking more than 100ms on average?” is a better question.
“Why is 60% of the merb dispatch cycle in content negotiation?” is a good one too.
“Why are my Mongrel processes growing to 300MB of memory?” (Gets laughs)
QUESTION: “Is route generation as fast in rack-router as it is in Merb and Rails?”
Tools: Rbench, ruby-prof/kcachegrind, EXPLAIN ANALYZE, log files, New Relic/Fiveruns, memory_usage_logger, bleak_house
He shows some data from the benchmarks, comparing rack-router and merb routing, and rails routing. This answers the question that Merb route generation is NOT as fast.
So, rephrase the question. How do you make it fast? Benchmarks aren’t good for this. He used Rubyprof which provides a lot of ways to set up test and output data. He uses the “call graph” output, which he can open in kcachegrind. It is available via macports.
He then shows the graphical output of kcachegring. Top left shows the methods which take longest, lower left is call stack, showing aggregate (’incl’) and individual time (’self’) spent in methods.
Sort by “self”, and it turns out Array::map is the one taking most individual time. Most of the calls occur in Rack::Router::Condition::generate_from_segments. This is a good place to look and spend time trying to speed up.
Most of this logic can be removed and moved somewhere else. You can check Git logs to see how he did it.
Rewrote the code, it was faster.
Twitter and let everyone know about it.
Shows more kcachegrind examples. Shows how it can show source code annotated with performance data.
Remember – you don’t have to go through all the steps or feel bad because you didn’t in the past, just keep them in mind to figure out quicker where things are happening.
Conservative mark and sweep. Every time it runs, none of your ruby gets executed. The goal is to get the garbage collector to run as little as possible.
The way object allocation works is ruby boots and gives you 8 meg of memory. When your code runs, it allocates memory. If it can’t, it will run the garbage collector.
Don’t need to do this:
records.dup.values # records is a Hash
Use DataMapper’s identity map. It will not create a new object if it doesn’t need to. This will drastically reduce the number of objects created.
For example, slash at end of line to split up code
“No code is faster than no code” – merb motto:
Sexy, but slow. Sometimes you need them, but keep in mind they are more expensive than method dispatch.
def my_method yield end
def my_method(&block) yield end
class_eval For The Win.