Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Http optimizations #8002
These are a series of refactors to improve parsing of HTTP requests. Check each commit for more details (each has a description in it).
This is more code, more complex code, and more low-level code, but that's the whole idea of Crystal: if you want to go deeper and optimize hot paths you can do it in Crystal itself.
I wrote this benchmark:
require "benchmark" require "http" # # request.txt was generated using this code # request = <<-REQUEST.lines.join("\r\n") + "\r\n\r\n" # GET /hello.htm HTTP/1.1 # User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT) # Host: www.tutorialspoint.com # Accept-Language: en-us # Accept-Encoding: gzip, deflate # Connection: Keep-Alive # REQUEST # File.write("request.txt", request) io = File.open("request.txt") Benchmark.ips do |x| x.report("from_io") do io.rewind HTTP::Request.from_io(io) end end
I read from a file to simulate reading from an external resource, though the entire file probably fits
If I run the above benchmark against
When against this PR:
So a 30% improvement!
Also note the memory allocated per op: 2.1kB before, now 816B. This is the main reason it's faster.
If I use
Since HTTP servers are pretty common in Crystal I thought this is a good way to optimize all apps out there. I know usually a lot more goes on in a typical web server (for example rendering) but the less time and memory the framework takes for itself, the better.
I didn't benchmark an HTTP::Server with
Jul 29, 2019
5 checks passed
By the way, I benchmarked the simple http server on the samples directory before and after this change with
And I'm almost sure if we change Hash to have an open addressing implementation it could go up to
By comparison, doing the same benchmark against a simple server in Go gives these results:
However, Go handles parallelism and when we'll have parallelism the performance will get a bit worse, but on the other hand a single request doing expensive CPU won't be able to stop the server from receiving other requests.
@RX14 Sure! Here it it:
(I don't know if those values are good, I just copied them from their github repo)
Before this PR:
After this PR:
With a "hypothetical" Hash with open addressing:
So the results are very different from
No, that's without specifying
If I pass
Yes, but in a couple of hours.