You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by to...@apache.org on 2015/10/07 14:52:10 UTC
svn commit: r1707283 - in /sling/trunk/bundles/engine/src:
main/java/org/apache/sling/engine/impl/request/
test/java/org/apache/sling/engine/impl/request/
Author: tomekr
Date: Wed Oct 7 12:52:09 2015
New Revision: 1707283
URL: http://svn.apache.org/viewvc?rev=1707283&view=rev
Log:
SLING-4544 Performance: MessageFormat shouldn't be used for logging in SlingRequestProgressTracker
Added:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/FastMessageFormat.java
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/request/FastMessageFormatTest.java
Modified:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/SlingRequestProgressTracker.java
Added: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/FastMessageFormat.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/FastMessageFormat.java?rev=1707283&view=auto
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/FastMessageFormat.java (added)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/FastMessageFormat.java Wed Oct 7 12:52:09 2015
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.engine.impl.request;
+
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+
+/**
+ * Fast MessageFormat implementation which is not thread-safe. It is based on the assumptions that
+ * <ul>
+ * <li>most formats do not contain format types and styles</li>
+ * <li>do not use escaping</li>
+ * <li>format elements are in order</li>
+ * </ul>
+ *
+ * If one of these assumptions fails, then it falls back to the original {@link MessageFormat}.<br>
+ * To increase the benefit of this implementation, every instance should be reused as often as possible.
+ */
+public class FastMessageFormat {
+
+ // Reusable formats instances. Cannot be static because these classes are not thread safe.
+ private NumberFormat numberFormat;
+ private DateFormat dateFormat;
+
+ private NumberFormat getNumberFormat() {
+ if (numberFormat == null) {
+ numberFormat = NumberFormat.getNumberInstance();
+ }
+ return numberFormat;
+ }
+
+ private DateFormat getDateFormat() {
+ if (dateFormat == null) {
+ dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+ }
+ return dateFormat;
+ }
+
+ /**
+ * Use this method exactly like {@link MessageFormat#format(String, Object...)}.
+ *
+ * @see MessageFormat#format(String, Object...)
+ */
+ public String format(String pattern, Object... arguments) {
+ if (arguments == null || arguments.length == 0) {
+ return pattern;
+ } else {
+ if (pattern.indexOf('\'') != -1) {
+ // Escaping is not supported, fall back
+ return MessageFormat.format(pattern, arguments);
+ } else {
+ StringBuilder message = new StringBuilder();
+ int previousEnd = 0;
+ for (int i = 0; i < arguments.length; i++) {
+ String placeholder = '{' + String.valueOf(i);
+ int placeholderIndex = pattern.indexOf(placeholder);
+ // -1 or before previous placeholder || format element with type/style
+ if (placeholderIndex < previousEnd
+ || pattern.charAt(placeholderIndex + placeholder.length()) != '}') {
+ // Type, style and random order are not supported, fall back
+ return MessageFormat.format(pattern, arguments);
+ } else {
+ // Format argument if necessary
+ Object argument = arguments[i];
+ if (argument instanceof Number) {
+ argument = getNumberFormat().format(argument);
+ } else if (argument instanceof Date) {
+ argument = getDateFormat().format(argument);
+ }
+
+ // Append previous part of the string and formatted argument
+ message.append(pattern.substring(previousEnd, placeholderIndex));
+ message.append(argument);
+ previousEnd = placeholderIndex + placeholder.length() + 1;
+ }
+ }
+ message.append(pattern.substring(previousEnd, pattern.length()));
+ return message.toString();
+ }
+ }
+ }
+
+}
Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/SlingRequestProgressTracker.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/SlingRequestProgressTracker.java?rev=1707283&r1=1707282&r2=1707283&view=diff
==============================================================================
--- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/SlingRequestProgressTracker.java (original)
+++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/SlingRequestProgressTracker.java Wed Oct 7 12:52:09 2015
@@ -19,7 +19,6 @@
package org.apache.sling.engine.impl.request;
import java.io.PrintWriter;
-import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -129,6 +128,8 @@ public class SlingRequestProgressTracker
*/
private final Map<String, Long> namedTimerEntries = new HashMap<String, Long>();
+ private final FastMessageFormat messageFormat = new FastMessageFormat();
+
/**
* Creates a new request progress tracker.
*/
@@ -210,7 +211,7 @@ public class SlingRequestProgressTracker
/** Creates an entry with the given entry tag and message */
public void log(String format, Object... args) {
- String message = MessageFormat.format(format, args);
+ String message = messageFormat.format(format, args);
entries.add(new TrackingEntry(LOG_PREFIX + message));
}
@@ -250,7 +251,7 @@ public class SlingRequestProgressTracker
*/
public void logTimer(String name, String format, Object... args) {
if (namedTimerEntries.containsKey(name)) {
- logTimerInternal(name, MessageFormat.format(format, args), namedTimerEntries.get(name));
+ logTimerInternal(name, messageFormat.format(format, args), namedTimerEntries.get(name));
}
}
Added: sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/request/FastMessageFormatTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/request/FastMessageFormatTest.java?rev=1707283&view=auto
==============================================================================
--- sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/request/FastMessageFormatTest.java (added)
+++ sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/request/FastMessageFormatTest.java Wed Oct 7 12:52:09 2015
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.engine.impl.request;
+
+import org.junit.Test;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+
+public class FastMessageFormatTest {
+
+ @Test
+ public void testFormat() {
+ FormatTest[] tests = {
+ // Data types
+ new FormatTest("{0}", 1),
+ new FormatTest("{0}", Integer.MAX_VALUE),
+ new FormatTest("{0}", Long.MAX_VALUE),
+ new FormatTest("{0}", Math.PI),
+ new FormatTest("{0}", 123456.123456),
+ new FormatTest("{0}", Float.MAX_VALUE),
+ new FormatTest("{0}", new Date()),
+ new FormatTest("{0}", Calendar.getInstance()),
+ new FormatTest("{0}", true),
+ new FormatTest("{0}", false),
+ new FormatTest("{0}", new int[] {1,2,3}),
+ new FormatTest("{0}", (Object) new Integer[] {1,2,3}),
+ new FormatTest("{0}", Arrays.asList(1, 2, 3)),
+ new FormatTest("{0}", "text"),
+
+ // Patterns
+ new FormatTest("{0}{0}", 1, 2),
+ new FormatTest("a{0}b{1}c", 1, 2),
+ new FormatTest("a{0}b{1}c{2}d", 1, 2, 3),
+ new FormatTest("a{0}bb{1}ccc{2}dddd", 10, 20, 30),
+ new FormatTest("c{1}b{0}a", 1, 2),
+ new FormatTest("c{1}b{0}a{1}c", 1, 2),
+
+ // Type/style
+ new FormatTest("c{0,number,#.##}b{0}a{1}c", 1, 2),
+ new FormatTest("{0,number,#.##}", 1.2345),
+
+ // Escaping
+ new FormatTest("'{0}'", 1)
+ };
+
+ FastMessageFormat fastMessageFormat = new FastMessageFormat();
+ for (FormatTest test : tests) {
+ String expected = MessageFormat.format(test.pattern, test.args);
+ String actual = fastMessageFormat.format(test.pattern, test.args);
+ assertEquals(expected, actual);
+ }
+ }
+
+ private static class FormatTest {
+ final String pattern;
+ final Object[] args;
+ public FormatTest(String pattern, Object... args) {
+ this.pattern = pattern;
+ this.args = args;
+ }
+ }
+
+}