Skip to content

Instantly share code, notes, and snippets.

@doha99-eh
Forked from janko/Gemfile
Last active October 26, 2022 10:16
Show Gist options
  • Save doha99-eh/97eddd054484ab571d8588d555ff5f7d to your computer and use it in GitHub Desktop.
Save doha99-eh/97eddd054484ab571d8588d555ff5f7d to your computer and use it in GitHub Desktop.
Memory profiling of http.rb and other popular Ruby HTTP client libraries
# Run with `rackup app.ru`
require "roda"
Roda.route do |r|
r.post "upload" do
"Success"
end
r.get "download" do
"a" * 10*1024*1024 # 10 MB
end
end
run Roda.app
require 'benchmark'
require 'faraday'
require 'json'
require "http"
require "rest-client"
require "httparty"
url = "http://localhost:9292/download"
def req_by_faraday(url)
response = Faraday.get(url)
end
def req_by_httparty(url)
HTTParty.get(url, stream_body: true) { |chunk| chunk.clear }
end
def req_by_http(url)
response = HTTP.get(url)
response.body.each { |chunk| chunk.clear }
end
def req_by_rest_client(url)
RestClient::Request.execute(
method: :get,
url: url,
block_response: -> (response) { response.read_body { |chunk| chunk.clear } })
end
def run_ben(url, n)
puts "Run benchmark with url=#{url} n=#{n}\n"
Benchmark.bm(7) do |bm|
bm.report('Faraday') { n.times { req_by_faraday(url) } }
bm.report('HTTParty') { n.times { req_by_httparty(url) } }
bm.report('HTTP') { n.times { req_by_http(url) } }
bm.report('RestClient') { n.times { req_by_rest_client(url) } }
end
end
run_ben(url, 1)
run_ben(url, 10)
run_ben(url, 100)
require "http"
require "net/http"
require "rest-client"
require "httparty"
def profile_old(name)
memory_before = `ps -p #{Process::pid} -o rss`.split("\n")[1].chomp.to_i
result = yield
memory_after = `ps -p #{Process::pid} -o rss`.split("\n")[1].chomp.to_i
total_memory = memory_after - memory_before
puts "#{name}: #{"%.2f" % (total_memory.to_f / 1024)} MB"
result
end
def profile(name, t = 100)
total_memory = 0
t.times do
memory_before = `ps -p #{Process::pid} -o rss`.split("\n")[1].chomp.to_i
result = yield
memory_after = `ps -p #{Process::pid} -o rss`.split("\n")[1].chomp.to_i
total_memory += memory_after - memory_before
end
avg_memory = total_memory / t.to_f
puts "#{name}: #{"%.2f" % (avg_memory.to_f / 1024)} MB"
# result
end
GC.disable
require_relative "common"
url = "http://localhost:9292/download"
profile("http.rb") do
response = HTTP.get(url)
response.body.each { |chunk| chunk.clear }
end
profile("Net::HTTP") do
uri = URI.parse(url)
Net::HTTP.start(uri.host, uri.port) do |http|
http.request_get(uri.request_uri) do |response|
response.read_body { |chunk| chunk.clear }
end
end
end
profile("RestClient") do
RestClient::Request.execute(
method: :get,
url: url,
block_response: -> (response) { response.read_body { |chunk| chunk.clear } })
end
profile("HTTParty") do
HTTParty.get(url, stream_body: true) { |chunk| chunk.clear }
end
# Results (download)
# ==================
#
# http.rb: 0.02 MB
# Net::HTTP: 12.36 MB
# RestClient: 12.57 MB
# HTTParty: 12.59 MB
source "https://rubygems.org"
gem "roda"
gem "http", "~> 3.3"
gem "rest-client"
gem "httparty"
require_relative "common"
require "tempfile"
tempfile = Tempfile.new
tempfile.write "a" * 10*1024*1024 # 10 MB
tempfile.rewind
path = tempfile.path
url = "http://localhost:9292/upload"
profile("http.rb") do
HTTP.post(url, form: { file: HTTP::FormData::File.new(path) })
end
profile("Net::HTTP") do
uri = URI.parse(url)
Net::HTTP.start(uri.host, uri.port) do |http|
post = Net::HTTP::Post.new(uri.request_uri)
post.set_form({ "file" => File.open(path) }, "multipart/form-data")
http.request(post)
end
end
profile("RestClient") do
RestClient.post(url, file: File.open(path))
end
profile("HTTParty") do
HTTParty.post(url, body: { file: tempfile })
end
# Results (upload)
# ================
#
# http.rb: 0.10 MB
# Net::HTTP: 0.02 MB
# RestClient: 9.03 MB
# HTTParty: 40.03 MB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment