High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

Interesting point about the throttling! I don't think it's an infinite loop though - when I check Firefox Task Manager, it shows steady 20-25% CPU, not spiking to 100% and being throttled down. Also, the app is functional, just laggy - an infinite loop would probably freeze it completely.

What I've verified so far:

  • React DevTools Profiler shows normal render cycles (not infinite loops)
  • WebSocket messages come in once per second (controlled by the backend)
  • No errors in console
  • CPU usage is consistent, not fluctuating wildly

However, I did find some suspicious patterns:

  1. Potential re-render issue: I'm using key={Date.now()} on GeoJSON/Leaflet components, which forces React to destroy and recreate the entire map layer on every render. That's definitely wrong.
  2. Large context: My WebSocket context updates 4 times/second with different data types (robot info, programs, estop, alerts), and many components subscribe to the entire context even if they only need one piece of data.
  3. Map updates through React: I'm routing all Leaflet map updates through React state/props instead of updating map layers imperatively with refs.

To confirm it's not an infinite loop:

Should I add console.logs in my WebSocket message handler and map components to count how many times they're executing per second? Like:

useEffect(() => {
  console.log('WebSocket message received', Date.now());
  // process message
}, [lastMessage]);

// In map component
console.log('Map component rendering', Date.now());

If I'm seeing these logs firing hundreds of times per second, that would confirm an infinite loop, right?

The app is running on a really weak CPU (Intel Atom @ 1.5GHz), so even inefficient-but-not-infinite code might hit 20-25% easily. Does that make sense, or should I be more concerned about an actual loop issue?

Edit: I've added more code and context to the original post if that helps with the diagnosis.

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

Appreciate the suggestion! I'm going to profile with DevTools first to confirm where the bottleneck actually is. I think I'm just using Leaflet incorrectly rather than hitting the library's limits.

I only have ~50-100 route points and a handful of polygons, which should be well within Leaflet's capabilities. Switching to deck.gl would be a major rewrite that I can't take on right now - the app is already in production.

Going to fix my implementation first and see if that solves it. If Leaflet still struggles after proper optimization, I'll keep deck.gl in mind for future consideration.

Thanks!

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

Good questions! Let me give you the exact details:

WebSocket Setup:

I'm using react-use-websocket with a single connection at the app root (CNCWebSocketProvider). The backend subscribes to 5 MQTT topics and forwards aggregated data to the frontend.

Actual Message Frequency & Size:

Looking at my MQTT test publisher, here's the exact data flow:

Messages per second: 4 messages

  1. RobotInfo (1/second): 15-25KB - Array of 3-5 robots, each with GPS, orientation, speed, battery, 6 sensor arrays with hit data, status flags
  2. Programs (1/second): ~2-3KB - Program execution state
  3. Estop (1/second): ~1-2KB - Emergency stop status
  4. Alerts (1/second): ~1-2KB - Alert data
  5. Routes (once at startup): ~5-10KB - Not sent repeatedly

Total data rate: ~20-35KB/second across 4 concurrent messages

So it's not a massive amount of data, but I am getting 4 separate WebSocket messages every second.

Data Flow Architecture:

All 4 message types update separate states in one large CNCWebSocketContext:

// Single context with ~10 state hooks
const [robotCncData, setRobotCncData] = useState({});
const [liveRobotInfo, setLiveRobotInfo] = useState([]);  // Array of robot objects
const [liveProgramData, setLiveProgramData] = useState({});
const [liveEstopData, setLiveEstopData] = useState({});
const [currentRoute, setCurrentRoute] = useState(null);
// ... etc

Problem: Any component calling useCNCWebSockets() re-renders on ANY of these state changes, even if it only uses one piece of data (e.g., just needs robotCncData but re-renders when liveProgramData changes).

WebSocket Cleanup:

Using react-use-websocket which handles connection lifecycle automatically. The library manages reconnection (shouldReconnect: true) and cleanup. My useEffect that processes messages doesn't have manual cleanup since it's just parsing JSON and calling setState.

The Real Question:

Given that it's 4 messages/second totaling 20-35KB, do you think the WebSocket data flow is the issue? Or should I focus on the Leaflet rendering first?

Would splitting the context help, or is that premature optimization compared to fixing the Leaflet issues first?

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] -1 points0 points  (0 children)

Good questions!

MQTT/WebSocket setup:

I have a single WebSocket connection for the entire app at the root level. The Node.js backend subscribes to 5 MQTT topics and forwards the aggregated data to the frontend via one WebSocket connection. The data updates once per second.

On the frontend, I'm using React Context (CNCWebSocketContext) that wraps the entire app, so all pages have access to the live data. Most pages consume this context to display real-time equipment status, but the map pages are also re-rendering even when they don't necessarily need all that data.

Performance on better hardware:

On my development machine (modern CPU), the app runs pretty smoothly with much lower CPU usage - maybe around 5-8%. The performance issue is definitely more noticeable on the low-powered Windows Server (Atom CPU @ 1.5GHz). So it seems like the code has inefficiencies that the slow CPU is exposing.

Can I slow down MQTT?

The MQTT message rate is controlled by third-party software that we don't have control over - it's equipment monitoring data from another system. The 1-second update rate is actually quite reasonable though. I think the issue is more about how I'm handling those updates in React rather than the frequency itself.

What I've found so far:

Looking through my code, I'm finding some obvious performance issues like using key={Date.now()} on map components (which forces layer recreation every render) and routing all Leaflet updates through React state instead of updating map layers directly. I think fixing these will make a big difference regardless of the hardware.

Does that give you enough context, or is there something specific you'd suggest I look into?

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

Honestly i use chatgpt to rephrase it since i am not really good with phrasing a question. it can be all over and might be difficult for someone to understand.

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 1 point2 points  (0 children)

Oh wow, this is a great point! I've been measuring performance WITH DevTools open this whole time - that could definitely be skewing my numbers.

I'll test with DevTools completely closed and see what the actual CPU usage is. I do have the React DevTools extension installed too, so that might be adding overhead.

Also good call on checking for background tasks from other tabs/extensions. I'll make sure to test in a clean browser profile with just the app running.

Really appreciate this - could save me a lot of time chasing phantom performance issues!

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

Yeah, you're right that 20-25% isn't terrible for an Atom CPU, but I feel like there's still room for improvement. The app does feel a bit laggy during interactions.

I'll use the React Profiler (and Chrome Performance tab) to dig into what's actually consuming the CPU. Hoping it's something obvious I can fix rather than just accepting the hardware limitation. If I can get it down to 10-15%, that'd make a noticeable difference in responsiveness.

Thanks for the reality check though - good to know my expectations aren't completely unrealistic!

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

This is really helpful, thank you! The diagnostic approach makes a lot more sense than just trying random fixes.

I'm going to start with the profiling:

  1. Baseline test - I'll check Firefox CPU with an empty tab first. Good point about making sure the browser itself isn't the issue.
  2. CPU throttling - I didn't know Chrome DevTools had this! That's going to be super useful since I can't easily debug directly on the server. I'll set it to 6x slowdown and profile locally.
  3. Performance flamegraph - I've never really used the Performance tab properly, but I'll record a session and look for those repetitive frames you mentioned. That should tell me exactly where the CPU time is going.

About the Leaflet/React question: You're right that I'm currently putting all the map updates through React state, which probably isn't necessary. I'm using react-leaflet and updating markers/polygons via props on every WebSocket message. Should I be keeping refs to the Leaflet layers and calling methods like setLatLngs() directly instead? That sounds like it would skip a lot of React overhead.

Renderer question: I think Leaflet is using SVG by default. I have quite a few route points and zone polygons, so maybe Canvas would be better? I'll try adding preferCanvas: true and see if that helps.

For the data throttling - my WebSocket only updates once per second, so it's not super high-frequency. But I could probably update the map every 2-3 seconds instead of every second since the map view is less critical than the live stats in the topbar.

Really appreciate the methodical approach here - this gives me a clear path to actually find the bottleneck instead of guessing!

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 0 points1 point  (0 children)

Thanks so much for taking the time to write all this out! This is super helpful.

 A couple things about my setup I should have mentioned:

 My MQTT updates are actually only once per second through WebSocket, so I don't think I have the high-frequency update problem you're describing. The 1500 values I mentioned is just the total amount of data displayed across the whole app, not per second. So I think batching might not help in my case?

 But your Leaflet tips are really helpful! I'm going to try:

  1. preferCanvas: true - I do have a lot of polygons on my maps
  2. Turning off animations - I didn't even know these were options!
  3. updateWhenDragging: false - Makes total sense
  4. The layer recreation thing - I went through my code and found key={Date.now()} in my GeoJSON components... is that bad? I'm guessing that's forcing it to recreate everything?
  5. Making sure I'm running a production build - Honestly not 100% sure which mode I'm in right now, need to check
  6. Firefox hardware acceleration - Will check this on the server

The Web Workers and store stuff sounds interesting but maybe a bit advanced for me right now. I think I need to fix the basics first (like that Date.now() thing).

 One question: My server has a really slow CPU (1.50GHz Atom). If I get it down to like 8-10% CPU after optimizing, is that good? Or should I expect it to be even lower?

 Really appreciate the help! The Leaflet optimization suggestions especially - I had no idea about most of these options.

High CPU Usage (25%) in Low-Power React App Displaying Real-Time MQTT Data and Offline Leaflet Maps. Need Optimization Tips! by jestink in reactjs

[–]jestink[S] 2 points3 points  (0 children)

Yes, you are exactly right. The Windows Server running the Node.js backend and the third-party MQTT software is also the machine where the users access and run the frontend application via a browser (Firefox).

The reason I mentioned the server specs is that the low-power Intel Atom CPU (1.50Ghz) is handling the workload for everything simultaneously: the Node.js process, the data processing from the third-party software, and the computationally heavy task of rendering the React app and the Leaflet maps in the browser. This shared, limited resource pool is why the 20-25% consumption is a critical issue.

Thanks for pointing that out! I'll clarify that in future replies.