Skip to content

Commit a6e9bb6

Browse files
committed
CR Updates
1 parent 68d4949 commit a6e9bb6

File tree

3 files changed

+36
-82
lines changed

3 files changed

+36
-82
lines changed

src/components/MemoryFooter.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class MemoryFooter extends React.Component<MemoryFooterProps, MemoryFooterState>
2121
private lastWarningLevel: 'none' | 'high' | 'critical' = 'none'
2222
private lastCriticalWarningTime: number = 0
2323
private readonly criticalWarningThrottleMs: number = 30000
24+
private didStartMonitoring: boolean = false
2425

2526
constructor (props: MemoryFooterProps) {
2627
super(props)
@@ -64,13 +65,17 @@ class MemoryFooter extends React.Component<MemoryFooterProps, MemoryFooterState>
6465
})
6566

6667
memoryMonitor.startMonitoring()
68+
this.didStartMonitoring = true
6769
}
6870

6971
componentWillUnmount (): void {
7072
if (this.unsubscribeMemory != null) {
7173
this.unsubscribeMemory()
7274
}
73-
memoryMonitor.stopMonitoring()
75+
if (this.didStartMonitoring) {
76+
memoryMonitor.stopMonitoring()
77+
this.didStartMonitoring = false
78+
}
7479
}
7580

7681
render (): React.ReactNode {

src/components/SlideViewer.tsx

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -298,71 +298,6 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
298298
return palette
299299
}
300300

301-
shouldComponentUpdate (
302-
nextProps: SlideViewerProps,
303-
nextState: SlideViewerState
304-
): boolean {
305-
// Only re-render if relevant props or state changed
306-
// Skip re-render for frequent state updates that don't affect UI
307-
if (
308-
this.props.location.pathname !== nextProps.location.pathname ||
309-
this.props.studyInstanceUID !== nextProps.studyInstanceUID ||
310-
this.props.seriesInstanceUID !== nextProps.seriesInstanceUID ||
311-
this.props.slide !== nextProps.slide ||
312-
this.props.clients !== nextProps.clients ||
313-
this.state.isLoading !== nextState.isLoading ||
314-
this.state.isAnnotationModalVisible !== nextState.isAnnotationModalVisible ||
315-
this.state.isSelectedRoiModalVisible !== nextState.isSelectedRoiModalVisible ||
316-
this.state.isReportModalVisible !== nextState.isReportModalVisible ||
317-
this.state.isGoToModalVisible !== nextState.isGoToModalVisible ||
318-
this.state.isHoveredRoiTooltipVisible !== nextState.isHoveredRoiTooltipVisible ||
319-
this.state.hoveredRoiAttributes !== nextState.hoveredRoiAttributes ||
320-
this.state.visibleRoiUIDs !== nextState.visibleRoiUIDs ||
321-
this.state.visibleSegmentUIDs !== nextState.visibleSegmentUIDs ||
322-
this.state.visibleMappingUIDs !== nextState.visibleMappingUIDs ||
323-
this.state.visibleAnnotationGroupUIDs !== nextState.visibleAnnotationGroupUIDs ||
324-
this.state.selectedRoiUIDs !== nextState.selectedRoiUIDs ||
325-
this.state.selectedEvaluations !== nextState.selectedEvaluations ||
326-
this.state.selectedRoi !== nextState.selectedRoi ||
327-
this.state.selectedFinding !== nextState.selectedFinding ||
328-
this.state.selectedGeometryType !== nextState.selectedGeometryType ||
329-
this.state.selectedMarkup !== nextState.selectedMarkup ||
330-
this.state.selectedPresentationStateUID !== nextState.selectedPresentationStateUID ||
331-
this.state.areRoisHidden !== nextState.areRoisHidden ||
332-
this.state.isICCProfilesEnabled !== nextState.isICCProfilesEnabled ||
333-
this.state.isSegmentationInterpolationEnabled !== nextState.isSegmentationInterpolationEnabled ||
334-
this.state.isParametricMapInterpolationEnabled !== nextState.isParametricMapInterpolationEnabled ||
335-
this.state.isClusteringEnabled !== nextState.isClusteringEnabled ||
336-
this.state.clusteringPixelSizeThreshold !== nextState.clusteringPixelSizeThreshold ||
337-
this.state.isRoiDrawingActive !== nextState.isRoiDrawingActive ||
338-
this.state.isRoiModificationActive !== nextState.isRoiModificationActive ||
339-
this.state.isRoiTranslationActive !== nextState.isRoiTranslationActive ||
340-
this.state.hoveredRoiTooltipX !== nextState.hoveredRoiTooltipX ||
341-
this.state.hoveredRoiTooltipY !== nextState.hoveredRoiTooltipY ||
342-
this.state.selectedXCoordinate !== nextState.selectedXCoordinate ||
343-
this.state.selectedYCoordinate !== nextState.selectedYCoordinate ||
344-
this.state.selectedMagnification !== nextState.selectedMagnification ||
345-
this.state.isSelectedXCoordinateValid !== nextState.isSelectedXCoordinateValid ||
346-
this.state.isSelectedYCoordinateValid !== nextState.isSelectedYCoordinateValid ||
347-
this.state.isSelectedMagnificationValid !== nextState.isSelectedMagnificationValid ||
348-
this.state.validXCoordinateRange !== nextState.validXCoordinateRange ||
349-
this.state.validYCoordinateRange !== nextState.validYCoordinateRange ||
350-
this.state.presentationStates !== nextState.presentationStates ||
351-
this.state.visibleOpticalPathIdentifiers !== nextState.visibleOpticalPathIdentifiers ||
352-
this.state.activeOpticalPathIdentifiers !== nextState.activeOpticalPathIdentifiers ||
353-
this.state.selectedSeriesInstanceUID !== nextState.selectedSeriesInstanceUID ||
354-
this.state.selectedSegmentationSeriesInstanceUID !== nextState.selectedSegmentationSeriesInstanceUID ||
355-
this.state.customizedSegmentColors !== nextState.customizedSegmentColors ||
356-
this.state.generatedReport !== nextState.generatedReport
357-
) {
358-
return true
359-
}
360-
361-
// Don't re-render for loadingFrames changes (too frequent)
362-
// Don't re-render for pixelDataStatistics changes (computed, not directly displayed)
363-
return false
364-
}
365-
366301
componentDidUpdate (
367302
previousProps: SlideViewerProps,
368303
previousState: SlideViewerState

src/services/MemoryMonitor.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ type MemoryUpdateCallback = (memory: MemoryInfo) => void
8484
*/
8585
class MemoryMonitor {
8686
private readonly updateCallbacks: Set<MemoryUpdateCallback> = new Set()
87-
private monitoringInterval: ReturnType<typeof setInterval> | null = null
88-
private readonly updateInterval: number = 5000 // 5 seconds
87+
private monitoringTimeoutId: ReturnType<typeof setTimeout> | null = null
88+
private monitoringActive: boolean = false
89+
private readonly updateInterval: number = 5000
8990
private lastMeasurement: MemoryInfo | null = null
9091
private readonly highUsageThreshold = 0.80 // 80%
9192
private readonly criticalUsageThreshold = 0.90 // 90%
@@ -270,39 +271,52 @@ class MemoryMonitor {
270271
}
271272

272273
/**
273-
* Start periodic memory monitoring
274+
* Start periodic memory monitoring. Serializes runs so the next tick is scheduled
275+
* only after the current measure() finishes, avoiding overlapping executions.
274276
*/
275277
startMonitoring (interval: number = this.updateInterval): void {
276-
if (this.monitoringInterval !== null) {
278+
if (this.monitoringTimeoutId != null) {
277279
this.stopMonitoring()
278280
}
281+
this.monitoringActive = true
282+
283+
const scheduleNext = (): void => {
284+
if (!this.monitoringActive) return
285+
this.monitoringTimeoutId = setTimeout(() => {
286+
this.monitoringTimeoutId = null
287+
this.measure()
288+
.then(() => { scheduleNext() })
289+
.catch(error => {
290+
console.error('Error in periodic memory measurement:', error)
291+
scheduleNext()
292+
})
293+
}, interval)
294+
}
279295

280-
this.measure().catch(error => {
281-
console.error('Error in initial memory measurement:', error)
282-
})
283-
284-
this.monitoringInterval = setInterval(() => {
285-
this.measure().catch(error => {
286-
console.error('Error in periodic memory measurement:', error)
296+
this.measure()
297+
.then(() => { scheduleNext() })
298+
.catch(error => {
299+
console.error('Error in initial memory measurement:', error)
300+
scheduleNext()
287301
})
288-
}, interval)
289302
}
290303

291304
/**
292305
* Stop periodic memory monitoring
293306
*/
294307
stopMonitoring (): void {
295-
if (this.monitoringInterval !== null) {
296-
clearInterval(this.monitoringInterval)
297-
this.monitoringInterval = null
308+
this.monitoringActive = false
309+
if (this.monitoringTimeoutId != null) {
310+
clearTimeout(this.monitoringTimeoutId)
311+
this.monitoringTimeoutId = null
298312
}
299313
}
300314

301315
/**
302316
* Check if monitoring is active
303317
*/
304318
isMonitoring (): boolean {
305-
return this.monitoringInterval !== null
319+
return this.monitoringActive
306320
}
307321

308322
/**

0 commit comments

Comments
 (0)