David John Welsh
David John Welsh

Reputation: 1569

Which is more efficient in SVG, multiple small paths or one giant one?

If I am displaying a regular SVG in a browser (either as an independent file or embedded in HTML), is there any theoretical difference in efficiency between having lots of separate path elements and one giant path element?

I'm thinking of doing some kind of animation from one picture into a totally different picture. If I can draw them both with just the one <path> tag each, animating between them will be much easier. I am however worried that if the path is too large, the processing might take longer or be less efficient.

I have not tested this myself because it would require concatenating a lot of paths by hand, which I don't want to waste time on if it turns out to be hideously inefficient in the end :-(

Cannot seem to find anything in the docs on this, either at W3C or Mozilla. Any comments appreciated.

Upvotes: 8

Views: 4128

Answers (2)

chris
chris

Reputation: 3193

I know this is old, but answering in case it helps others:

The following plots a line of 1000 random coordinates, 1st as a single path and 2nd as multiple separate paths.

I know it is not very rigorous as a benchmark but it results in ~10x slower performance for enter() of the multiple paths on Chrome 84.

const pathSingle = [
  [0, 0]
];
const pathMultiple = [];

for (let i = 0; i < 1000; i++) {
  const pathSingleLength = pathSingle.push([
    Math.floor(Math.random() * 200),
    Math.floor(Math.random() * 200),
  ]);

  pathMultiple.push([
    pathSingle[pathSingleLength - 2],
    pathSingle[pathSingleLength - 1]
  ]);
}

const svg1 = d3
  .select("body")
  .append("svg")
  .attr('width', 200)
  .attr('height', 200);

const line = d3.line();

console.time('single');
svg1
  .selectAll('path')
  .data([{
    path: pathSingle,
  }])
  .enter()
  .append('path')
  .attr('d', d => line(d.path));
console.timeEnd('single');

const svg2 = d3
  .select("body")
  .append("svg")
  .attr('width', 200)
  .attr('height', 200);

console.time('multiple');
svg2
  .selectAll('path')
  .data(pathMultiple)
  .enter()
  .append('path')
  .attr('d', d => line(d));
console.timeEnd('multiple');
path {
  fill: none;
  stroke-width: 1px;
  stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.js"></script>

Upvotes: 7

Nick Bastin
Nick Bastin

Reputation: 31329

You don't have to do it by hand, it's trivial to test this with a small xml parser (make up some toy data if you have to).

That being said, in a reasonable world without completely exotic optimization (where small paths ended on the same point would become a single long path), long paths are better - but probably only by a few bytes. Rendering performance shouldn't really differ - any smart renderer is going to use the proper primitives such that the graphics card can render individual segments in parallel.

You can certainly find bad parsers and renderers, so really the question for you is going to come down to a few components:

  1. Do you have control over what parser/renderer your customers use?
  2. Is that faster with long or short paths?

If you can't control what your clients are using then you're going to have to build a set of test data and test on every common permutation regardless of what we say here.

Upvotes: 2

Related Questions