-
Notifications
You must be signed in to change notification settings - Fork 601
Open
Labels
QuestionFurther information is requestedFurther information is requested
Description
🐛 使用Line图表,以120hz频率更新图表数据,EE事件积压.
G2 的Annotation组件调用 update 方法时,调用onAfterRender方法,会调用ee.once方法,但是好像因为更新频率过快,事件没有触发,造成事件积压,内存上升.
以下代码可以复现:
// #hook.ts
import { ref, onUnmounted } from 'vue';
import { Line } from '@antv/g2plot';
console.dir(Line.__proto__.prototype.__proto__);
Line.__proto__.prototype.__proto__.on = function (evt, callback, once) {
// if (evt === 'afterrender') {
// return;
// }
if (!this._events[evt]) {
this._events[evt] = [];
}
this._events[evt].push({
callback,
once: !!once
});
if (evt === 'afterrender') {
if (this._events[evt].length % 1000 == 0) {
console.log(this._events, this);
}
}
return this;
};
// -------------------------
const MAX_DATA_POINTS = 120;
const RENDER_FPS = 30;
const RENDER_INTERVAL = 1000 / RENDER_FPS;
const useWatchChart = (options) => {
const chartContainerRef = ref(null);
let chart = null;
let isMounted = false;
let animationFrameId = null;
let dataBuffer = [];
let pendingDataQueue = [];
// 模拟数据生成器
let mockDataIndex = 0;
function mountChart() {
if (!chartContainerRef.value) return;
isMounted = true;
chart = new Line(chartContainerRef.value, {
data: dataBuffer,
xField: 'index',
yField: 'value',
seriesField: 'type',
color: ['green'],
animation: false,
smooth: false,
tooltip: false,
xAxis: {
min: 0,
max: MAX_DATA_POINTS,
tickCount: 7
},
yAxis: {
min: -0.01,
max: 1
}
});
console.log(chart);
chart.render();
startRenderLoop();
}
function unmountChart() {
isMounted = false;
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
if (chart) {
chart.destroy();
chart = null;
}
dataBuffer = [];
pendingDataQueue = [];
console.log('Chart unmounted');
}
// 模拟Socket数据接收
function updateDataBuffer() {
if (!isMounted) return;
// 生成模拟数据
const mockData = {
value1: { value: Math.random() },
value2: { value: Math.random() }
};
// 模拟多字段数据推送
['value1', 'value2'].forEach((key) => {
pendingDataQueue.push({
type: key,
value: mockData[key].value,
index: 0
});
});
// // 每处理1000个数据点记录一次
// if (mockDataIndex % 1000 === 0) {
// if (chart) {
// chart.logEvent();
// }
// }
mockDataIndex++;
}
let lastRenderTime = 0;
const renderLoop = (currentTime) => {
if (!isMounted) return;
animationFrameId = requestAnimationFrame(renderLoop);
// 限制帧率
if (currentTime - lastRenderTime < RENDER_INTERVAL) return;
if (pendingDataQueue.length === 0) return;
lastRenderTime = currentTime;
// 消费队列
for (let i = 0; i < pendingDataQueue.length; i++) {
dataBuffer.push(pendingDataQueue[i]);
}
pendingDataQueue.length = 0;
// 限制缓冲区大小
const maxTotalItems = MAX_DATA_POINTS * 2; // 2个字段
if (dataBuffer.length > maxTotalItems) {
const overflow = dataBuffer.length - maxTotalItems;
const deleteCount = Math.ceil(overflow / 2) * 2;
dataBuffer.splice(0, deleteCount);
}
// 更新索引
for (let i = 0; i < dataBuffer.length; i++) {
dataBuffer[i].index = Math.floor(i / 2);
}
// 更新图表
if (chart) {
chart.changeData(dataBuffer);
}
};
function startRenderLoop() {
if (!animationFrameId) {
animationFrameId = requestAnimationFrame(renderLoop);
}
}
// 模拟高频数据推送
function startMockDataStream() {
console.log('Starting mock data stream...');
const intervalId = setInterval(() => {
if (isMounted) {
updateDataBuffer();
}
}, 1000 / 120); // 模拟120Hz数据
return () => {
clearInterval(intervalId);
console.log('Mock data stream stopped');
};
}
onUnmounted(() => {
unmountChart();
});
return {
chartContainerRef,
mountChart,
updateDataBuffer,
unmountChart,
startMockDataStream,
isMounted
};
};
export { useWatchChart };
// 在Vue组件中使用
import { useWatchChart } from './hooks';
const { mountChart, startMockDataStream, unmountChart, chartContainerRef } =
useWatchChart({});
let stopMockStream = null;
const remove = () => {
if (stopMockStream) stopMockStream();
unmountChart();
};
const start = () => {
mountChart();
// 开始模拟数据流
stopMockStream = startMockDataStream();
};
</script>
<template>
<div class="io-demo-page-wrapper">
<div class="io-demo-hero-wrapper">
<div
class="chartContainer"
ref="chartContainerRef"></div>
<el-button @click="remove">remove</el-button>
<el-button @click="start">start</el-button>
</div>
</div>
</template>
<style lang="scss">
.io-demo-page-wrapper {
height: 100%;
.chartContainer {
width: 600px;
height: 300px;
}
}
</style>
我不确定是什么问题,但是事件累计造成了内存上升,对于10个图表如上频率更新,持续较长时间,内存上升明显.
Metadata
Metadata
Assignees
Labels
QuestionFurther information is requestedFurther information is requested