Replies: 3 comments
-
Hello @maximeg, That's very interesting, thank you for testing this. I think what's happening is that your processing is relatively quick, so being able to do it during the download does not save a great deal of time. I tried:
It's only 100ms of CPU that can be overlapped with download. It should save you a useful chunk of memory -- you're no longer buffering the entire source image. I don't know why implementing seek makes a difference, that seems very curious (and inefficient). I'll investigate. |
Beta Was this translation helpful? Give feedback.
-
I had a thought: how about adding upload as well, to simulate writing back to S3? The stream version should be able to overlap download and upload, and that ought to give a nice speedup. |
Beta Was this translation helpful? Give feedback.
-
I spent a little time on this again. Here's a revised version of that nice benchmark: 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 vips_ops(image)
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.thumbnail_buffer(buffer, SIZE, crop: "centre")
image = vips_ops(image)
image.write_to_file("old_way.jpg", Q: 95, strip: true)
end
def stream_way
remote = Down::Http.open(IMAGE_URL)
source = Vips::SourceCustom.new
source.on_read { |length| remote.read(length) }
# fails if we don't implement seek() ... why?
source.on_seek { |offset, whence| remote.seek(offset, whence) }
image = Vips::Image.thumbnail_source(source, SIZE, crop: "centre")
image = vips_ops(image)
image.write_to_file("stream_way.jpg", Q: 95, strip: true)
remote.close
end
def download_and_stream_way
tmpfile = Down::Http.download(IMAGE_URL)
source = Vips::Source.new_from_memory tmpfile.read
tmpfile.unlink
image = Vips::Image.thumbnail_source(source, SIZE, crop: "centre")
image = vips_ops(image)
image.write_to_file("download_and_stream_way.jpg", Q: 95, strip: true)
end
Benchmark.ips do |x|
x.config(time: 10, warmup: 2)
# streaming is slower overall, perhaps because of the number of callbacks we
# end up triggering ... try buffering reads?
x.report("old_way") { old_way }
x.report("stream_way") { stream_way }
x.report("download_and_stream_way") { download_and_stream_way }
end Changes:
I see:
Notes:
So I think it's likely that the slowdown is just the Ruby callback overhead. Therefore:
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
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:
Result:
Do you have any insight? Maybe I missed something.
Note: when I don't implement
on_seek
, I get a bunch ofread: fiber called across threads
andVipsJpeg: Premature end of JPEG file
.Beta Was this translation helpful? Give feedback.
All reactions