io = env['rack.hijack'].call Thread.new do sleep 1 io.write "HTTP/1.1 200\r\n" io.write "Connection: close\r\n" io.write "Content-‐Length: 2\r\n" io.write "\r\n" io.write "OK" io.close end [418,{},"NOT DEFINED IN SPEC"] } % ab -‐c 100 -‐n 100 hOp://localhost:8080/ … Percentage of the requests served within a certain 4me 50% 1076 100% 1084 (longest request) 100 concurrent requests All sleep for 1 second Served with 1.08 seconds Unicorn/Puma or Passenger
• In produc4on in Discourse for 2+ years • Minimal dependencies (redis and rack only) • can be ported to pg or memory • Runs inside your Rails app as middleware, no need for extra ports / apps
• Reliable pub/sub s4ll required • Fallback logic s4ll required (6 connec4on per browser, less on phones) • HTTPS required • HAProxy hacks may be required • Hard to debug • Not significantly beOer than long polling • PR welcome
MemoryProfiler.report do result = raw_connection.exec("SELECT price, tax FROM products LIMIT 10") result.type_map = type_map result.values end.pretty_print 13 objects allocated (was 286) 1.1K bytes allocated (was 25K) Shout out to Lars Kanis for building this
at: discourse/lib/freedom_patches/ fast_pluck.rb • 100% backwards compat (works on Rails 4.1 / 4.2) • Uses new PG type map • Reduce alloca4ons from 286 to 198 • Reduce memory allocated from 25K to 18K • Will not be backported into Rails 4.2
* from cars " and_or_where = "where" if color sql << "where color = '#{PG::Connection.escape(color)}'" and_or_where = "and" end sql << "#{and_or_where} max_speed = '#{max_speed}'" if max_speed connection.exec(sql).each |row| puts "make: #{row["make"]} max_speed: #{row["max_speed"]}" end
/*where*/") builder.where("color = :color", color: color) if color builder.where("max_speed = :max_speed", max_speed: max_speed) if max_speed builder.map_exec(Car).each do |row| puts "make: #{row.make} max_speed: #{row.max_speed}" end
though the SQL for this takes 12 milliseconds, the total 4me it takes to execute the above code is much higher, profiling shows a 90 ms execuHon Hme.” … so we created Dapper …
public int? Age { get; set; } public Guid Id { get; set; } public string Name { get; set; } public float? Weight { get; set; } public int IgnoredProperty { get { return 1; } } } var guid = Guid.NewGuid(); var dog = connec4on.Query<Dog>( "select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
-‐> object mapper • Small code base • Standalone gem • Handle parameters • Interoperable with Rails • All queries run through object mapper • Provide a “blessed” efficient SQL story