-
Notifications
You must be signed in to change notification settings - Fork 62
Closed
Labels
Description
Hi @jcupitt,
I saw the promising streaming features from the 8.9 release 🥳.
So I tested to see if I could gain some perf improvement over one of my uses of vips.
The result is not what I hoped for.
Here is a synthetic test I used:
puts "Ruby version: #{RUBY_VERSION}"
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "benchmark-ips"
gem "down"
gem "http"
gem "ruby-vips"
end
require "benchmark/ips"
require "down/http"
IMAGE_URL = "https://images.unsplash.com/photo-1491933382434-500287f9b54b?q=80&w=5000"
SIZE = 512
def calc_shrink(image)
image_size = image.size.min
exp = Math.log2(image_size / (SIZE * 2.0)).floor
[2 ** exp, 8].min # max for jpeg is 8x8
end
def vips_ops(image)
image = image.thumbnail_image(SIZE, height: SIZE, crop: "centre")
image = image.sharpen(sigma: 1, x1: 2, y2: 10, y3: 20, m1: 0, m2: 3)
image
end
def old_way
buffer = HTTP.get(IMAGE_URL).to_s
image = Vips::Image.new_from_buffer(buffer, "", access: :sequential)
shrink = calc_shrink(image)
image = Vips::Image.new_from_buffer(buffer, "", access: :sequential, shrink: shrink) if shrink > 1
image = vips_ops(image)
# simulate old process then write to file
result = image.jpegsave_buffer(Q: 95, interlace: true, strip: true)
File.write("old_way.jpg", result)
end
def stream_way
remote = Down::Http.open(IMAGE_URL)
source = Vips::SourceCustom.new
source.on_read { |length| remote.read(length) }
source.on_seek { |offset, whence| remote.seek(offset, whence) }
image = Vips::Image.new_from_source(source, "", access: :sequential)
shrink = calc_shrink(image)
image = Vips::Image.new_from_source(source, "", access: :sequential, shrink: shrink) if shrink > 1
image = vips_ops(image)
image.write_to_file("stream_way.jpg", Q: 95, interlace: true, strip: true)
remote.close
end
Benchmark.ips do |x|
x.config(time: 10, warmup: 2)
x.report("old_way") { old_way }
x.report("stream_way") { stream_way }
endResult:
Ruby version: 2.6.5
Fetching gem metadata from https://rubygems.org/............
Resolving dependencies...
Using rake 13.0.1
Using public_suffix 4.0.3
Using addressable 2.7.0
Using benchmark-ips 2.7.2
Using bundler 1.17.3
Using unf_ext 0.0.7.6
Using unf 0.1.4
Using domain_name 0.5.20190701
Using down 5.1.0
Using ffi 1.11.3
Using ffi-compiler 1.0.1
Using http-cookie 1.0.3
Using http-form_data 2.2.0
Using http-parser 1.2.1
Using http 4.3.0
Using ruby-vips 2.0.17
Warming up --------------------------------------
old_way 1.000 i/100ms
stream_way 1.000 i/100ms
Calculating -------------------------------------
old_way 3.326 (± 0.0%) i/s - 33.000 in 10.105056s
stream_way 3.230 (± 0.0%) i/s - 32.000 in 10.044809s
Do you have any insight? Maybe I missed something.
Note: when I don't implement on_seek, I get a bunch of read: fiber called across threads and VipsJpeg: Premature end of JPEG file.