Has anyone considered re-implementing processing.js on top of SVG?

63 views
Skip to first unread message

hughw

unread,
Sep 30, 2010, 7:26:44 PM9/30/10
to Processing.js
Hi all,

I am enjoying my first crack at processing and processing.js. This is
a great piece of work. Thanks to John and all the developers.

I am sitting here looking at a visualization I've constructed that is
doing nothing 99.99999% of the time. Yet Google Chrome renderer is
hogging 90% CPU. I am using frameRate = 30, but 15 wasn't very
different. Processing.js must be executing those unchanged drawing
commands repeatedly. I'd hate to see this sketch burn through an iPad
battery.

If processing.js were to render to SVG rather than canvas, this would
not be an issue, would it? The SVG scene graph would mostly idle
along.

I'm sure many people have thought this through and canvas has won out.
I just thought I'd ask what people who've considered the question
before, how come canvas wins? Is it a bad idea, or not possible, to
reimplement interactive sketches in SVG ?

Thanks,

Hugh

Just for fun here is the sketch in question.


int nx = 640;
int ny = 800;

int [] t;
float [] z;
float zHover = 0;

int marginY = 100;
PFont depthFont;

void makeData() {
float rop = 100.0 /3600.0; // 100 fph
int connectionTime = 7 * 60;
float standLength = 90;

int tripStand = 90;
int tripTime = 200 * 60; // 200 minutes tripping, at 7200 + 90 * 10
= 8100 ft.
float zMin = 7200;

int nt = 24 * 3600;

t = new int [nt];
z = new float [nt];

t[0] = 0; z[0] = zMin;
int stand = 0;


for (int i=1; i< nt; ) {
int delayTime = 0;
float deltaDepth = 0;



float lastZ = z[i-1];
int thisStand = floor(lastZ / standLength);
if ( thisStand != stand) {
stand = thisStand;
// either make a connection or a trip

if ( stand == tripStand) {
delayTime = tripTime;
} else {
delayTime = connectionTime;
}
} else {
delayTime = 1;
deltaDepth = rop;
}

// loop over delayTime time and depth samples
for (int j = 0; j < delayTime; j++) {
t[i+j] = i+j;
z[i+j] = z[i+j-1] + deltaDepth/delayTime;
}
i += delayTime;
}
}

void setup(){
size( nx, ny);
//noLoop();
frameRate( 30);
colorMode(RGB);
smooth();
depthFont = createFont("SansSerif", 20);
textFont(depthFont);
makeData();

int nz = z.length;


}



void draw() {
background(0);
stroke(200);

int nz = z.length;

float x1 = width/2;
float y1 = map (z[0], z[0], z[nz-1], marginY, ny - marginY);


int contourInterval = 10;

int lastContourT = t[0];
float lastContourZ = floor(z[0]/contourInterval) * contourInterval;


// Draw ellipses at minor depth intervals, colored according to the
time duration

for (int i=1; i<nz; i++){
float thisContourZ = floor (z[i] / contourInterval) *
contourInterval;

if ( thisContourZ != lastContourZ) {

int thisContourT = t[i];

float thisRop = 3600 * (thisContourZ - lastContourZ) /
(thisContourT - lastContourT);

float x0 = x1;
float y0 = y1;
x1 = width/2;

y1 = map (z[i], z[0], z[nz-1], marginY, ny - marginY);

float weight = 1.0;
if (thisContourZ > zHover && lastContourZ <= zHover) {
weight = 2.0;
}
strokeWeight(weight);

float mcolor = map (thisRop, 0, 110, 0, 255);
fill ( 255 - round(mcolor), 12, 64);
ellipse( x1, y1, 170, 30);

// println("rop @ " + thisContourZ + " = " + thisRop + ", hue = "
+ round(mcolor));
lastContourT = thisContourT;
lastContourZ = thisContourZ;


}
}


// draw the depth intervals
fill (255);
int zInterval = 100;
for (int zz = floor(z[0] / zInterval) * zInterval + zInterval; zz <
z[nz-1]; zz += zInterval){
int x = width/2 + 30;
float y = map (zz, z[0], z[nz-1], marginY, ny - marginY);
text (zz, x + 200, y);
}
}

void mouseMoved () {

zHover = map ( mouseY, marginY, ny - marginY, z[0], z[z.length
-1]);
// println(zHover);
}

Cary Hull

unread,
Sep 30, 2010, 9:48:24 PM9/30/10
to proces...@googlegroups.com
Do a search for raphealjs.


--
You received this message because you are subscribed to the Google Groups "Processing.js" group.
To post to this group, send email to proces...@googlegroups.com.
To unsubscribe from this group, send email to processingjs...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/processingjs?hl=en.




--
01100011 01100001 01110010 01111001

Will Farrell

unread,
Sep 30, 2010, 9:54:45 PM9/30/10
to proces...@googlegroups.com
The canvas element is based on bitmap data like processing, svg is vector data. 

Tom Longson (nym)

unread,
Sep 30, 2010, 10:34:29 PM9/30/10
to proces...@googlegroups.com
Haters going to hate, don't let the vectors get you down Hugh!

Cheers,
Tom Longson (nym)
------------------------------
http://tomlongson.com

Cary Hull

unread,
Sep 30, 2010, 11:39:36 PM9/30/10
to proces...@googlegroups.com
On Thu, Sep 30, 2010 at 7:34 PM, Tom Longson (nym) <tom...@gmail.com> wrote:
Haters going to hate, don't let the vectors get you down Hugh!

I suppose only my comment could be considered "hate". Let me elaborate: Try out raphaeljs, which is just like processingjs but based on svg. Prove to yourself which is more performant, or whatever.



--
01100011 01100001 01110010 01111001

timeu

unread,
Jan 11, 2011, 5:24:49 AM1/11/11
to proces...@googlegroups.com
SVG probably only makes sense if you have to deal with small amounts of data. As soon as you have to draw a lot of objects (> 500) the performance will be really bad with SVG.



Jeremy Arca

unread,
Jan 11, 2011, 12:32:40 PM1/11/11
to proces...@googlegroups.com
not necessarily true, i'm currently working on a plotting application for work and we are plotting 3000+ objects (circles, polygons, lines) into each cell/image and SVG works just fine....of course it performs rather slow on browsers like IE, but i think that's due to more of the javascript engine behind the browser.

timeu

unread,
Jan 12, 2011, 5:17:42 AM1/12/11
to proces...@googlegroups.com
SVG scales better with increasing resolution however canvas is definitely faster and scales better with increasing number of objects. That's basically related to the way they work. As far as I know SVG is only hardware accelerated in IE9. However canvas should get hardware acceleration in most browser in the next versions. 

I don't say you shouldn't use SVG at all It really depends on for what you are using.

Kyle

unread,
Jan 12, 2011, 10:30:00 AM1/12/11
to Processing.js
I would imagine the bottom-line for why Processing.js is done with
canvas is because it mimics the natural processing environment. Both
are pixel-based visualizations, where you are changing pixels on a
rectangle of screen and you do this from scratch every time you loop
and clear it (with background()). SVG is more like the typical way of
working with Flash, you construct a Sprite and you add it to the
display-list and it just stays theres until you remove it.

So Processing.js just doesn't readily translate to being an SVG
implementation. However, Processing.js does support SVG, look at
PShape (http://processingjs.org/reference/PShape)

@timeu - Canvas has hardware-acceleration in IE9 as well (but it
doesn't support compsite operations :( ).

SVG and Canvas are both great and have many things to consider. For
example on mobile... Android doesn't support svg, because it adds 1m
to the webkit image (lame!) (http://code.google.com/p/android/issues/
detail?id=1376)


if your looking for a good svg library, check out http://raphaeljs.org

-Kyle Phillips

Mike Niemi

unread,
Jan 12, 2011, 6:54:19 PM1/12/11
to Processing.js
I've been playing around with the performance of Processing.js/canvas
vs Raphael/SVG/div. Here are some frames per second (fps) results I'm
currently seeing from the 5 leading browsers:
http://svbreakaway.info/tp.php#jan12

The plots are maybe a bit overwhelming, but
- Rows are canvas size. Columns are browser.
- fps is on the y-axis. # balls on the x-axis.
- The red line (generally max fps) is without any rendering.
- The green line is rendering using Processing.js. The green area is
the difference - to try to make it easier to see.. well, the
difference.
- The solid blue line is a simple replacement of ellipse() and line()
in the Processing.js code with calls to Raphael circle() and path() -
creating a new object for each ball and line on each frame.
- The dashed blue line is where I allocate the Raphael circle and path
objects at the setup and then reuse them for the whole run (using
calls to attr() on the objects to change their position from frame to
frame). Again, the blue area is the difference between non-rendering
(the red line) and the Raphael/SVG results (solid and dashed blue
lines).

I think the results were fairly predictable - Chrome did well,
Processing.js did well, the version of the Raphael/SVG testcase that
reused the objects (generally) did better than the create-a-new-object-
each-time version.

There were a couple surprises - Opera and IE9 exhibit what I *think*
are problems (but it could be something I'm doing), and my new-and-
improved-through-reuse version of the Raphael/SVG testcase was
actually worse in some of the Safari runs (at a small number of
objects, 10 balls).

The current version of the benchmark is here:
http://svbreakaway.info/dfe/
in case you want to try it yourself. (I'll try to sort out the IE9
problem yet)

Regarding the original post, one (maybe obvious) option is the
judicious call to loop() and noLoop(). I'm using Processing.js for my
report-drawing code in the benchmark runner (dfe) using loop() when
woken up by the Dromaeo Javascript code and noLoop() at the bottom of
draw(). Just thought I'd mention it.

Sorry for the long post,
Mike

timeu

unread,
Jan 13, 2011, 5:45:41 AM1/13/11
to proces...@googlegroups.com
@Mike 

These are fairly interesting results:
 - Big differences in fps btween for example Chrome and Firefox. Is it possible that canvas in chrome is hardware accelerated and not in firefox? Would be interesting to see how firefox 4.0 performs. 
 - In chrome, opera and safari it seems that the canvas performance starts degrading faster at around 20 balls whereas the SVG performance starts degrading slower
 - I would have assumed that canvas scales better with higher number of objects to be drawn compared to svg however your plots seem to say the opposite. Would be it be possible to run the tests with even higher number of balls ( > 500)?



mediapathic

unread,
Jan 12, 2011, 7:30:49 PM1/12/11
to proces...@googlegroups.com
This is some really great work. I've been playing with both pjs and
raphael (as well as jit, but that's kind of a different beast) for
various applications and it's good to have a better idea of when it
would be appropriate to use each tool.

Thanks for doing this!

--Steen

Mike Niemi

unread,
Jan 15, 2011, 12:30:46 AM1/15/11
to Processing.js
Steen,

Yeah, it's kind of fun to see the differences (and similarities)
between the results on the various browsers. As I mentioned in my
reply to timeu, I think the pendulums benchmark is probably an
Order(n^2) code in that each free particle is bound to every other by
an attraction force. It would be nice to make up a couple other
benchmarks (e.g. an Order(n) code with a graphic output) that are
interesting/relevant for comparison.

Mike

Mike Niemi

unread,
Jan 14, 2011, 10:12:55 PM1/14/11
to Processing.js
timeu,

Ooo. Good questions.

> Is it possible that canvas in chrome is hardware accelerated
> and not in firefox?
I don't know how to quantify it but the other Dromaeo results also
seem to show Chrome performing well.

> Would be interesting to see how firefox 4.0 performs.
I added to 4.0 results. Looks like a nice boost in performance over
version 3.

> Would be it be possible to run the tests with even higher number
> of balls ( > 500)?
I made runs out to 400 balls (there are 2 circles and 1 line drawn per
ball so 1200 rendered objects) and stopped there because the results
on the slower browsers start to get hinky. The plots are here:
http://svbreakaway.info/tp.php#jan14
Performance starts to be dominated by the calculation of the particle
positions. I think it is n-squared in that every free particle is
bound to every other free particle with a force (probably a class of
problems/codes).

Mike

timeu

unread,
Jan 16, 2011, 7:24:39 AM1/16/11
to proces...@googlegroups.com
@Mike

Thanks for updating your benchmarks and sharing the results. 
I guess you are right. The benchmark is clearly CPU-bound. It would be interesting to see how canvas and SVG compare if you run a benchmark which is not really CPU bound. (i.e > 400 objects with simple positional calculations). I would guess that the performance gap between SVG and Canvas would be bigger. 
The performance differences between minor firefox revisions (b8 and b9) is also somehow interesting. 

Ümit

Mike Niemi

unread,
Jan 22, 2011, 9:14:52 AM1/22/11
to Processing.js
I added a benchmark that just draws shapes - circles, lines,
rectangles, and a short text string. Each is a modest size - there is
a screen sample in my little writeup. I ran it from 4 to 4000 shapes
per frame. ("4" is one of each shape, "4000" is 1000 of each shape,
overlapping, placed randomly, colored randomly. I create a table of
random numbers during setup, so that calculating the random number
isn't inside the fps loop.) The interesting plot is here:
http://svbreakaway.info/tp.php#jan21a

I've normalized the times to "per shape rendered" - so a result that
is linear with the number of shapes would be a flat line on the
graph. Which is the case for Processing.js. SVG showed varying
degrees of non-linear growth. Well, except for Firefox, which
appeared to become more efficient with a large # of shapes. I wonder
if their renderer does clipping or some sort of z-buffer approach
before rendering - to say, detect that a shape is completely covered
so it won't bother rendering it at all? I can't think of anything
else (other than an error in my benchmark, although the results seem
consistent). Anyone know? I'll make a version of the benchmark with
(I guess pretty small, but) non-overlapping shapes to try.

Mike

Mike Niemi

unread,
Jan 24, 2011, 7:09:05 PM1/24/11
to Processing.js
> except for Firefox, which appeared to become more efficient with a large # of shapes

Just to followup on this.. I made up a run where the shapes don't
overlap. The end result was that Firefox SVG rendering now showed
slight growth as the number of shapes increased (rather than getting
more efficient as the case with the overlapping shapes). So they
appear to do some sort of clipping/z-buffer evaluation.

My little writeup with plots is here:
http://svbreakaway.info/tp.php#jan24

Mike

Reply all
Reply to author
Forward
0 new messages