I went out to practice flight shots early this morning before a day in the office. When the gulls get into a feeding frenzy, it makes for nice action along the water. Gorgeous morning to be out in the field, too!
At the risk of sounding repetitive... An average page is now over 1300 kB in size and over 60% of that is in images. Hence, if you have limited time, then inspecting and optimizing your image assets will likely yield the highest rate of return.
Case in point, the new data compression proxy for Chrome applies dozens of different content optimizations, but image optimization almost invariably comes out at the top. End result? On average, data usage is reduced by 50%! The strategy? Simple, transcode all images to WebP!
With that in mind, I had a chance to sit down with Stephen Konig (Product Manager on the WebP team), to chat about the latest news, team progress over last two years, and where WebP is heading. You can scan through the slides, or watch the GDL on YouTube, but below are a few highlights and resources to help you get started.
Focus on adoption in 2013
The primary focus and goal for the WebP team over the course of the past two years has been on developing the necessary features of the format itself - i.e., the engineering part. The good news is, end of 2012 marked an important milestone: support for lossy and lossless compression, alpha channel, animation, metadata, color profiles, and more. With all of these features in place, the focus is shifting towards tooling and driving adoption.
In fact, in the time-honored tradition of dogfooding own products, there is already a large and growing list of Google properties (Gmail, Drive, Picasa, Instant Previews, Play Magazines, Image Search, YouTube, ...) with WebP support. Most recently, Chrome Web Store switched to WebP, saw ~30% byte reduction on average, and is now saving several terabytes of bandwidth per day!
In parallel, there are now over 300,000 sites using the open-source PageSpeed libraries, which enable transparent WebP transcoding on Apache (mod_pagespeed) and Nginx (ngx_pagespeed), and there is a growing list of commercial products (Torbit, EdgeCast) which can do similar optimizations - the bandwidth savings are hard to argue against!
"Time to Glass" vs. Bandwidth
WebP achieves better compression by spending more CPU cycles - that's an inherent tradeoff of any compression algorithm. Today, when compared to JPEG, the encoding speed for WebP is ~10x slower, and decoding is ~1.4x slower when done on the CPU. Is that big deal? The answer depends on your application: if you are generating unique and dynamic images on every request, then the extra CPU overhead is something you'll notice. But if the files are (mostly) static, then the encoding time is a non-issue.
More likely, the concern is not over encoding, but over decoding speeds. Is 1.4x going to hurt your performance? Once again, it depends on your application - as with any performance metric, measure it. The Ebay tech team recently published a great overview of various image optimization techniques:
This test from webpagetest.org compares the page load time of WebP vs. JPEG. The test has one page with 50 images in the WebP format, and another page with the same 50 images in the JPEG format. Because the WebP page had to download fewer bytes (474484 vs. 757228), it completes loading much earlier compared to the JPEG page... If you track your web site's browser usage stats and find that Chrome/Opera users are a sizable chunk, using WebP images will improve the page load time for these users.
Despite the extra decoding time, the visual rendering time is much faster due to fewer bytes shipped. Further, for a significant segment of the population, bytes are (literally) expensive: bandwidth caps are a real constraint for many users, especially on mobile devices and in the developing world.
Deploying WebP on Native and Web platforms
Deploying WebP in a native app, iOS or Android, is actually very straightforward: Android 4.x.x+ has native support for WebP, and there is a backport for earlier versions; on iOS you can use the official libraries provided by the WebP team (tutorial, demo app). Since you control the display logic and the platform, you can safely convert all assets to WebP and save on data transfers both from and to the device - WebP helps for upload cases equally well!
On the web, things get a bit more difficult, but still manageable. Chrome and Opera have native support for WebP, and there is an open discussion with the Firefox team. There are also third party plugins for Safari and Chrome Frame provides support for IE - however, you can't rely on these plugins being present. Instead, for time being you have to fall back to
Accept negotiation to make this entire process much easier.
The most popular technique today and one that is used by PageSpeed and other optimization products, is to rely on server detection: run a
User-Agent check, and serve the HTML with WebP image links, or non-WebP links. What are the
User-Agent rules? PageSpeed is open-source, so the answer is right in the code. Further, to simplify this process, I've translated the rules into sample configuration files for Varnish and Nginx:
With above detection in place, Varnish and Nginx will report an extra
WebP: lossy, lossless header to the app server, allowing your application to generate customized HTML based on available WebP support. In turn, the static image assets can be safely cached either on the local file system or on any CDN service. The only other caveat is that the HTML must be marked with
Cache-Control: private to ensure that an intermediate cache does not accidentally serve the wrong file to the wrong browser.
Welcome to this week’s roundup of Ruby news, articles, videos, and more, cobbled together from my e-mail newsletter, Ruby Weekly. Sorry these roundups have been missing for a couple of months, I've been focusing very heavily on the e-mail newsletters which are continuing to grow like crazy! :-) I hope to get back into blogging more soon.
Matz on Ruby 2.0
Matz spoke about Ruby 2.0 ('the happiest release ever') for 30 minutes at the Heroku Waza event a week ago and the video is already available to watch. He stresses that "Ruby 1.8 will die soon" and encourages everyone to upgrade.
Dynamic Method Definitions
Aaron 'tenderlove' Patterson says that "depending on your app, using define_method is faster on boot, consumes less memory, and probably doesn’t signigicantly impact performance" compared to eval-based techniques. (And he has the numbers to prove it.)
Steel City Ruby Conference 2013 CFP Now Open
Steel City Ruby takes places in Pittsburgh, PA on August 16-17 and the CFP is now open if you want to submit a talk. The Burlington Ruby Conference has a CFP open too, as does RubyConf India.
Inspecting Rails 4 using Ruby 2.0 and TracePoint
Matt Aimonetti shows off a practical use for Ruby 2.0's TracePoint execution tracing functionality.
Visualizing Memory Leaks in Ruby 1.9
Conrad Irwin on some clever work to extend ObjectSpace with a new find_references method to perform better analysis on object and memory usage on Ruby 1.9.
Parsing TOML in Ruby with Parslet
Recently, GitHub founder Tom Preston-Werner created an interesting INI-influenced 'TOML' format. In this series of posts, Nathan Witmer looks at what's involved in building a parser for TOML using the Parslet PEG parser construction library.
Introducing Ress: A System for Building Mobile Optimized Rails Apps
Matthew Robertson introduces his new system for building mobile-optimized Rails applications using semantic, media query-based device detection and server side component optimization.
Ruby 2.0 Walkthrough: The Best Bits
Some slides from my yet-to-be-released 'Ruby 2.0 Walkthrough' that quickly skim through what I consider to be the 'best bits' (and not just the headline features).
Rails + Ember.js
Watching and Listening
Sinatra in SIX Lines: How to Do Crazy Stuff with Ruby
A talk by Konstantin Haase at Ruby Australia.
Libraries and Code
Phusion Passenger 4.0 Release Candidate 4
Leading Rack-based app deployment tool Passenger gets yet another step closer to the 4.0 release.
time-lord: A Human DSL for Time Expressions
A gem that gives you more human like expressions for time and space math. Get fun like
identity_cache: Opt-in Read-through ActiveRecord Caching, From Shopify
IdentityCache lets you specify how you want to cache your model objects, at the model level, and adds a number of convenience methods for accessing those objects through the cache. Uses Memcached as the backend cache store.
neg 1.1.0: A Small PEG Parser Library
"One could say it’s a small brother of Parslet."
Web Application Developer for Big Nerd Ranch
Seeking smart, kind folks who want to make the world a little better through developing, training and writing about cutting-edge code.
JS / Ruby Developer at ReplayPoker (Full-Time, Remote)
Looking for a challenge? Our company is looking for a top-notch junior to mid level developer to join our small team and make a big difference!
Last but not least..
RTanque: A Robot Programming Game for Rubyists
Players program the 'brain' of a tank and then send their tank into battle with other bots. Based upon the Java project 'Robocode.'
This week we talk about a brand new Bundler, signed RubyGems, CoffeeScript source maps, Posgres Tips, code typos and learning programming as an apprentice.
This episode is sponsored by Top Ruby Jobs
If you're looking for a top Ruby job or for top Ruby talent, then you should check out Top Ruby Jobs. Top Ruby Jobs is a website dedicated to the best jobs available in the Ruby community.
A new binstubs command creates a `bin/gemname` for any gem with an executable component, like Rake for instance. Whenever you call bundle open or bundle update, partial name matches will now return a list of gems to pick from. This release should also fix some issues people were seeing with SSL when trying to bundle under the recent Ruby 2.0.0-p0. Last but not least, Bundler now supports signed gems! through a `bundle install --trust-policy` that takes the same arguments as `gem install --trust-policy` does.
A Practical Guide to Using Signed RubyGems
Speaking of gems, the guys at Meldium wrote up a nice blog post about using signed gems. After the security breach that affected RubyGems a few weeks ago, several people pointed to the fact that by now we should all be using signed gems to add a layer of security. Bradley Buda from the Meldium team open sourced a tool that lets you check which gems from your Gemfile have been signed and which trust policy you can use with them. I think it’s important to note that the trust policy is only used when installing a gem for the first time.
CoffeeScript 1.6.0 with Source Maps
Peter Van Hardenberg of the Postgres team at Heroku gave a talk at the Waza conference last week called The Bits You Haven’t Found in Postgres. Among the tips he pointed out where the ability to generate date series to search the database at specific time increments, how to connect to a remote database right inside of a query, listen & notify for events before doing a specific query, and a ton of really cool date helpers similar to the good stuff we’re used to with ActiveSupport.
Close Enough is a gem that uses spell check algorithms to hack at method_missing, and guess what you meant to type when your fingers betray you. Perhaps using it in production would be dangerous, irresponsible, or ethically questionable, but it’s an interesting thought experiment.
The Apprentice Programmer
Tobias Lütke, the founder and CEO of Shopify wrote a nice blog post about his learning experience as a programmer. He talks about dropping out of high school and starting his career as a programming apprentice in his homeland of Germany. Considering the current raging debate on whether programmers can be taught their craft inside of traditional schools it’s interesting to note how his hands-on experience learning software development from solving concrete problems inside of a company seems to make a lot more sense than spending years learning theoretical computer science in school. It’s not substantially different than the path of a career-changer- educated or trained in something else, but turning to programming by jumping in with both feet. It’s an approach that works well for a lot of people.
Phusion Passenger turns Apache and Nginx into a full-featured application server for Ruby and Python web apps. It has a strong focus on ease of use, stability and performance. Phusion Passenger is built on top of tried-and-true, battle-hardened Unix technologies, yet at the same time introduces innovations not found in most traditional Unix servers. Since mid-2012, it aims to be the ultimate polyglot application server.
Today we are pleased to announce Release Candidate 4 of Phusion Passenger 4.0. Last week we said that the open source release of Release Candidate 1 will be out today. However because of the helpful feedback and bug reports we’ve received from Enterprise customers, we’ve decided to push out these bug fixes to the open source version earlier. Release Candidate 3 was only available for Enterprise customers in order to test bug fixes, so it hasn’t been announced publicly.
The 4.x series is a huge improvement over the 3.x series: during the development of 4.0, we’ve introduced a myriad of changes which we’ve covered in past beta preview articles:
- Support for multiple Ruby versions, support for Python WSGI, multithreading, evented core similar to Nginx and Node.js, real-time response buffering, improved zero-copy architecture, better error diagnostics.
- JRuby and Rubinius support.
- Out-of-Band Work.
- Support for the Rack socket hijacking API
- Improved stability and test suite.
Changes in 4.0 RC 3 and RC 4
The focus of RC 3 and RC 4 have yet again been on improving stability. We’ve closed over 50 issues in our issue tracker.
The most important changes in RC 3 and RC 4 are as follows:
- Fixed Rake autodetection.
- Fixed compilation on systems where /tmp is mounted noexec.
- Fixed some memory corruption bugs.
- Phusion Passenger Standalone now sets
underscores_in_headers. Fixes issue #708.
- Fixed some process spawning compatibility problems, as reported in issue #842.
- The Python WSGI loader now correctly shuts down client sockets even when there are child processes that keep the socket open.
- A new configuration option
passenger_python(Nginx) has been added so that users can customize the Python interpreter on a per-application basis. Fixes issue #852.
- The Apache module now supports file uploads larger than 2 GB when on 32-bit systems. Fixes issue #838.
- The Nginx version now supports the
- Environment variables set in the Nginx configuration file (through the
envconfig option) are now correctly passed to all application processes. Fixes issue #371.
- Fixed support for RVM mixed mode installations. Fixes issue #828.
- Phusion Passenger now outputs the Date HTTP header in case the application didn’t already do that (and was violating the HTTP spec). Fixes issue #485.
- Phusion Passenger now checks whether /dev/urandom isn’t broken. Fixes issue #516.
- Improved debugging messages.
Installing and testing 4.0.0 Release Candidate 4
Open source users can install the open source version of 4.0 RC 4 with the following commands:
gem install passenger --pre passenger-install-apache2-module passenger-install-nginx-module
You can also download the tarball at Google Code.
In-depth installation and upgrade instructions can be found in the Installation section of the documentation. The documentation has been updated to cover 4.0 changes, including Enterprise features. You can view them online here:
We are excited about the final release. You can help us by testing RC 4 and reporting any bugs. Please submit bug reports to our bug tracker.
Looking back at the first release, back in October 2010, Zepto has come a long way. It’s now compatible with all modern browsers (except Internet Explorer, and yes, it’s easy to fall back to jQuery) and supports complex frameworks like Twitter Bootstrap.
Notable additions and changes in V1.0
- Zepto is now compatible with Twitter Bootstrap
- Portable, completely new node.js-based build system
- Fully automated tests with PhantomJS and Travis CI
- Removed touch module from default distribution (you can add with our easy-to-use build system, or just load it in addition)
There’s many more additions and bug fixes—see the detailed change log on the Zepto site.
We’re already planning V1.1, for which we will look mostly into code refinements and performance improvements (Zepto is already pretty speedy, as it keeps the loading and parsing time of your site low, especially on mobile devices).
Super-special thanks to all our contributors. You’re the best!
This week Ben Orenstein is joined by Jeremy McAnally, employee at GitHub, author of Ruby in Practice, Rails 3 Upgrade Handbook, MacRuby in Action, and more. Jeremy and Ben discuss teaching and organizing conferences, remote working for GitHub, the and the company summits, GitHub workflows, their internal tools team. They also talk about standing out from the pack in work, life, and getting accepted to conferences, selecting people to speak at conferences, self-publishing, Jeremy’s writing process and future writing plans, work-life balance, how to get a job at GitHub, and much more.
I dropped out of school when I was 16 years old. School was not for me. To me, computers were so much more interesting. Right or wrong, I felt like I wasted my time there and my real education was starting when I came home. I lost respect for the institution and of course this meant that I no longer bothered to put any effort into it. They diagnosed me with all sorts of learning disabilities and started to medicate me. I wanted to leave it all behind.
I decided the best thing to do was to drop out and start an apprenticeship as a Fachinformatiker - computer programmer. This might sound like a stupid decision to people in North America, who often go to College or University to get a degree in something like computer science, but in Germany leaving high-school for an apprenticeship is not out of the ordinary. It is called the dual education system, and it is likely one of the main reasons for Germany's success.
The system has its roots in history of the region. Carpenters and a number of other important craftsman trades have used an apprenticeship system to teach and build expertise for hundreds, if not thousands of years. The underlying idea is that there are professions that profit more from experience then theoretical understanding and that education time is far better spent doing the actual work by watching or listening.
Many companies in Germany take on apprentices, much like North American companies accept interns and co-op students. If a company decides to take you on as an apprentice, the position is guaranteed by the state. Should the company go bust, you are placed with another company the next day. There is a web of companies guaranteeing the positions for each other, spread all across the country.
Unlike interns in North American companies, apprentices in Germany are treated like normal junior employees except they are cheaper, (700 marks per month or $400USD when I went), often younger and misses about 60 work days a year to attend classes at their vocational school. The schools teach the theory behind each chosen trade and certify the students at the end of 3 years with an exit exam which concludes the program. Student apprentices, (they called us “Stift” = Pen), who successfully complete the program and pass the exam earn the vocational title.
I landed an apprenticeship with a company in my hometown called BOG Koblenz - a subsidiary of Siemens - a company with a history of taking on apprentices. For some reason I vividly remember this one question from my interview:
The number of lilies in a pond double every day. So, on the first day of the month there is one lily. On the second day, two lilies, the next day four lilies, then eight, sixteen, thirty two, etc. If the pond is full on the 30th day of the month, what day is it half full?
That was not exactly difficult.
Three other Stifts started with me at the same time. On our first day we got a tour of the 150 person company, which seemed massive to me at the time. The first year was about paying our dues: 3 months running the cafeteria, 3 helping in accounting, three more working in inventory, and then three months at reception. It was a rite of passage, they told us.
The first 3 months in the cafeteria meant I quickly met everyone in the company and learned what kind of coffee or tea they liked. I made sure to keep them well caffeinated. My absolutely favourite group of people worked in a small room in the basement of a secondary building. I do not remember what their official titles were, but they were essentially doing Skunk Works down there.
They did things differently than everyone else. Most of the company used an esoteric programming environment called Rosie SQL - which seemed like death to my Demo Szene honed sensibilities (Assembler, Pascal or bust!) - these guys used Delphi. I fell in love with it! Here was a programming language that put humans before machines. It was built for instant gratification, experimentation and rapid prototyping. Its window management library called the VCL was so much greater than anything I had seen before. More importantly, it was run by Jürgen.
Jürgen was a long-haired, 50-something, grizzled rocker who would have been right at home in any Hell's Angels gang. He was a rebel. He refused to wear the company attire, refusing to use the formal language, called people out on bad ideas when he saw them in plain language. Despite of all this, everyone respected him. I tried my best to make it absolutely obvious that I wanted to work for him. I borrowed the Delphi manuals and committed them to memory in my downtime between coffee runs.
At the same time, I would attend my vocational school every Friday, and twice a year we would go for two straight weeks to study and take exams. This was a much better way for me to learn. It felt relevant. I learnt the fundamentals of things picked up from being around Jürgen's team. We learned about algorithms, Big O, etc - even some basic soldering and electrical work.
It turned out those learning disabilities were not real disabilities; I was simply a kinesthetic learner. I could not understand or come up with solutions to problems I have never had. At my vocational school, I knew the problems we were solving. I had been in those situations. It was great! My self esteem and confidence improved quickly.
My plan was working.
After the first year, Jürgen drafted me to be a part of his little basement-dwelling team. It was probably the most important thing that happened to me in my professional life. Jürgen was a master teacher. He created an environment in which it was not only possible but easy to move through 10 years of career development every year. It is a method and an environment which I am fiercely trying to replicate at Shopify.
Most days I came to work and found a printout of the code I wrote the day before annotated with red marker everywhere. I used poor idioms or could have chosen better abstractions or done a better job hinting at the architecture of the overall system. This taught me not to tangle my ego up in the code I write. There are always ways to improve it and getting this feedback is a gift.
I remember we made software for GM. One particular car dealership needed a faster system to estimate the value of incoming used cars. A big competitive advantage. Jürgen gave this project to me. Shipping it meant Jürgen and I had to drive to the dealership which was a day trip away. In preparation for it, the company gave me extra money so I could buy a suit. We work for Siemens after all. We had to look the part.
The day before the installation, Jürgen casually tells me he has somewhere else to be. I would be going by myself. I felt overwhelmed but somehow managed to make a good impression and got everything working regardless.
This pattern kept on repeating itself. Jürgen somehow knew the extent of my comfort zone and manufactured situations which were slightly outside it. I overcame them through trial and error, through doing, and immediately applying the theory I was learning at the vocational school to practice at my apprenticeship, I succeeded.
My degree is not recognized in North America so I am technically a high school dropout. My cofounder at Shopify has a PhD, so we always joke that together we average out to a bachelor's degree.
Not that degrees matter anymore. They do not. Experience does. That is one of the things my apprenticeship and the dual education system in general taught me: experiencing and learning things quickly is the ultimate life skill. If you can do that, you can conjure up impossible situations for yourself over and over again and succeed.
Perhaps most importantly, the apprenticeship program gave me a solid head start. If I had gone to a University and studied to get a PhD like my Cofounder, I might JUST be getting out of school. Instead, at 32 years old and I have been paid to build complex software for almost half my life.
That is a powerful concept and one within the reach of almost any German student thanks to the dual education system. At the last count, there are 356 different occupations or occupational categories which offer apprenticeships. From hair dressers to oven builders to various specializations of computer programming. For hands-on people or kinesthetic learners like me, the apprenticeship program created a legitimate path to success.
It was the perfect environment for me, I learned a lot, and I am eternally thankful to have chosen that path. If only more countries struggling with dropout rates and job creation would give their students a similar choice.
In this episode of The Ruby Show, Jason and Peter talk about the latest Ruby release, Rails security releases, and the usual round up of interesting projects.
New versions of all the things! Docs, clearing up maintenance plans, and as usual, a smattering of useful ruby tools (singleton_process, flight, gridhook, and assorted blog entries) in this RubyLoco-powered edition of Ruby5.
This episode is sponsored by New Relic
Happy Birthday NewRelic! New Relic is 5 years old, and to celebrate, they are giving you even more. Are you using their free account? Bam! You now have 24 hours of data at your fingertips instead of half an hour. Using their lite or standard account? You now have access to features that previously were only available to the pros. Take a look - you've got nothing to lose.
Rails4b1 is out! Check it out on Ruby 2.0-p0 for your free sample of Living In The Future.
Rails Maintenance Policy
Stuck on Rails 3.0.19? Putting of the pain of moving off of 2.3.11? Confused with the recent flurry of security releases? Steve Klabnik wrote a blog entry explaining exactly what the rails maintenance policy is, so even if you're a version laggard, you know what the potential security exposure is.
Here's the nightmare scenario - you have a rake task that runs every 5 minutes. You deploy, and all is good... but over the ensuing months, the process has to chunk through more and more data, and one day it takes more than 5 minutes to complete. A second process starts up before the first one finishes, and your world collapses into in-deterministic chaos! With the singleton_process gem, you can wrap your code in a couple lines and ensure the first process is done before the second one starts.
Gridhook is a Rails engine providing an endpoint for handling incoming SendGrid webhook events.
Aaron Blohowiak took a cheap usb foot pedal, wrote this little shim, and made it work as his vim mode-switcher! Take that emacs! Emacs users would need, like, 3 feet to do something that cool.
Ruby 2 by Example
There are four big front-facing changes in 2.0—keyword arguments, refinements, lazy enumerables, and prependable modules. Here’s Ben Hosking's take on all four, using lots of code samples from his RubyConf AU talk.
Daniel Kehoe has published instructions for installing Rails4 on many different platform and ruby combinations. If you're that into gemsets though, you should take a look at "bundle install --path vendor/bundle"
Dave would like to give a shoutout to Nell Shamrell for her blog series on regular expressions in Ruby. He's mentoring a small group of developers right now, found the blog just in time to whet their appetites on that material.
We’re experimenting with Vagrant virtual machines for development.
To access the guest machine’s web server, the host machine will typically forward a different port to port 80 on each virtual machine.
So on your host machine, you may use
http://localhost:8001 for app1 and
http://localhost:8002 for app2.
This avoids port conflicts, but it’s a bit rough.
You can now use
http://app1.dev instead of
http://app2.dev instead of
I’m very pleased to introduce our new iPhone app for Learn.
We’ve started with the very valuable Trail Maps, guided paths for learning modern development technologies and practices.
The Trail Maps are kept up to date within the app and accessible offline. This allows you to track your learning progress by checking off resources as you read them and validations as you learn.
Remember, our Trail Maps are open sourced on GitHub, so if you think something is a valuable resource, please do contribute.
The app is free on the App Store, so download it today.
If you want maintainable, loosely coupled classes, you must mind what they know about one another.
For example, you don’t want one Active Record model to know a lot about the schema of another.
Instead of this:<figure class="code"><figcaption>app/models/user.rb</figcaption>
1 2 3 4
You might use Active Record’s
merge and do something like:
1 2 3 4
1 2 3
We’re still coupled, of course, but to a higher and thus more stable abstraction.
For more complex SQL,
merge won’t cut it.
Today, I extracted columns like
contracts.emailed_at to a separate
Now there are
Event records which belong to a record (invoice or contract) and have an event name and a timestamp.
So a posted invoice may be represented by an
Event record with these attributes:
Now, if you want a scope/method like
Invoice.unposted (and perhaps
Contract.not_emailed), how would you go about it?
You’ll need a join that involves
You could put the join SQL in
Invoice, but then it would know a lot about the
events table. And you’d have to duplicate much of that SQL if
Contract adds a similar method.
Instead, you can simply have
Event own that SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Event needs to know is that its record has an id and a class; fairly stable assumptions.
Phusion Passenger is an Apache and Nginx module for deploying Ruby and Python web applications. It has a strong focus on ease of use, stability and performance. Phusion Passenger is built on top of tried-and-true, battle-hardened Unix technologies, yet at the same time introduces innovations not found in most traditional Unix servers. Since mid-2012, it aims to be the ultimate polyglot application server.
We know many users are eagerly awaiting the final release of Phusion Passenger 4.0. The 4.x series is a huge improvement over the 3.x series: during the development of 4.0, we’ve introduced a myriad of changes which we’ve covered in past beta preview articles:
- Beta 1: support for multiple Ruby versions, support for Python WSGI, multithreading (an Enterprise only feature), evented core similar to Nginx and Node.js, real-time response buffering, improved zero-copy architecture, better error diagnostics.
- Beta 2:
Today we are proud to announce Release Candidate 2 of Phusion Passenger 4.0. Release Candidate 1 has been skipped because a few bug fixes were applied right after RC 1 was tagged.
Changes in 4.0 RC 1 and RC 2
The focus of RC 1 and RC 2 have been on improving stability and on refining previously introduced features. We’ve closed over 100 issues in our issue tracker. We couldn’t have done this without the fantastic feedback from our users, especially those from many Phusion Passenger Enterprise customers who have beta tested the RC previews in their staging environments.
The changes in RC 1 and RC 2 are as follows:
- The Nginx version now supports the
- The Enterprise memory limiting feature has been extended to work with non-Ruby applications as well.
- Application processes that have been killed are now automatically detected within 5 seconds. Previously Phusion Passenger needed to send a request to the process before detecting that it’s gone. This change means that when you kill a process by sending it a signal, Phusion Passenger will automatically respawn it within 5 seconds (provided that the process limit settings allow respawning).
- Phusion Passenger Standalone’s HTTP client body limit has been raised from 50 MB to 1 GB.
- Python 3 support has been added.
- The build system has been made compatible with JRuby and Ruby 2.0. This does not mean that Phusion Passenger works on Ruby 2.0; please read on for more about this subject.
- The installers now print a lot more information about detected system settings so that the user can see whether something has been wrongly detected.
- Some performance optimizations. These involve further extending the zero-copy architecture, and the use of hash table maps instead of binary tree maps.
- Many potential crasher and freezer bugs have been fixed.
- Error diagnostics have been further improved.
- Many documentation improvements.
What about Ruby 2.0?
We are just as excited about Ruby 2.0 as many of you are. Since 2.0 was released a few days ago, we’ve been testing Phusion Passenger on it. We really wanted to release RC 2 with Ruby 2.0 support, but a few things stood in our way so we had to postpone this goal.
- We couldn’t get Ruby 2.0.0 installed on OS X Mountain Lion. The compiled Ruby crashes during Ruby 2.0.0′s build process with a low-level error ([BUG] Stack consistency error). Apparently we aren’t the only ones.
- We were able to get it installed on a Debian VM, but it does not pass all the Phusion Passenger unit tests. It fails on some tests with obscure errors that seem to indicate bugs in Ruby, e.g. errors in which Ruby cannot figure out where the exception came from.
We recommend sticking with 1.9.3 in the mean time until the next Ruby 2.0 patchlevel release.
Release Candidate 2 timeline & download
The release of the open source version will follow in one week, on March 5 2013. Of course, open source users who want to stay on the bleeding edge are free to obtain the latest sources from the open source Phusion Passenger git repository at any time.
When the open source version is released, users can install it by following the in-depth installation and upgrade instructions in the Installation section of the documentation. The manual also covers installation of beta releases.
We are excited about the final release. You can help us by testing RC 1 and reporting any bugs. Please submit bug reports to our bug tracker.
We’re proud to announce the release of Hobo 2.0.0.
Major New Features
Theming support has been extensively updated. New themes are much easier to write, and multiple themes per application are supported.
The default theme has been changed to a Bootstrap based theme.
Support added for the techniques mentioned in this blog post: How Basecamp Next got to be so damn fast without using much client-side UI including two mechanisms for pushState based AJAX and two mechanisms for intelligent hierarchical fragment caching.
all tags now use the standard Hobo AJAX support mechanism, which used to be known as Hobo form AJAX. The editor tags in particular have changed substantially.
new tags: nested-cache, swept-cache, live-editor, click-editor, formlet, hot-input, feckless-fieldset, accordion, accordion-collection, autocomplete, combobox, datepicker, dialog-box, tabs and more.
plugins are now based on the Rails asset pipeline. Available plugins include
hobo_mapstraction. Rails, jQuery and Bootstrap plugins can also generally be easily used.
Rails 3.2 is required, 3.2.12 or greater is strongly recommended.
many other fixes and updates. See CHANGES for more detailed information.
Changes from Hobo 2.0.0.pre10
HoboSupport’s patches to Chronic have been removed due to incompatibility with Ruby 2.0.0.
Hobo 2.0.0 has been tested against 1.8.7-p371, 1.9.3-p374, 2.0.0-p0 and JRuby 1.7.3.
Rails 4 Support
Work has started on Rails 4.0 support for Hobo. No other major features are planned for the next release of Hobo, so we do not expect it to lag too far behind the release of Rails 4.0.