Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switching concurrency from cpucount to 1 increated performance. Looking for an explanation #2481

Closed
wardpeet opened this issue Dec 11, 2020 · 6 comments
Labels

Comments

@wardpeet
Copy link

What are you trying to achieve?

At Gatsy we are playing with sharp's concurrency and queue'ing. It seems limitting sharp to 1 cpu (thread?) makes image generation faster for us. I've read https://sharp.pixelplumbing.com/api-utility#concurrency but still unsure what's the cause of it is. In my head concurrency should make things faster if you have multiple transforms for 1 image.

Anything we should be aware of when setting it to 1? Is this expected behaviour? How can we optimize sharp even more?

Have you searched for similar questions?
#2322

Are you able to provide a minimal, standalone code sample that demonstrates this question?
gatsbyjs/gatsby#28575

Are you able to provide a sample image that helps explain the question?

With concurrency = cpucount, queue 1 at a time

success Generating image thumbnails - 311.836s - 532/532 1.71/s
info Done building in 317.3029042 sec

concurrency = 1, queue = cpucount

success Generating image thumbnails - 174.163s - 532/532 3.05/s
info Done building in 179.6475083 sec

Second site:

With concurrency = cpucount, queue 1 at a time

Generating image thumbnails - 436.176s

concurrency = 1, queue = cpucount

Generating image thumbnails - 259.491s
@lovell
Copy link
Owner

lovell commented Dec 14, 2020

Hi, as you've seen, there are concurrency threads spawned to process each image, which can have an overhead - there's some discussion about re-using thread pools in libvips at libvips/libvips#1492

In Gatsby, am I right in thinking that the queue will look like the following?

[[in_1, out_1_1], [in_1, out_1_2], [in_1, out_1_3], [in_2, out_2_1] ...]

If so, and there are lots of JPEG inputs, then you might be experiencing a thread-safety limitation of libjpeg.

All libvips-spawned threads that operate on the same JPEG input image must share a mutex (i.e. block each other). Preventing the effects of this could be as simple as randomising the queue order, so adjacent items in the queue are more likely to refer to different input images.

@lovell
Copy link
Owner

lovell commented Dec 14, 2020

Sorry, I missed a bit of the linked issue - why is Gatsby currently only queuing one image at a time? I would imagine the queue should always contain at least 4 items, the default value of UV_THREADPOOL_SIZE, to gain any kind of parallelism.

@vladar
Copy link

vladar commented Dec 16, 2020

It is a jobs queue. Each job corresponds to a single input image but contains several image transformations: usually from 2 to 5.

So it is more like this:

[[in_1, out_1_1, out_1_2, out_1_3], [in_2, out_2_1, out_2_2,] ...]

@lovell
Copy link
Owner

lovell commented Dec 16, 2020

Thanks, this suggests you are probably are seeing the effects of JPEG input mutexes.

The proposed increase in Gatsby's "queue concurrency" will also increase thread count, which then reduces the effects of any blocked threads as these will (mostly) no longer be on the critical path.

It would be interesting to compare the two approaches when using only non-JPEG inputs to see if there is any difference.

@lovell
Copy link
Owner

lovell commented Jan 6, 2021

It looks like the linked issue at gatsbyjs/gatsby#28575 has been merged so will close this question as it appears the previous approach to queuing in Gatsby was affected by libjpeg input mutexes.

@lovell lovell closed this as completed Jan 6, 2021
@wardpeet
Copy link
Author

wardpeet commented Jan 7, 2021

Yes, thanks @lovell for the advice! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants