@@ -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 [str , str ] = 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,9 @@ 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
357389
358390 def get_draw_count_str (self ) -> str :
359391 '''
@@ -368,7 +400,8 @@ def get_draw_count_str(self) -> str:
368400 if self .draw_call_count == 1 :
369401 return '1 draw'
370402
371- return f'{ self .draw_call_count } draws'
403+ label = f'{ self .draw_call_count } draws'
404+ return self .memoize (label )
372405
373406 def get_subpass_count_str (self ) -> str :
374407 '''
@@ -378,7 +411,8 @@ def get_subpass_count_str(self) -> str:
378411 Returns the label for use in the UI.
379412 '''
380413 es = '' if self .subpass_count == 1 else 'es'
381- return f'{ self .subpass_count } subpass{ es } '
414+ label = f'{ self .subpass_count } subpass{ es } '
415+ return self .memoize (label )
382416
383417 def get_attachment_present_str (self ) -> str :
384418 '''
@@ -388,7 +422,8 @@ def get_attachment_present_str(self) -> str:
388422 Returns the label for use in the UI.
389423 '''
390424 bindings = [x .binding for x in self .attachments ]
391- return self .get_compact_string (bindings )
425+ label = self .get_compact_str (bindings )
426+ return GPUWorkload .memoize (label )
392427
393428 def get_attachment_loadop_str (self ) -> str :
394429 '''
@@ -398,7 +433,8 @@ def get_attachment_loadop_str(self) -> str:
398433 Returns the label for use in the UI.
399434 '''
400435 bindings = [x .binding for x in self .attachments if x .is_loaded ]
401- return self .get_compact_string (bindings )
436+ label = self .get_compact_str (bindings )
437+ return GPUWorkload .memoize (label )
402438
403439 def get_attachment_storeop_str (self ) -> str :
404440 '''
@@ -408,10 +444,11 @@ def get_attachment_storeop_str(self) -> str:
408444 Returns the label for use in the UI.
409445 '''
410446 bindings = [x .binding for x in self .attachments if x .is_stored ]
411- return self .get_compact_string (bindings )
447+ label = self .get_compact_str (bindings )
448+ return GPUWorkload .memoize (label )
412449
413450 @classmethod
414- def get_compact_string (cls , bindings : list [str ]) -> str :
451+ def get_compact_str (cls , bindings : list [str ]) -> str :
415452 '''
416453 Get the compact UI string for a set of attachment bind points.
417454
@@ -422,7 +459,8 @@ def get_compact_string(cls, bindings: list[str]) -> str:
422459 A binding string of the form, e.g. "C0124DS".
423460 '''
424461 merge = '' .join (bindings )
425- return '' .join ([j for i , j in enumerate (merge ) if j not in merge [:i ]])
462+ label = '' .join ([j for i , j in enumerate (merge ) if j not in merge [:i ]])
463+ return GPUWorkload .memoize (label )
426464
427465 def get_attachment_long_label (self ) -> str :
428466 '''
@@ -441,7 +479,8 @@ def get_attachment_long_label(self) -> str:
441479 if stored :
442480 stored = f' > store({ stored } ) '
443481
444- return f'{ loaded } [{ present } ]{ stored } '
482+ label = f'{ loaded } [{ present } ]{ stored } '
483+ return GPUWorkload .memoize (label )
445484
446485 def get_attachment_short_label (self ) -> str :
447486 '''
@@ -451,7 +490,8 @@ def get_attachment_short_label(self) -> str:
451490 A string showing attachments without load/storeOp usage.
452491 '''
453492 present = self .get_attachment_present_str ()
454- return f'[{ present } ]'
493+ label = f'[{ present } ]'
494+ return GPUWorkload .memoize (label )
455495
456496 def get_long_label (self ) -> str :
457497 '''
@@ -471,7 +511,8 @@ def get_long_label(self) -> str:
471511 line = self .get_attachment_long_label ()
472512 lines .append (line )
473513
474- return '\n ' .join (lines )
514+ label = '\n ' .join (lines )
515+ return GPUWorkload .memoize (label )
475516
476517 def get_short_label (self ) -> str :
477518 '''
@@ -488,7 +529,8 @@ def get_short_label(self) -> str:
488529 line = self .get_attachment_short_label ()
489530 lines .append (line )
490531
491- return '\n ' .join (lines )
532+ label = '\n ' .join (lines )
533+ return GPUWorkload .memoize (label )
492534
493535
494536class GPUDispatch (GPUWorkload ):
@@ -547,7 +589,8 @@ def get_resolution_str(self) -> str:
547589 if self .groups_z > 1 :
548590 dims .append (self .groups_z )
549591
550- return f'{ "x" .join ([str (dim ) for dim in dims ])} groups'
592+ label = f'{ "x" .join ([str (dim ) for dim in dims ])} groups'
593+ return GPUWorkload .memoize (label )
551594
552595 def get_long_label (self ) -> str :
553596 '''
@@ -562,7 +605,8 @@ def get_long_label(self) -> str:
562605 lines .append (label_name )
563606
564607 lines .append (self .get_short_label ())
565- return '\n ' .join (lines )
608+ label = '\n ' .join (lines )
609+ return GPUWorkload .memoize (label )
566610
567611 def get_short_label (self ) -> str :
568612 '''
@@ -574,7 +618,8 @@ def get_short_label(self) -> str:
574618 lines = []
575619 line = self .get_resolution_str ()
576620 lines .append (line )
577- return '\n ' .join (lines )
621+ label = '\n ' .join (lines )
622+ return GPUWorkload .memoize (label )
578623
579624
580625class GPUTraceRays (GPUWorkload ):
@@ -633,7 +678,8 @@ def get_resolution_str(self) -> str:
633678 if self .items_z > 1 :
634679 dims .append (self .items_z )
635680
636- return f'{ "x" .join ([str (dim ) for dim in dims ])} items'
681+ label = f'{ "x" .join ([str (dim ) for dim in dims ])} items'
682+ return GPUWorkload .memoize (label )
637683
638684 def get_long_label (self ) -> str :
639685 '''
@@ -648,7 +694,8 @@ def get_long_label(self) -> str:
648694 lines .append (label_name )
649695
650696 lines .append (self .get_short_label ())
651- return '\n ' .join (lines )
697+ label = '\n ' .join (lines )
698+ return GPUWorkload .memoize (label )
652699
653700 def get_short_label (self ) -> str :
654701 '''
@@ -659,7 +706,8 @@ def get_short_label(self) -> str:
659706 '''
660707 lines = []
661708 lines .append (self .get_resolution_str ())
662- return '\n ' .join (lines )
709+ label = '\n ' .join (lines )
710+ return GPUWorkload .memoize (label )
663711
664712
665713class GPUImageTransfer (GPUWorkload ):
@@ -715,7 +763,8 @@ def get_transfer_size_str(self) -> str:
715763 return f'? pixels'
716764
717765 s = 's' if self .pixel_count != 1 else ''
718- return f'{ self .pixel_count } pixel{ s } '
766+ label = f'{ self .pixel_count } pixel{ s } '
767+ return GPUWorkload .memoize (label )
719768
720769 def get_long_label (self ) -> str :
721770 '''
@@ -732,7 +781,8 @@ def get_long_label(self) -> str:
732781 line = f'{ self .transfer_type } ({ self .get_transfer_size_str ()} )'
733782 lines .append (line )
734783
735- return '\n ' .join (lines )
784+ label = '\n ' .join (lines )
785+ return GPUWorkload .memoize (label )
736786
737787 def get_short_label (self ) -> str :
738788 '''
@@ -797,7 +847,8 @@ def get_transfer_size_str(self) -> str:
797847 return f'? bytes'
798848
799849 s = 's' if self .byte_count != 1 else ''
800- return f'{ self .byte_count } byte{ s } '
850+ label = f'{ self .byte_count } byte{ s } '
851+ return GPUWorkload .memoize (label )
801852
802853 def get_long_label (self ) -> str :
803854 '''
@@ -814,7 +865,8 @@ def get_long_label(self) -> str:
814865 line = f'{ self .transfer_type } ({ self .get_transfer_size_str ()} )'
815866 lines .append (line )
816867
817- return '\n ' .join (lines )
868+ label = '\n ' .join (lines )
869+ return GPUWorkload .memoize (label )
818870
819871 def get_short_label (self ) -> str :
820872 '''
@@ -884,7 +936,8 @@ def get_transfer_size_str(self) -> str:
884936 return f'? primitives'
885937
886938 s = 's' if self .primitive_count != 1 else ''
887- return f'{ self .primitive_count } primitive{ s } '
939+ label = f'{ self .primitive_count } primitive{ s } '
940+ return GPUWorkload .memoize (label )
888941
889942 def get_long_label (self ) -> str :
890943 '''
@@ -901,7 +954,8 @@ def get_long_label(self) -> str:
901954 line = f'{ self .build_type } ({ self .get_transfer_size_str ()} )'
902955 lines .append (line )
903956
904- return '\n ' .join (lines )
957+ label = '\n ' .join (lines )
958+ return GPUWorkload .memoize (label )
905959
906960 def get_short_label (self ) -> str :
907961 '''
@@ -963,7 +1017,8 @@ def get_transfer_size_str(self) -> str:
9631017 return f'? bytes'
9641018
9651019 s = 's' if self .byte_count != 1 else ''
966- return f'{ self .byte_count } byte{ s } '
1020+ label = f'{ self .byte_count } byte{ s } '
1021+ return GPUWorkload .memoize (label )
9671022
9681023 def get_long_label (self ) -> str :
9691024 '''
@@ -980,7 +1035,8 @@ def get_long_label(self) -> str:
9801035 line = f'{ self .transfer_type } ({ self .get_transfer_size_str ()} )'
9811036 lines .append (line )
9821037
983- return '\n ' .join (lines )
1038+ label = '\n ' .join (lines )
1039+ return GPUWorkload .memoize (label )
9841040
9851041 def get_short_label (self ) -> str :
9861042 '''
0 commit comments