Skip to content

Large overhead for drawing plots with lots of data points #94

@alex-hhh

Description

@alex-hhh

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-plot will draw the plot using the draw-lines dc<%> method, and do all plotting calculations itself
  • the third one, do-manual-plot/individual-lines will draw the plot using one draw-line call 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))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions