[OpenJDK 2D-Dev] Thread-Private RenderBuffers for RenderQueue?
Dmitri Trembovetski
Dmitri.Trembovetski at Sun.COM
Mon Mar 24 22:23:04 UTC 2008
Chris pointed to me that currently SunToolkit.lock() uses
ReentrantLock which is supposed to have better
characteristics than built-in Java synchronization
under contention.
So it would be interesting to see exactly what you were
measuring, and how.
Also, if you're doing any kind of Java2D performance
testing I would encourage to use J2DBench as the
benchmark (can be found in jdk/src/share/demo/J2DBench).
You can plug in new tests if the existing ones don't
match what you want to test.
Thanks,
Dmitri
Dmitri Trembovetski wrote:
>
> Hi Clemens.
>
> Clemens Eisserer wrote:
>> Hello,
>>
>>> Since most applications do render from one thread (either the
>>> Event Queue like Swing apps, or some kind of dedicated rendering
>>> thread like games), the lock is indeed very fast, given
>>> biased locking and such.
>>>
>>> I would suggest not trying to optimize things - especially tricky
>>> ones which involve locking - until you have
>>> identified with some kind of tool that there's a problem.
>>
>> I did some benchmarking to find out the best design for my new
>> pipeline, and these are the results I got:
>>
>> 10mio solid 1x1 rect, VolatileImage, server-compiler, Core2Duo-2ghz,
>> Intel-945GM, Linux:
>>
>> 200ms no locking, no native call
>> 650ms locking only
>> 850ms native call, no locking
>> 1350ms as currently implemented in X11Renderer
>
> Did you mean OGLRenderer? The X11Renderer doesn't use single
> thread rendering model and thus doesn't need render queue.
>
> Note that on X11 the render queue lock is doubled as the lock against
> all X11 access - for both awt and 2d. We must lock around it because
> we all use the same display, and X11 is not multi-threaded (at
> least in the way we use it).
> This means that the lock is likely to be promoted to a heavyweight lock,
> which is why it is expensive.
>
> So the problem with having separate render buffers per thread is that
> at some point you will have to synchronize on SunToolkit.awtLock()
> anyway.
>
>> I did rendering only from a single thread (however not the EDT), in
>> this simple pipeline-overhead test the locking itself is almost as
>> expensive as the "real" work (=native call), and far more expensive
>> than an "empty" JNI call.
>> However this was on a dual-core machine, on my single-core amd64
>> machine locking has much less influence. As far as I know biased
>> locking is only implemented for monitors.
>> Xorg ran on my 2nd core, and kept it with locking only 40% busy,
>> without locking about 80%.
>>
>> However I have to admit there are probably much more important things
>> to do than playing with things like that ;)
>
> You probably can explore ways to improve the current design,
> which only allows a single rendering queue. For example,
> we had discussed the possibility of extending the STR design
> to allow a rendering thread per destination. But again,
> on unix it will bump against the need to sync around X11 access.
>
> You can also play with having a render buffer per thread as
> you suggest, but your rendering thread will have to sync for
> reading from each render buffer - presumably on the same lock
> as the thread used to put stuff into that buffer.
> All doable, but risky and hard to assess the benefits before
> you have a working implementation. Just commenting out
> locks gives wrong impression, since the resulting code
> becomes incorrect and thus the benchmark results can't be
> trusted.
>
> Anyway, I would suggest that you look at optimizing
> this later.
>
>>> If it appears null during a sync() call, no harm is done (the
>>> sync is just ignored - which is fine given that the render queue
>>> hasn't been created yet, so there's nothing to sync), so this is
>>> not a problem.
>> But what does happen if it has already been created, but the thread
>> calling sync() just does not see the updated "theInstance" value?
>> Could there be any problem when sync()-calls are left out?
>
> If the thread calling sync() sees theInstance as null, this means
> that it could not have anything to sync. If there's no queue,
> it could not have put anything into that queue prior to
> calling sync(). The sync() can be safely ignored.
>
> Thanks,
> Dmitri
More information about the 2d-dev
mailing list