@@ -32,6 +32,9 @@ public class StringSimilarity {
3232
3333 private static final int mapLength = 1500 ;
3434 public static int maxElaborationRegex = 8192 ;
35+ // slow elaboration warn threshold in ms; 0 = disabled (default)
36+ // enable via GlobalProperty or test setup: StringSimilarity.slowElaborationThresholdMs = 200;
37+ public static long slowElaborationThresholdMs = 0 ;
3538
3639 // matched errors
3740 private static final Map <String , ErrorCodeElaboration > errors = new LinkedHashMap <String , ErrorCodeElaboration >(mapLength , 0.9f , true ) {
@@ -280,8 +283,15 @@ private static boolean isRedundant(String sub) {
280283 }
281284
282285 private static void logSearchSpend (String sub , long start , boolean found ) {
283- logger .debug (String .format ("[%s] spend %s ms to search elaboration \" %s\" " , found , System .currentTimeMillis () - start ,
284- sub .length () > 50 ? sub .substring (0 , 50 ) + "..." : sub ));
286+ long cost = System .currentTimeMillis () - start ;
287+ if (slowElaborationThresholdMs > 0 && cost > slowElaborationThresholdMs ) {
288+ logger .warn (String .format ("[SLOW-ELABORATION] cost %d ms, found=%s, input_len=%d, input=%s" ,
289+ cost , found , sub .length (),
290+ sub .length () > 100 ? sub .substring (0 , 100 ) + "..." : sub ));
291+ } else {
292+ logger .debug (String .format ("[%s] spend %s ms to search elaboration \" %s\" " , found , cost ,
293+ sub .length () > 50 ? sub .substring (0 , 50 ) + "..." : sub ));
294+ }
285295 }
286296
287297 /**
@@ -306,7 +316,10 @@ public static ErrorCodeElaboration findSimilar(String sub, Object...args) {
306316 }
307317
308318 long start = System .currentTimeMillis ();
309- ErrorCodeElaboration err = errors .get (sub );
319+ ErrorCodeElaboration err ;
320+ synchronized (errors ) {
321+ err = errors .get (sub );
322+ }
310323 if (err != null && verifyElaboration (err , sub , args )) {
311324 logSearchSpend (sub , start , true );
312325 return err ;
@@ -317,20 +330,26 @@ public static ErrorCodeElaboration findSimilar(String sub, Object...args) {
317330 // same cause will happen
318331 // invalid cache, generate elaboration again
319332 if (err != null ) {
320- errors .remove (sub );
333+ synchronized (errors ) {
334+ errors .remove (sub );
335+ }
321336 }
322337
323338 // check missed cache for both fmt template and formatted string
324- if (missed .get (sub ) != null ) {
325- logSearchSpend (sub , start , false );
326- return null ;
339+ synchronized (missed ) {
340+ if (missed .get (sub ) != null ) {
341+ logSearchSpend (sub , start , false );
342+ return null ;
343+ }
327344 }
328345 if (args != null ) {
329346 try {
330347 String formatted = String .format (sub , args );
331- if (missed .get (formatted ) != null ) {
332- logSearchSpend (sub , start , false );
333- return null ;
348+ synchronized (missed ) {
349+ if (missed .get (formatted ) != null ) {
350+ logSearchSpend (sub , start , false );
351+ return null ;
352+ }
334353 }
335354 } catch (Exception e ) {
336355 logger .trace (String .format ("failed to format elaboration key: %s" , e .getMessage ()));
0 commit comments