Resources.getMessage takes 4 times as long as necessary because it calls the static function MessageFormat.format() This function essentially instantiates a new MessageFormat object every time and then formats a message. With each new instantiation, the message string must be parsed. Using a profiling tool, I made 18,000 consecutive calls to the ResourceMessages.getMessage(String, Object[]) function on my machine which took 49,340ms to process. 47,695ms was consumed in the MessageFormat.format() function. I altered the class and created a static hashtable to cache MessageFormats after each initial request. The formats were re-used instead of parsing the string with each call. Making the same number of call to ResourceMessages.getMessage took only 10,086ms. This is a simple alteration, below is the code I used to make this change. private static Hashtable formats = new Hashtable(); private static MessageFormat getFormat(String name) throws MissingResourceException { MessageFormat format = (MessageFormat) formats.get(name); if (format==null) { format = new MessageFormat(rb.getString(name)); formats.put(name, format); } return format; } /** Retrieves a message with arbitrarily many arguments. */ public static String getMessage(String name, Object[] a) throws MissingResourceException { Format f = getFormat(name); synchronized(f) { return f.format(a); } }
Created attachment 5182 [details] pre-parsed formats cached with simple pooling code
Created attachment 5189 [details] CVS diff file containing changes made in previous upload
Thanks for the suggestion on improving performance. However, wouldn't we want a more sophisticated caching mechanism to avoid having the cache grow indefinitely?
CC'ing the taglibs-dev address to all Standard bugs.
SPI style plugin cache added for this (see attachment to issue https://issues.apache.org/bugzilla/show_bug.cgi?id=31789 ).
Quite a confusing issue. As far as I can tell, the only things that use the Resources class are errors. So there shouldn't be such a speed improvement unless Resources was being used in the application too (ill advised I think) or there were lots of errors, in which case there's a bigger issue. There is no ResourcesMessages class in the JSTL implementation. A cache could be put in place for the fmt:message, but it would need to be keyed on both locale and pattern and I'm hesistant to dive in on that. I think this should be a WONTFIX.