I have the following setting: a webpage is generating requests for images which are rendered on the server implemented in C++. The object generating images is very expensive to initialize so it is kept initialized in 3-4 copies on the server.
There are usually a number ~10 requests for images at the same time, so the copies of the object need to be locked.
The problem is that objects need to be locked for a rather long period ~0.5-1.0 seconds until the image is done rendering. What is currently done is there is an array of locks for each copy of the object and image requests are assigned to a particular copy in a random way.
Benchmarking with mutrace shows contention of locks:
mutrace: Total runtime is 127612.949 ms. mutrace: Showing 10 most contended mutexes:
+-----------------------------------------------------------------------------------+
| Mutex# Locked Changed Cont. tot.Time[ms] avg.Time[ms] max.Time[ms] Flags |
+-----------------------------------------------------------------------------------+
| 65027 5129457 387745 79148 754.146 0.000 8.045 M-.--. |
| 443324 754545 172260 25960 7984.958 0.011 43.426 Mx.--. |
| 20645 1728872 5531 412 579.019 0.000 5.091 M-.--. |
| 540024 453 406 280 50068.601 110.527 830.096 M-.--. |
| 539797 462 413 254 39928.156 86.425 834.889 M-.--. |
| 540460 475 419 244 34194.536 71.988 698.798 M-.--. |
| 299764 3036 2091 215 149.902 0.049 11.128 Mx.--. |
| 491395 108 94 87 545.591 5.052 58.174 M-.--. |
| 518584 41440 1744 79 367.372 0.009 6.292 M-.--. |
| 487295 48304 5491 69 250.457 0.005 64.186 M-.--. |
+-----------------------------------------------------------------------------------+
Basically locks 539797,539797,540460 are contented the entire time. I am thinking of using a single producer/single consumer lock-free queue for each object that generates images, here's roughly the pseudocode:
Whenever an image request comes to the server, the callback is invoked with some image parameters:
function serverCallBack(params imageParams) {
queueId = imageParams.getQueueId()
queues[queueId].put(imageParams)
result = getImage()
return image
}
Where I am stuck is that we need a way to get the resulting image when the object is done rendering. Any ideas on how to implement this one?
Clarification
It is clear that if there are more requests than objects, then some requests will be blocked. The question is weather it is possible to implement blocking in a more efficient way than with mutexes