As the author of Xamine I should clarify a bit for historical purposes. Both Xamine and Root draw rectangles for each channel. The difference is in how those rectangles are drawn. Dusting off my rusty Xwindows programming knowledge…
When you draw a rectangle using XDrawRectangle each channel requires a round trip interaction with the X server if that is your display engine.
What Xamine does is create an XImage object. Those are client side entities rather than server side entities. XPutPixel is called, possibly several times per channel to draw a rectangle, in the image but, since these are executed fully client local they run much faster than XDrawRectangle. Once the image is drawn a single server interaction (XPutImage) is called to transfer that image to the server and hence the display itself.
There is a simplification in this description and a potential for an improvement in Root that does not break its current model (maybe):
Simplification: If X11 batching is enabled, several XDrawRectangle operations can be batched into a single client/server interaction.
Potential optimization:
If, in general, several channels map to the same color value, the algorithm for plotting a 2d in col form could, instead of scanning the histogram in coordinate space, drawing a rectangle at a time, locate all channels that map to each color and perform an XDrawRectangles for each batch of rectangles it needs to draw with a common color. That would reduce the server interactions to one per color level rather than one per rectangle – under the assumption that XDrawRectangles is not just doing a client side loop to do a bunch of XDrawRectangle calls but sending a single message to the X11 server with several RECTANGLE atoms.
Unfortunately XDrawRectangles only takes a single GC (which is where the color is stored), hence the need in this optimization to sort the rectangles by color level.
This optimization could be done in a manner that is display engine independent by adding a drawRectangles method to the display API and then letting X11 use XDrawRectangles and windows, e.g. use several Rectangle calls to implement it.
Ron.
[quote=“jrtomps”]@couet
After some discussion here at the NSCL, we believe there are two major differences between Xamine and ROOT that produce the performance difference.
- Xamine computes the image of a histogram through multiple calls to XPutPixel whereas ROOT draws a histogram via calls to XDrawRectangle. The difference between these two is that XPutPixel operates on an XImage that is local to the client of the X server. Each call to XPutPixel causes no protocol requests to be made to the X server. It is therefore fast. XDrawRectangle on the other hand appears to communicate with the server. If this is the proper understanding, it means that ROOT performance is severely hindered by the overhead of communicating with the server, since it tries to do so for every single bin in the histogram. In Xamine, the only communication that occurs with the server is after the XImage is fully drawn. It does so by calling XPutImage, which transfers the local XImage to the X server in one fell swoop.
To test the difference, in Xamine, I replaced XPutPixel calls with XDrawRectangle calls. Doing so destroyed Xamine’s performance to equivalent or even worse than the rendering performance of ROOT. Nothing else changed in Xamine, so clearly XDrawRectangle is a major culprit to the problem.
- Xamine only accesses the histogram contents as many times as there are pixels to draw. So if there are only 1000 pixels available to draw in and 1M bins in the histogram, Xamine will only access bin content 1000 times. ROOT on the other hand draws a rectangle for every bin in the histogram. This is extra effort.
Because of the test I did by replacing XPutPixel with XDrawRectangle, I believe that addressing the first issue is where the most performance is to be gained. It is clear that implementing this would introduce a bit of a paradigm shift to the way ROOT handles its rendering and would likely affect a significant amount of code. How much? I am not so sure.
I am curious to know you or anyone else’s thoughts on how to proceed considering that this has the potential to affect a significant amount of code.[/quote]