Re: [ROOT] drawing speed in online monitoring

From: Fons Rademakers (Fons.Rademakers@cern.ch)
Date: Sun Feb 18 2001 - 04:19:55 MET


Valery's description of how the TCanvas/TPad ROOT graphics works is 
basically correct. To summarize, each TPad is represented by an X pixmap
(stored in the X server) and each TCanvas by an X pixmap and an X window 
(window is an on screen pixmap). Drawing a single line in a TPad causes 
the sending of the X command to draw a line in the pixmap associated with
the pad. To make the pads visible one calls TCanvas::Update() which causes
all pad pixmaps to be copied to the canvas pixmap and then the canvas pixmap 
to be copied to the canvas window. This pixmap blitting is very efficient
and well optimized by the X11 server. Also handling expose events (i.e.
when a canvas gets (partially) un-obscured) is very efficient since it
only requires the blitting of the canvas pixmap, no partial repainting of
objects is needed.

Drawing directly on the screen is done by drawing directly in the canvas
window, bypassing the off screen pixmap. This is done for rubber banding,
zoom boxes, cross-hair cursor, the rotating cube, etc. However for more
permanent on screen items this is not ideal, since refreshing the window
(after being obscured) would require redrawing those parts of the objects 
that fall within the un-obscured rectangles (causing a lot of X11 client/
server traffic) and this is much more costly than just blitting the
canvas pixmap to the canvas window (especially since both reside already 
in the X server).

The ROOT GUI widgets are a different story. Each widget has its own
X window in which it is drawn. The widgets are not double buffered, i.e.
to refresh the GUI window each widget is asked to redraw itself. This is
quite acceptable and efficient for widgets since most consist of only a
few lines (for the shadow effects) and a text string. Since all widgets
are rectangular shaped it is natural to put them in their own X windows.
Also repositioning or hiding of widgets is done by just moving or changing
the visibility attribute of the widget's X window.

Pasha's remark about ROOT graphics being much slower over slow links
than PAW graphics is true and mainly due to the extra features of a
ROOT canvas (menu's, color settings and queries, cursor tracking, etc.).
With some X message analysis we probably can improve the performance by
delaying some X operations instead of doing them all at canvas creation
time. However, it is not caused by creating the extra pixmaps (creating
a pixmap is done in an X message of only 5 ints, opcode + x,y,w,h and
not by sending w x h bytes).

Coming back to Damir's original remark on histogram drawing performance.
It was related to very large histograms (several thousands of bins). Indeed
the refresh of such histograms is relatively time consuming since the 
histogram paint method clears the entire pad/canvas and redraws
the complete histogram, not just the changed bins, axis and stats.
However, even if a "fast" histogram redrawing would be implemented one 
wants to use the double buffered method to avoid screen flicker and to
support efficient window refreshing. A "fast" histogram drawing method
would require something like a shadow bin array (or bin bitmap) needed 
to know which bins have to be erased and redrawn. Extra complications 
are that bin erasing can cause mutilation of grid lines, functions and 
any other objects drawn in the pad. A "fast" histogram repaint method 
would probably require that no other objects will be allowed in the pad.

Hope this clarifies some issues around the ROOT graphics.


Cheers, Fons.



 
On Sat, Feb 17, 2001 at 08:26:17PM -0500,  Valery Fine wrote:
> 
> 
> > my 2 cents: 
> > 
> > - I think that from the technical point of view the real issue is somewhat 
> >   different from discussed in this thread: ROOT is using pixmap-based graphics 
> >   rather than vector-based, so to redraw a line one flushes on the screen a
> >   rectangle, containing this line, but not the line itself. 
> 
>   It is not correct.
> 
>   ROOT uses so-called "double-buffering" approach by default.
>   This means it draws things first into some the "memory buffer" to create 
>   the pixmap. Then the entire pixmap is used to override the screen pixmap 
>   buffer.
> 
>   If the issue is the histograms only one can provide some optimized
>   solution right away deriving the FastDrawingHistPainter from the 
>   existent HistPainter.
> 
> 
>   Fortunately one can turn off the double-buffering mode and draw things 
>   to the screen buffer directly. This option is used to draw the 
>   "rotation cube" for 3D objects.
> 
>   For the histograms one can image within the existent ROOT the scenario 
>   as follows:
> 
>  Paint():
>    1. Paint the histogram as the regular ROOT HistPainter does.
> 
>  Paint("update")
> 
>    2. Turn the "double buffering" mode  off
>    3. "Erase" the "obsolete" piece of the histogram directly on the screen
>    4. Add the "fresh" piece directly to the screen.
> 
> There are several underwater stones though. The main one. How the "painter" knows 
> which piece of the histogram has become "obsolete". To address this question 
> the painter must keep the copy of the histogram been drawn with the previous Paint 
> step and compare it with the "present up-to-date" object. 
> However even for the histogram it is not always as trivial as comparing two 
> floating-point arrays.
>   This problem has nothing to do with Qt PaintRectangle method whatsoever.
> This method is useful if the object was NOT changed but the part of its 
> screen view was destroyed. That corrupted part is defined by some rectangular 
> area on the screen. It is not our case. In this case ROOT is efficient.
> 
>   Hope this  helps
>                                           Valeri
> 
> 
> 
> 
> Pixmap-based approach 
> >   provides a lot of features very useful for high-level applications, however
> >   for many simple ones (like histogramming, for example) it perfors
> >   much, much slower. I'm still connecting to the lab over the 28K modem line 
> >   with the latency of about 170ms (sorry, no DSL in the village) and while it 
> >   is possible to run PAW remotely, performance of ROOT graphics over this line 
> >   is well below any reasonable level.
> > 
> > - as for online performance, I don't see any problem here: specialized applications 
> >   normally need specialized drawing methods. I.e. (as outlined by Valery) one can create a 
> >   canvas with its list of primitives containing just one "view" object,
> >   managing all the histograms displayed in this canvas and repainting them 
> >   in smart way. Yes, it is some work, but nothing comes for free and in this case 
> >   performance penalty paid would be at the level of repainting the whole window 
> >   vs repainting one line... but JUST ONCE, meaning somewhat tens of milliseconds, 
> >   but not seconds, per canvas..
> >   best, Pasha
> > 
> > 
> > Anton Fokin wrote:
> > > 
> > > Hi Valery,
> > > 
> > > ROOT has only ::Paint methods which basically redraw everything. In Qt, for
> > > example, each class provides PaintRectangle method and this improves the
> > > performance a lot in case you need to repaint only a part of an object.
> > > 
> > > There is also a brutal way to introduce histogram behavior I discussed in my
> > > previous mail: make TBin class and consider a histogram as a collection of
> > > TBins. TBin class knows how to redraw itself, etc. In this case
> > > TH2::Fill(x,y,1) triggers (x,y) bin and only this bin will be redrawn.
> > > 
> > > In fact I think that if a low-level facility can paint (set) one pixel on a
> > > screen, all the problems are solved...
> > > 
> > > I also think it is a bit strange to repaint/recalculate the whole complex
> > > object like TH2 if only one bin needs to be repainted.
> > > 
> > > Regards,
> > > Anton
> > > 
> > > -----
> > > 
> > >  I don't think what you are talking about is a kind of the
> > > "improvement". This does change the low level ROOT design
> > > .
> > > The main idea (as I understand it) is to minimize the dependency
> > > of the current operating system / graphics layer. As result ROOT
> > > (as its parent HIGZ) requires very few simplest graphics features.
> > > 
> > > The main ROOT idea is TPad keeps the list of the original objects those
> > > paint themselves via virtual TVirtualPAd::Paint() method.
> > > 
> > > To implement what you are speaking about this model should be changed.
> > > Namely instead of the list of objects TPad must be in possession of the
> > > instance of the "helper" / "proxy ??" class objects for the objects one
> > > wants
> > > to be drawn.
> > > 
> > > This means to be able to optimize drawing the way you propose
> > > the author of the class has to provide another "helper" class rather
> > > the MyClass::Paint method. In fact it is very way Microsoft Foundation
> > > Classes are designed.
> > > 
> > > "de Facto" ROOT team has adopted such approach for some classes
> > > like  THxx and TNtuple introducing so-called "painters"
> > > However this is a kind of patch that doesn't change the original schema.
> > > 
> > > Each scheme has its own pro and cons.
> > > 
> > > The current schema works well when one needs to play with many different
> > > kind
> > > of classes and wants  implementing things quickly.
> > > 
> > > "Microsoft" schema works better when the number of classes is restricted
> > > and one wants optimize drawing to many different real hardware devices.
> > > 
> > > One can find this approach within ROOT 3D graphics classes. There
> > > one has to create the list of 3D objects to be draw and then select some
> > > particular rendering method: X3D, OpenGL, Open Inventor.
> > > 
> > > For each type of the 3D rendering ROOT creates a special "view" objects.
> > > As result the concrete viewer is provided with objects optimized for this
> > > particular viewer. But it loses the capability to represent the arbitrary
> > > class object. Only "known" 3D objects can be drawn.
> > > 
> > > http://www.smartquant.com
> > 

-- 
Org:    CERN, European Laboratory for Particle Physics.
Mail:   1211 Geneve 23, Switzerland
E-Mail: Fons.Rademakers@cern.ch              Phone: +41 22 7679248
WWW:    http://root.cern.ch/~rdm/            Fax:   +41 22 7677910



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:36 MET