@@ -61,6 +61,31 @@ class GPUWorkload:
6161 PARENS = re .compile (r'(\(.*\))' )
6262 RESOLUTION = re .compile (r'\d+x\d+' )
6363 WHITESPACE = re .compile (r'\s\s+' )
64+ MEMO = dict ()
65+
66+ @classmethod
67+ def memoize (cls , string : str ) -> str :
68+ '''
69+ Get a memoized version of a string to reduce runtime memory use and
70+ improve rendering performance.
71+
72+ Args:
73+ string: User string to memoize.
74+
75+ Return:
76+ Memoized copy of a string.
77+ '''
78+ memo = GPUWorkload .MEMO
79+ if string not in memo :
80+ memo [string ] = string
81+ return memo [string ]
82+
83+ @classmethod
84+ def clear_memoize_cache (cls ) -> None :
85+ '''
86+ Clear the local memoization cache.
87+ '''
88+ GPUWorkload .MEMO .clear ()
6489
6590 def __init__ (
6691 self , event : RenderstageEvent , metadata : Optional [MetadataWork ]):
@@ -105,7 +130,8 @@ def get_label_name_full(self) -> Optional[str]:
105130 return None
106131
107132 if not LABEL_HEURISTICS :
108- self .parsed_label_name_full = self .label_stack [- 1 ]
133+ label = GPUWorkload .memoize (self .label_stack [- 1 ])
134+ self .parsed_label_name_full = label
109135 return self .parsed_label_name_full
110136
111137 # Create a copy we can edit ...
@@ -146,6 +172,7 @@ def get_label_name_full(self) -> Optional[str]:
146172 else :
147173 label = '.' .join (labels )
148174
175+ label = GPUWorkload .memoize (label )
149176 self .parsed_label_name_full = label
150177 return self .parsed_label_name_full
151178
@@ -181,6 +208,7 @@ def get_label_name(self) -> Optional[str]:
181208 postfix = label [- half_max :]
182209 label = f'{ prefix } ...{ postfix } '
183210
211+ label = GPUWorkload .memoize (label )
184212 self .parsed_label_name = label
185213 return self .parsed_label_name
186214
@@ -239,7 +267,8 @@ def get_long_label(self) -> str:
239267 '''
240268 # Subclass will override this if metadata exists
241269 # Submit ID isn't useful, but traces back to Perfetto data for debug
242- return f'Submit: { self .submit_id } '
270+ label = f'Submit: { self .submit_id } '
271+ return GPUWorkload .memoize (label )
243272
244273 def get_short_label (self ) -> str :
245274 '''
@@ -250,7 +279,8 @@ def get_short_label(self) -> str:
250279 '''
251280 # Subclass will override this if metadata exists
252281 # Submit ID isn't useful, but traces back to Perfetto data for debug
253- return f'Submit: { self .submit_id } '
282+ label = f'Submit: { self .submit_id } '
283+ return GPUWorkload .memoize (label )
254284
255285 def get_key_value_properties (self ) -> dict [str , str ]:
256286 '''
@@ -353,7 +383,10 @@ def get_resolution_str(self) -> str:
353383 Returns:
354384 Returns the label for use in the UI.
355385 '''
356- return f'{ self .width } x{ self .height } '
386+ label = f'{ self .width } x{ self .height } '
387+ label = self .memoize (label )
388+ return label
389+
357390
358391 def get_draw_count_str (self ) -> str :
359392 '''
@@ -368,7 +401,8 @@ def get_draw_count_str(self) -> str:
368401 if self .draw_call_count == 1 :
369402 return '1 draw'
370403
371- return f'{ self .draw_call_count } draws'
404+ label = f'{ self .draw_call_count } draws'
405+ return self .memoize (label )
372406
373407 def get_subpass_count_str (self ) -> str :
374408 '''
@@ -378,7 +412,8 @@ def get_subpass_count_str(self) -> str:
378412 Returns the label for use in the UI.
379413 '''
380414 es = '' if self .subpass_count == 1 else 'es'
381- return f'{ self .subpass_count } subpass{ es } '
415+ label = f'{ self .subpass_count } subpass{ es } '
416+ return self .memoize (label )
382417
383418 def get_attachment_present_str (self ) -> str :
384419 '''
@@ -388,7 +423,8 @@ def get_attachment_present_str(self) -> str:
388423 Returns the label for use in the UI.
389424 '''
390425 bindings = [x .binding for x in self .attachments ]
391- return self .get_compact_string (bindings )
426+ label = self .get_compact_str (bindings )
427+ return GPUWorkload .memoize (label )
392428
393429 def get_attachment_loadop_str (self ) -> str :
394430 '''
@@ -398,7 +434,8 @@ def get_attachment_loadop_str(self) -> str:
398434 Returns the label for use in the UI.
399435 '''
400436 bindings = [x .binding for x in self .attachments if x .is_loaded ]
401- return self .get_compact_string (bindings )
437+ label = self .get_compact_str (bindings )
438+ return GPUWorkload .memoize (label )
402439
403440 def get_attachment_storeop_str (self ) -> str :
404441 '''
@@ -408,10 +445,11 @@ def get_attachment_storeop_str(self) -> str:
408445 Returns the label for use in the UI.
409446 '''
410447 bindings = [x .binding for x in self .attachments if x .is_stored ]
411- return self .get_compact_string (bindings )
448+ label = self .get_compact_str (bindings )
449+ return GPUWorkload .memoize (label )
412450
413451 @classmethod
414- def get_compact_string (cls , bindings : list [str ]) -> str :
452+ def get_compact_str (cls , bindings : list [str ]) -> str :
415453 '''
416454 Get the compact UI string for a set of attachment bind points.
417455
@@ -422,7 +460,8 @@ def get_compact_string(cls, bindings: list[str]) -> str:
422460 A binding string of the form, e.g. "C0124DS".
423461 '''
424462 merge = '' .join (bindings )
425- return '' .join ([j for i , j in enumerate (merge ) if j not in merge [:i ]])
463+ label = '' .join ([j for i , j in enumerate (merge ) if j not in merge [:i ]])
464+ return GPUWorkload .memoize (label )
426465
427466 def get_attachment_long_label (self ) -> str :
428467 '''
@@ -441,7 +480,8 @@ def get_attachment_long_label(self) -> str:
441480 if stored :
442481 stored = f' > store({ stored } ) '
443482
444- return f'{ loaded } [{ present } ]{ stored } '
483+ label = f'{ loaded } [{ present } ]{ stored } '
484+ return GPUWorkload .memoize (label )
445485
446486 def get_attachment_short_label (self ) -> str :
447487 '''
@@ -451,7 +491,8 @@ def get_attachment_short_label(self) -> str:
451491 A string showing attachments without load/storeOp usage.
452492 '''
453493 present = self .get_attachment_present_str ()
454- return f'[{ present } ]'
494+ label = f'[{ present } ]'
495+ return GPUWorkload .memoize (label )
455496
456497 def get_long_label (self ) -> str :
457498 '''
@@ -471,7 +512,8 @@ def get_long_label(self) -> str:
471512 line = self .get_attachment_long_label ()
472513 lines .append (line )
473514
474- return '\n ' .join (lines )
515+ label = '\n ' .join (lines )
516+ return GPUWorkload .memoize (label )
475517
476518 def get_short_label (self ) -> str :
477519 '''
@@ -488,7 +530,8 @@ def get_short_label(self) -> str:
488530 line = self .get_attachment_short_label ()
489531 lines .append (line )
490532
491- return '\n ' .join (lines )
533+ label = '\n ' .join (lines )
534+ return GPUWorkload .memoize (label )
492535
493536
494537class GPUDispatch (GPUWorkload ):
@@ -547,7 +590,8 @@ def get_resolution_str(self) -> str:
547590 if self .groups_z > 1 :
548591 dims .append (self .groups_z )
549592
550- return f'{ "x" .join ([str (dim ) for dim in dims ])} groups'
593+ label = f'{ "x" .join ([str (dim ) for dim in dims ])} groups'
594+ return GPUWorkload .memoize (label )
551595
552596 def get_long_label (self ) -> str :
553597 '''
@@ -562,7 +606,8 @@ def get_long_label(self) -> str:
562606 lines .append (label_name )
563607
564608 lines .append (self .get_short_label ())
565- return '\n ' .join (lines )
609+ label = '\n ' .join (lines )
610+ return GPUWorkload .memoize (label )
566611
567612 def get_short_label (self ) -> str :
568613 '''
@@ -574,7 +619,8 @@ def get_short_label(self) -> str:
574619 lines = []
575620 line = self .get_resolution_str ()
576621 lines .append (line )
577- return '\n ' .join (lines )
622+ label = '\n ' .join (lines )
623+ return GPUWorkload .memoize (label )
578624
579625
580626class GPUTraceRays (GPUWorkload ):
@@ -633,7 +679,8 @@ def get_resolution_str(self) -> str:
633679 if self .items_z > 1 :
634680 dims .append (self .items_z )
635681
636- return f'{ "x" .join ([str (dim ) for dim in dims ])} items'
682+ label = f'{ "x" .join ([str (dim ) for dim in dims ])} items'
683+ return GPUWorkload .memoize (label )
637684
638685 def get_long_label (self ) -> str :
639686 '''
@@ -648,7 +695,8 @@ def get_long_label(self) -> str:
648695 lines .append (label_name )
649696
650697 lines .append (self .get_short_label ())
651- return '\n ' .join (lines )
698+ label = '\n ' .join (lines )
699+ return GPUWorkload .memoize (label )
652700
653701 def get_short_label (self ) -> str :
654702 '''
@@ -659,7 +707,8 @@ def get_short_label(self) -> str:
659707 '''
660708 lines = []
661709 lines .append (self .get_resolution_str ())
662- return '\n ' .join (lines )
710+ label = '\n ' .join (lines )
711+ return GPUWorkload .memoize (label )
663712
664713
665714class GPUImageTransfer (GPUWorkload ):
@@ -715,7 +764,8 @@ def get_transfer_size_str(self) -> str:
715764 return f'? pixels'
716765
717766 s = 's' if self .pixel_count != 1 else ''
718- return f'{ self .pixel_count } pixel{ s } '
767+ label = f'{ self .pixel_count } pixel{ s } '
768+ return GPUWorkload .memoize (label )
719769
720770 def get_long_label (self ) -> str :
721771 '''
@@ -732,7 +782,8 @@ def get_long_label(self) -> str:
732782 line = f'{ self .transfer_type } ({ self .get_transfer_size_str ()} )'
733783 lines .append (line )
734784
735- return '\n ' .join (lines )
785+ label = '\n ' .join (lines )
786+ return GPUWorkload .memoize (label )
736787
737788 def get_short_label (self ) -> str :
738789 '''
@@ -797,7 +848,8 @@ def get_transfer_size_str(self) -> str:
797848 return f'? bytes'
798849
799850 s = 's' if self .byte_count != 1 else ''
800- return f'{ self .byte_count } byte{ s } '
851+ label = f'{ self .byte_count } byte{ s } '
852+ return GPUWorkload .memoize (label )
801853
802854 def get_long_label (self ) -> str :
803855 '''
@@ -814,7 +866,8 @@ def get_long_label(self) -> str:
814866 line = f'{ self .transfer_type } ({ self .get_transfer_size_str ()} )'
815867 lines .append (line )
816868
817- return '\n ' .join (lines )
869+ label = '\n ' .join (lines )
870+ return GPUWorkload .memoize (label )
818871
819872 def get_short_label (self ) -> str :
820873 '''
@@ -884,7 +937,8 @@ def get_transfer_size_str(self) -> str:
884937 return f'? primitives'
885938
886939 s = 's' if self .primitive_count != 1 else ''
887- return f'{ self .primitive_count } primitive{ s } '
940+ label = f'{ self .primitive_count } primitive{ s } '
941+ return GPUWorkload .memoize (label )
888942
889943 def get_long_label (self ) -> str :
890944 '''
@@ -901,7 +955,8 @@ def get_long_label(self) -> str:
901955 line = f'{ self .build_type } ({ self .get_transfer_size_str ()} )'
902956 lines .append (line )
903957
904- return '\n ' .join (lines )
958+ label = '\n ' .join (lines )
959+ return GPUWorkload .memoize (label )
905960
906961 def get_short_label (self ) -> str :
907962 '''
@@ -963,7 +1018,8 @@ def get_transfer_size_str(self) -> str:
9631018 return f'? bytes'
9641019
9651020 s = 's' if self .byte_count != 1 else ''
966- return f'{ self .byte_count } byte{ s } '
1021+ label = f'{ self .byte_count } byte{ s } '
1022+ return GPUWorkload .memoize (label )
9671023
9681024 def get_long_label (self ) -> str :
9691025 '''
@@ -980,7 +1036,8 @@ def get_long_label(self) -> str:
9801036 line = f'{ self .transfer_type } ({ self .get_transfer_size_str ()} )'
9811037 lines .append (line )
9821038
983- return '\n ' .join (lines )
1039+ label = '\n ' .join (lines )
1040+ return GPUWorkload .memoize (label )
9841041
9851042 def get_short_label (self ) -> str :
9861043 '''
0 commit comments