Skip to content

Commit 1e10d59

Browse files
committed
performance monitor
1 parent bc7ac46 commit 1e10d59

1 file changed

Lines changed: 138 additions & 26 deletions

File tree

pecan/Frontend/pecan-live-dashboard/src/pages/Dashboard.tsx

Lines changed: 138 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect } from "react";
1+
import { useState, useEffect, useRef } from "react";
22
import DataCard from "../components/DataCard";
33
import { createCanProcessor } from "../utils/canProcessor";
44

@@ -10,6 +10,18 @@ function Dashboard() {
1010
rawData: string;
1111
} }>({});
1212
const [processor, setProcessor] = useState<any>(null);
13+
const [performanceStats, setPerformanceStats] = useState({
14+
messagesPerSecond: 0,
15+
avgProcessingTime: 0,
16+
memoryUsage: 'N/A' as string | number,
17+
fps: 0
18+
});
19+
20+
const messageCountRef = useRef(0);
21+
const processingTimesRef = useRef<number[]>([]);
22+
const lastSecondRef = useRef(Date.now());
23+
const frameCountRef = useRef(0);
24+
const lastFpsUpdateRef = useRef(Date.now());
1325

1426
useEffect(() => {
1527
// Initialize CAN processor
@@ -36,6 +48,52 @@ function Dashboard() {
3648
});
3749
}, []);
3850

51+
// Performance monitoring
52+
useEffect(() => {
53+
// FPS monitoring
54+
const updateFPS = () => {
55+
frameCountRef.current++;
56+
const now = Date.now();
57+
if (now - lastFpsUpdateRef.current >= 1000) {
58+
const fps = Math.round((frameCountRef.current * 1000) / (now - lastFpsUpdateRef.current));
59+
setPerformanceStats(prev => ({ ...prev, fps }));
60+
61+
if (fps < 30) {
62+
console.warn(`Low FPS: ${fps}`);
63+
}
64+
65+
frameCountRef.current = 0;
66+
lastFpsUpdateRef.current = now;
67+
}
68+
requestAnimationFrame(updateFPS);
69+
};
70+
requestAnimationFrame(updateFPS);
71+
72+
// Memory monitoring
73+
const updateMemory = () => {
74+
if ('memory' in performance) {
75+
const memInfo = (performance as any).memory;
76+
const memoryMB = Math.round(memInfo.usedJSHeapSize / 1024 / 1024);
77+
console.log('Memory info:', memInfo, 'Memory MB:', memoryMB);
78+
setPerformanceStats(prev => ({
79+
...prev,
80+
memoryUsage: memoryMB
81+
}));
82+
83+
if (memoryMB > 100) {
84+
console.warn(`High memory usage: ${memoryMB}MB`);
85+
}
86+
} else {
87+
console.log('Performance.memory API not available');
88+
}
89+
};
90+
const memoryInterval = setInterval(updateMemory, 2000);
91+
92+
return () => {
93+
clearInterval(memoryInterval);
94+
};
95+
}, []);
96+
3997
// WebSocket connection for real-time CAN data
4098
useEffect(() => {
4199
if (!processor) return;
@@ -47,6 +105,8 @@ function Dashboard() {
47105
};
48106

49107
ws.onmessage = (event) => {
108+
const startTime = performance.now();
109+
50110
try {
51111
console.log('Received WebSocket message:', event.data);
52112

@@ -91,6 +151,46 @@ function Dashboard() {
91151
...updates
92152
}));
93153
}
154+
155+
// Performance tracking
156+
const processingTime = performance.now() - startTime;
157+
processingTimesRef.current.push(processingTime);
158+
159+
// Keep only last 100 processing times
160+
if (processingTimesRef.current.length > 100) {
161+
processingTimesRef.current = processingTimesRef.current.slice(-100);
162+
}
163+
164+
// Count actual CAN messages decoded
165+
const canMessageCount = messagesToProcess.filter(msg => msg && msg.signals).length;
166+
messageCountRef.current += canMessageCount;
167+
168+
// Update stats every second
169+
const now = Date.now();
170+
if (now - lastSecondRef.current >= 1000) {
171+
const messagesPerSecond = messageCountRef.current;
172+
const avgProcessingTime = processingTimesRef.current.length > 0
173+
? processingTimesRef.current.reduce((a, b) => a + b, 0) / processingTimesRef.current.length
174+
: 0;
175+
176+
setPerformanceStats(prev => ({
177+
...prev,
178+
messagesPerSecond,
179+
avgProcessingTime: Math.round(avgProcessingTime * 100) / 100
180+
}));
181+
182+
// Performance warnings
183+
if (messagesPerSecond > 100) {
184+
console.warn(`High CAN message rate: ${messagesPerSecond} messages/sec`);
185+
}
186+
if (avgProcessingTime > 10) {
187+
console.warn(`Slow processing: ${avgProcessingTime}ms average`);
188+
}
189+
190+
messageCountRef.current = 0;
191+
lastSecondRef.current = now;
192+
}
193+
94194
} catch (error) {
95195
console.error('Error processing WebSocket message:', error);
96196
}
@@ -110,32 +210,44 @@ function Dashboard() {
110210
}, [processor]);
111211

112212
return (
113-
<div className="flex flex-wrap">
114-
{Object.entries(canMessages).map(([canId, message]) => {
115-
const data = Object.entries(message.signals).map(([key, value]) => ({
116-
[key]: `${value.sensorReading} ${value.unit}`
117-
}));
213+
<div className="flex flex-col min-h-screen">
214+
<div className="flex flex-wrap flex-1">
215+
{Object.entries(canMessages).map(([canId, message]) => {
216+
const data = Object.entries(message.signals).map(([key, value]) => ({
217+
[key]: `${value.sensorReading} ${value.unit}`
218+
}));
219+
220+
return (
221+
<DataCard
222+
key={canId}
223+
msgID={canId}
224+
messageName={message.messageName}
225+
data={data.length > 0 ? data : [{ "No Data": "Waiting for messages..." }]}
226+
lastUpdated={message.lastUpdated}
227+
rawData={message.rawData}
228+
/>
229+
);
230+
})}
231+
232+
{/* Static card for comparison */}
233+
<DataCard
234+
msgID="1006"
235+
messageName="TORCH_M1_V1"
236+
category="BMS/TORCH"
237+
lastUpdated={Date.now()}
238+
rawData="00 01 02 03 04 05 06 07"
239+
/>
240+
</div>
118241

119-
return (
120-
<DataCard
121-
key={canId}
122-
msgID={canId}
123-
messageName={message.messageName}
124-
data={data.length > 0 ? data : [{ "No Data": "Waiting for messages..." }]}
125-
lastUpdated={message.lastUpdated}
126-
rawData={message.rawData}
127-
/>
128-
);
129-
})}
130-
131-
{/* Static card for comparison */}
132-
<DataCard
133-
msgID="1006"
134-
messageName="TORCH_M1_V1"
135-
category="BMS/TORCH"
136-
lastUpdated={Date.now()}
137-
rawData="00 01 02 03 04 05 06 07"
138-
/>
242+
{/* Performance Stats - low key at bottom */}
243+
<div className="w-full py-2 px-4 bg-gray-700 text-gray-300 text-xs border-t border-gray-600">
244+
<div className="flex justify-between items-center max-w-6xl mx-auto">
245+
<span>FPS: {performanceStats.fps}</span>
246+
<span>CAN frames/sec: {performanceStats.messagesPerSecond}</span>
247+
<span>Avg: {performanceStats.avgProcessingTime}ms</span>
248+
<span>Mem: {performanceStats.memoryUsage}{typeof performanceStats.memoryUsage === 'number' ? 'MB' : ''}</span>
249+
</div>
250+
</div>
139251
</div>
140252
);
141253
}

0 commit comments

Comments
 (0)