antvis / util

utility library for AntV products.
MIT License
74 stars 27 forks source link

fix: fix the way to get the tmp element (#115) #116

Closed nekocode closed 3 months ago

nekocode commented 4 months ago

从 dom 树中尝试获取之前生成的临时元素,避免元素被第三方卸载后报错

hustcc commented 4 months ago

另外一个点,很重要,torbg 这个方法在上层库中是一个高频操作,之前直接缓存到变量上,性能是最优的,如果每次都去 select 查询一下,性能会有大幅下降,可以使用工具测试一下时间。

如果下降幅度很大,建议看看有没有其他方式去解决。比如在出现异常的地方,catch 一下,然后再去创建。

nekocode commented 4 months ago

@hustcc 你看看这个可以接受不?1270 个元素,使用 getElementById 查询 100 万次耗时 23ms 左右。但是我的机器是 Apple M1 Max 32GB 的,可能耗时会少一些。 image

你说的 catch 的方式性能肯定更好一些,你看下你们比较倾向哪种方式呢?

hustcc commented 4 months ago

@hustcc 你看看这个可以接受不?1270 个元素,使用 getElementById 查询 100 万次耗时 23ms 左右。但是我的机器是 Apple M1 Max 32GB 的,可能耗时会少一些。

image

你说的 catch 的方式性能肯定更好一些,你看下你们比较倾向哪种方式呢?

要对比,这么做之后,和没这么做之前的性能。

nekocode commented 4 months ago

要对比,这么做之后,和没这么做之前的性能。

@hustcc 你可以在浏览器 console 上分别用下面这两段代码测试下:

原方式:

function toHex(value) {
  const x16Value = Math.round(value).toString(16);
  return x16Value.length === 1 ? `0${x16Value}` : x16Value;
}

function arr2rgb(arr) {
  return `#${toHex(arr[0])}${toHex(arr[1])}${toHex(arr[2])}`;
}

const RGB_REG = /rgba?\(([\s.,0-9]+)\)/;

function createTmp() {
  const i = document.createElement('i');
  i.title = 'Web Colour Picker';
  i.style.display = 'none';
  document.body.appendChild(i);
  return i;
}

let iEl;

function toRGBString(color) {
  if (color[0] === '#' && color.length === 7) {
    return color;
  }
  if (!iEl) {
    iEl = createTmp();
  }

  iEl.style.color = color;
  let rst = document.defaultView.getComputedStyle(iEl, '').getPropertyValue('color');
  const matches = RGB_REG.exec(rst);
  const cArray = matches[1].split(/\s*,\s*/).map((s) => Number(s));
  rst = arr2rgb(cArray);
  return rst;
}

test = "global variable"
console.time(test);
for (let i = 0; i < 100_0000; i++) toRGBString("black");
console.timeEnd(test);

改成使用 getElementById:

function toHex(value) {
  const x16Value = Math.round(value).toString(16);
  return x16Value.length === 1 ? `0${x16Value}` : x16Value;
}

function arr2rgb(arr) {
  return `#${toHex(arr[0])}${toHex(arr[1])}${toHex(arr[2])}`;
}

const RGB_REG = /rgba?\(([\s.,0-9]+)\)/;

function getTmp() {
  let i = document.getElementById('antv-web-colour-picker');
  if (i) return i;
  i = document.createElement('i');
  i.id = 'antv-web-colour-picker';
  i.title = 'Web Colour Picker';
  i.style.display = 'none';
  document.body.appendChild(i);
  return i;
}

function toRGBString(color) {
  if (color[0] === '#' && color.length === 7) {
    return color;
  }
  const iEl = getTmp();
  iEl.style.color = color;
  let rst = document.defaultView.getComputedStyle(iEl, '').getPropertyValue('color');
  const matches = RGB_REG.exec(rst);
  const cArray = matches[1].split(/\s*,\s*/).map((s) => Number(s));
  rst = arr2rgb(cArray);
  return rst;
}

test = "getElementById"
console.time(test);
for (let i = 0; i < 100_0000; i++) toRGBString("black");
console.timeEnd(test);

测试结果:

在我本地的测试结果是:

global variable: 1034.404052734375 ms
getElementById: 1033.176025390625 ms

耗时几乎一样。而且我看导出的函数还有用 memoize 做缓存优化,感觉对性能应该没太大的影响?

hustcc commented 4 months ago

那没问题了~ 👍🏻

hustcc commented 4 months ago

单侧报错了,帮忙把 https://github.com/antvis/util/blob/master/.github/workflows/build.yml#L15 改成 16 或者 18 试试看。

nekocode commented 4 months ago

单侧报错了,帮忙把 https://github.com/antvis/util/blob/master/.github/workflows/build.yml#L15 改成 16 或者 18 试试看。

已改成 16 了

hustcc commented 3 months ago

image

好像还是报错,看看这个。这个 PR 弄了好久了,好事多磨~~

nekocode commented 3 months ago

@hustcc 嗯,已改。刚在 fork 的仓库上跑了遍,现在应该能通过了: image

hustcc commented 3 months ago

已经合并,如果有兴趣,欢迎加入群聊。

image

hustcc commented 3 months ago