66//! logging of advisories that would otherwise spam every frame).
77
88use std:: {
9- collections:: HashSet ,
9+ collections:: {
10+ HashSet ,
11+ VecDeque ,
12+ } ,
1013 sync:: {
1114 Mutex ,
1215 OnceLock ,
1316 } ,
1417} ;
1518
16- /// Global, process-wide de-duplication set for warn-once messages.
17- static WARN_ONCE_KEYS : OnceLock < Mutex < HashSet < String > > > = OnceLock :: new ( ) ;
19+ /// Maximum number of unique warn-once keys to retain in memory.
20+ const WARN_ONCE_MAX_KEYS : usize = 1024 ;
21+
22+ /// Global, process-wide state for warn-once messages.
23+ ///
24+ /// The state uses a hash set for membership checks and a queue to track
25+ /// insertion order, allowing the cache to evict the oldest keys when the
26+ /// capacity is reached.
27+ #[ derive( Default ) ]
28+ struct WarnOnceState {
29+ seen_keys : HashSet < String > ,
30+ key_order : VecDeque < String > ,
31+ }
32+
33+ /// Global, process-wide de-duplication cache for warn-once messages.
34+ static WARN_ONCE_KEYS : OnceLock < Mutex < WarnOnceState > > = OnceLock :: new ( ) ;
1835
1936/// Log a warning message at most once per unique `key` across the process.
2037///
@@ -24,13 +41,24 @@ static WARN_ONCE_KEYS: OnceLock<Mutex<HashSet<String>>> = OnceLock::new();
2441/// panics.
2542pub fn warn_once ( key : & str , message : & str ) {
2643 let set = WARN_ONCE_KEYS . get_or_init ( || {
27- return Mutex :: new ( HashSet :: new ( ) ) ;
44+ return Mutex :: new ( WarnOnceState :: default ( ) ) ;
2845 } ) ;
2946 match set. lock ( ) {
3047 Ok ( mut guard) => {
31- if guard. insert ( key . to_string ( ) ) {
32- logging :: warn! ( "{}" , message ) ;
48+ if guard. seen_keys . contains ( key ) {
49+ return ;
3350 }
51+
52+ if guard. seen_keys . len ( ) >= WARN_ONCE_MAX_KEYS {
53+ if let Some ( oldest_key) = guard. key_order . pop_front ( ) {
54+ guard. seen_keys . remove ( & oldest_key) ;
55+ }
56+ }
57+
58+ let key_string = key. to_string ( ) ;
59+ guard. seen_keys . insert ( key_string. clone ( ) ) ;
60+ guard. key_order . push_back ( key_string) ;
61+ logging:: warn!( "{}" , message) ;
3462 return ;
3563 }
3664 Err ( _) => {
0 commit comments