openlayers icon indicating copy to clipboard operation
openlayers copied to clipboard

Style expression performance

Open bmcalees opened this issue 7 months ago • 4 comments

Describe the bug When adding more then 10-15k features to a layer, the layer flashes and becomes nearly impossible to navigate.

To Reproduce See sandbox here: https://codesandbox.io/p/sandbox/vector-layer-forked-yqm88r?file=%2Fmain.js

Clicking on the page will render 3k new points. Notice how after 3-5 clicks the display becomes unusable.

Expected behavior Ideally style expressions could support 100k+ features.

bmcalees avatar Dec 22 '23 22:12 bmcalees

Since that is a considerable number of features, have you tried to lazy load them? Load 1k, wait a few seconds and load another 1k

prosperva avatar Dec 22 '23 22:12 prosperva

In the example above, the performance issue that I see has to do with the number of Image elements being created (one per point feature). You can see similarly bad performance if you do something like this:

const vectorLayer = new VectorLayer({
  source: new VectorSource({}),
  style: () =>
    new Style({
      image: new CircleStyle({
        radius: 3,
        fill: new Fill({color: '#e4f22'}),
        stroke: new Stroke({color: '#e4f22', width: 2}),
      }),
    }),
});

(And then try to render many thousands of point features.)

With style functions, you can write more optimal code by creating the shared image objects once. There is not currently a way to do the same with style expressions.

@MoonE has put up #15169 to use a shared cache for regular shape symbolizers (like circles). When I run the above example with the branch from #15169, the performance is significantly better.

tschaub avatar Jan 02 '24 01:01 tschaub

i have same issue when i add vector source with lot of features, example here

fabienwnklr avatar Jan 02 '24 08:01 fabienwnklr

In the example above, the performance issue that I see has to do with the number of Image elements being created (one per point feature). You can see similarly bad performance if you do something like this:

const vectorLayer = new VectorLayer({
  source: new VectorSource({}),
  style: () =>
    new Style({
      image: new CircleStyle({
        radius: 3,
        fill: new Fill({color: '#e4f22'}),
        stroke: new Stroke({color: '#e4f22', width: 2}),
      }),
    }),
});

(And then try to render many thousands of point features.)

With style functions, you can write more optimal code by creating the shared image objects once. There is not currently a way to do the same with style expressions.

@MoonE has put up #15169 to use a shared cache for regular shape symbolizers (like circles). When I run the above example with the branch from #15169, the performance is significantly better. I haven't looked closely at #15169 yet, but it may be that we want to create a more general image cache rather than just a regular shape cache (so we would get the same benefit when people use image urls in styles).

This is exactly the issue! Here's an example of how we utilize a cache for styles.

function createColorStyle(
  fillColor,
  strokeColor,
  strokeWidth,
  opacity = 0.5,
  radius = 1
) {
  const cachedStyle =
    createColorStyleCache[
      `${fillColor},${strokeColor},${strokeWidth},${opacity},${radius}`
    ];
  if (cachedStyle) return cachedStyle;

  let colorArray = [0, 0, 0, 0];
  let colorWithOpacity = [0, 0, 0, 0];
  if (fillColor) {
    colorArray = hexToRgb(fillColor);
    colorWithOpacity = colorArray.slice();
    colorWithOpacity[3] = opacity;
  }

  const fill = new Fill({ color: colorWithOpacity });

  const circleStyle = new Circle({
    radius: radius,
    fill: new Fill({ color: colorArray }),
    stroke: createStroke(strokeColor, strokeWidth, 1),
  });
  circleStyle.setOpacity(opacity);
  const style = new Style({
    fill,
    stroke: createStroke(strokeColor, strokeWidth, opacity),
    image: circleStyle,
  });
  createColorStyleCache[
    `${fillColor},${strokeColor},${strokeWidth},${opacity},${radius}`
  ] = style;
  return style;
}

bmcalees avatar Jan 02 '24 17:01 bmcalees