GRUtils.jl
GRUtils.jl copied to clipboard
Loss of performance with respect to GR
From #45:
I currently observe a slight performance loss of 30-40% when switching from GR to GRUtils. I would like to investigate this in more detail.
I have made some comparisons (in the REPL with the GKS device, and in Atom with Juno's plotting pane) using this code and the resulting table: https://gist.github.com/heliosdrm/e242ab6c3e035af72e4d70c521c187b3
(In the uploaded code, the jl
file is ready to calculate times taken by GR; switch commented lines to change to GRUtils.)
I have observed the following (see the table in the gist):
-
using GRUtils
indeed takes 20-30% more time thanusing GR
. However, GRUtils is itself using GR, so it cannot be faster. Package loading times are difficult to compare until we try to merge the new module into GR, replacingjlgr
. - The time taken by the very first plot (row
plot_first
in the CSV file) is actually about 1.3 s faster with GRUtils, both in the REPL and in Atom. - The first time any other kind of plot is made (after the very first one), GRUtils is between 0.5 s and 1 s slower than GR.
- Just creating new plots (without drawing them) of kinds that have already been used, is about 80% faster with GRUtils, with some remarkable exceptions: in the REPL,
imshow
andtrisurf
are many times slower; in Atom onlyimshow
(and the slowdown is not that drastic). - In GRUtils drawing the plot is an operation disconnected from creating it (the calls to "core" functions from GR are in their vast majority made from
draw
methods, normally called when a figure is shown). The rowsplot_draw
,stem_draw
, etc. in the CSV file show the time taken by creating and drawing the plots, which is normally much more expensive than only creating them. In those rows, the times taken by GR and GRUtils are more similar. GRUtils is on average slower than GR, but the difference is small (and sometimes negative) except inimshow
andtrisurf
, whose problem is in their creation, not in drawing them.
In short: there is indeed something to look at in the cases of imshow
and trisurf
. But for the rest, there is a tradeoff to be considered.
I guess that the slower "first plot of each kind" is due to the fact that the method draw
for Geometry
also dispatches on the type of a second argument, which is a Val{kind}
(where kind
is the symbol that represents the kind of the plot. So, the specific method for drawing each geometry kind is not compiled until it is actually used. I made it that way in order to avoid the many if
blocks that jlgr
has, and perhaps (I'm not really sure) this is a factor for the improvement in the time to the very first plot. In plots that do not use a great variety of kinds, this should not be very annoying, but it may be worth to see how to improve this further.
Also, the fact that on average drawing the plots is more expensive than in GR, is probably due to the fact that the draw
method for Figure
always clears the current device and redraws the whole plot (including subplots). I expect this to be specially noticeable when new data are added to a figure after hold(true)
or subplot(m,n,p)
, because the current implementation in jlgr
keeps the device without clearing, and just adds new primitives to it. That is more efficient than the approach taken in GRUtils, but it leads to the problems observed e.g. in Atom and when saving figures with multiple plots with GR.