-
-
Notifications
You must be signed in to change notification settings - Fork 37
Description
A private email from a person who noticed poor performance of the plot package when plotting millions of data points, prompted me to run some tests to see what the overhead of the actual plot package is on top of racket/draw (which is used for all the drawing). The result is that it is a lot.
There are two programs below (the second one has two variants):
- one is drawing a plot using
lines - the second one ,
do-manual-plotwill draw the plot using thedraw-linesdc<%>method, and do all plotting calculations itself - the third one,
do-manual-plot/individual-lineswill draw the plot using onedraw-linecall for each line segment, also doing all plotting calculations itself.
Here is the performance of the programs
| data points | plot | draw-lines | individual draw-line |
|---|---|---|---|
| 100 | 31ms | 15 ms | 15ms |
| 1'000 | 78ms | 15ms | 15ms |
| 10'000 | 920ms | 93ms | 156ms |
| 100'000 | 81'515ms | 3'046ms | 1'484ms |
| 1'000'000 | too long | 45'734ms | 16'634ms |
For large number of points, the time of the plot version becomes too large very quickly, much more than the time increase for draw-lines and draw-line versions. Note that plot ultimately uses the same draw package, so the plot package overhead is probably the plot time minus the draw-lines time.
I also found that, for large number of points, a single draw-lines call is much slower than multiple draw-line calls, one for each line -- this is somewhat counterintuitive, but I could not find an explanation for this...
#lang typed/racket
(require plot)
(: points (Listof (List Real Real)))
(define points (build-list 100000 (lambda ([x : Index]) (list x (random)))))
(time
(parameterize ([plot-decorations? #f])
(plot-bitmap (lines points #:color 6))))#lang racket
(require racket/draw
plot ;; just for plot-width, plot-height
)
(define (transform-points p)
(define-values (min-x min-y max-x max-y)
(for/fold ([min-x (first (first points))]
[min-y (second (first points))]
[max-x (first (first points))]
[max-y (second (first points))])
([point (in-list (rest points))])
(define x (first point))
(define y (second point))
(values (min min-x x) (min min-y y) (max max-x x) (max max-y y))))
(define dx (- max-x min-x))
(define dy (- max-y min-y))
(define w (plot-width))
(define h (plot-height))
(define (transform point)
(define x (first point))
(define y (second point))
(cons (* w (/ (- x min-x) dx))
(* h (- dy (/ (- y min-y) dy)))))
(map transform points))
(define (do-manual-plot points)
(define bm (make-object bitmap% (plot-width) (plot-height)))
(define dc (new bitmap-dc% [bitmap bm]))
(send dc set-pen (send the-pen-list find-or-create-pen "purple" 1 'solid))
(define plot-points (transform-points points))
(send dc draw-lines plot-points)
bm)
(define (do-manual-plot/individual-lines points)
(define bm (make-object bitmap% (plot-width) (plot-height)))
(define dc (new bitmap-dc% [bitmap bm]))
(send dc set-pen (send the-pen-list find-or-create-pen "purple" 1 'solid))
(define plot-points (transform-points points))
(for ([p1 (in-list plot-points)]
[p2 (in-list (rest plot-points))])
(send dc draw-line (car p1) (cdr p1) (car p2) (cdr p2)))
bm)
(define points (build-list 100000 (lambda (x) (list x (random)))))
(printf "individual draw-line calls~%")
(time (do-manual-plot/individual-lines points))
(printf "single draw-lines call~%")
(time (do-manual-plot points))