diff --git a/src/main/java/com/xceptance/common/lang/StringHasher.java b/src/main/java/com/xceptance/common/lang/StringHasher.java index 685a52500..8df894f26 100644 --- a/src/main/java/com/xceptance/common/lang/StringHasher.java +++ b/src/main/java/com/xceptance/common/lang/StringHasher.java @@ -15,6 +15,8 @@ */ package com.xceptance.common.lang; +import com.xceptance.xlt.api.util.XltCharBuffer; + /** * A class the supports special ways to hash a string to improve the overall performance and * reduce cache misses. @@ -55,4 +57,26 @@ public static int hashCodeWithLimit(final CharSequence s, final char limitingCha return hash; } + + /** + * Hashes a string up to a terminal character excluding it + * This implementation uses the String hashcode after finding the limiting character. + * because String::indexOf became very fast in JDK 21 (native code). + * + * @param s the sequence of characters to hash up to the limiter + * @return the hashcode + */ + public static int hashCodeWithLimit(final XltCharBuffer s, final char limitingChar) + { + String _s = s.toString(); + final int pos = _s.indexOf(limitingChar); + if (pos > 0) + { + return _s.substring(0, pos).hashCode(); + } + else + { + return _s.hashCode(); + } + } } diff --git a/src/main/java/com/xceptance/xlt/api/engine/AbstractData.java b/src/main/java/com/xceptance/xlt/api/engine/AbstractData.java index bbb15400b..2d5cb50a6 100644 --- a/src/main/java/com/xceptance/xlt/api/engine/AbstractData.java +++ b/src/main/java/com/xceptance/xlt/api/engine/AbstractData.java @@ -104,8 +104,6 @@ public void setBaseValues(final List values) { // read and check the values name = values.get(1).toString(); - name.hashCode(); // create it when it is still hot in the cache - time = ParseNumbers.parseLong(values.get(2)); if (time <= 0) diff --git a/src/main/java/com/xceptance/xlt/api/util/XltCharBuffer.java b/src/main/java/com/xceptance/xlt/api/util/XltCharBuffer.java index 4bb82bb52..06dd4b857 100644 --- a/src/main/java/com/xceptance/xlt/api/util/XltCharBuffer.java +++ b/src/main/java/com/xceptance/xlt/api/util/XltCharBuffer.java @@ -704,15 +704,23 @@ public int hashCode() final int l = length & ~(8 - 1); final int l2 = length + from; - for (; i < l; i += 8) + for (; i < l; i += 8) { - h = -1807454463 * h + 1742810335 * src[i + 0] + 887503681 * src[i + 1] + 28629151 * src[i + 2] + 923521 * src[i + 3] + - 29791 * src[i + 4] + 961 * src[i + 5] + 31 * src[i + 6] + 1 * src[i + 7]; + h = -1807454463 * h; + int h1 = 1742810335 * src[i] + + 887503681 * src[i+1] + + 28629151 * src[i+2] + + 923521 * src[i+3] + + 29791 * src[i+4] + + 961 * src[i+5] + + 31 * src[i+6] + + src[i+7]; + h += h1; } - for (; i < l2; i++) + for (; i < l2; i++) { - h = 31 * h + src[i]; + h = (src[i] - h) + (h << 5); } this.hashCode = h; diff --git a/src/main/java/com/xceptance/xlt/report/DataRecordFactory.java b/src/main/java/com/xceptance/xlt/report/DataRecordFactory.java index e9bb5368c..3875fe401 100644 --- a/src/main/java/com/xceptance/xlt/report/DataRecordFactory.java +++ b/src/main/java/com/xceptance/xlt/report/DataRecordFactory.java @@ -18,7 +18,16 @@ import java.lang.reflect.Constructor; import java.util.Map; +import com.xceptance.xlt.agent.JvmResourceUsageData; +import com.xceptance.xlt.api.engine.ActionData; +import com.xceptance.xlt.api.engine.CustomData; +import com.xceptance.xlt.api.engine.CustomValue; import com.xceptance.xlt.api.engine.Data; +import com.xceptance.xlt.api.engine.EventData; +import com.xceptance.xlt.api.engine.PageLoadTimingData; +import com.xceptance.xlt.api.engine.RequestData; +import com.xceptance.xlt.api.engine.TransactionData; +import com.xceptance.xlt.api.engine.WebVitalData; import com.xceptance.xlt.api.util.XltCharBuffer; import com.xceptance.xlt.api.util.XltException; @@ -98,11 +107,34 @@ public DataRecordFactory(final Map> dataClasses) */ public Data createStatistics(final XltCharBuffer src) throws Exception { - // TODO: The following may throw NullPointerException or ArrayIndexOutOfBoundsException in case of unknown type - // codes. - final Constructor c = constructors[src.charAt(0) - offset]; - final Data data = c.newInstance(); + // com.xceptance.xlt.reportgenerator.dataRecords.T = com.xceptance.xlt.api.engine.TransactionData + // com.xceptance.xlt.reportgenerator.dataRecords.A = com.xceptance.xlt.api.engine.ActionData + // com.xceptance.xlt.reportgenerator.dataRecords.R = com.xceptance.xlt.api.engine.RequestData + // com.xceptance.xlt.reportgenerator.dataRecords.C = com.xceptance.xlt.api.engine.CustomData + // com.xceptance.xlt.reportgenerator.dataRecords.E = com.xceptance.xlt.api.engine.EventData + // com.xceptance.xlt.reportgenerator.dataRecords.J = com.xceptance.xlt.agent.JvmResourceUsageData + // com.xceptance.xlt.reportgenerator.dataRecords.V = com.xceptance.xlt.api.engine.CustomValue + // com.xceptance.xlt.reportgenerator.dataRecords.P = com.xceptance.xlt.api.engine.PageLoadTimingData + // com.xceptance.xlt.reportgenerator.dataRecords.W = com.xceptance.xlt.api.engine.WebVitalData - return data; + return switch (src.charAt(0)) + { + case 'A' -> new ActionData(); + case 'T' -> new TransactionData(); + case 'R' -> new RequestData(); + case 'C' -> new CustomData(); + case 'E' -> new EventData(); + case 'J' -> new JvmResourceUsageData(); + case 'V' -> new CustomValue(); + case 'P' -> new PageLoadTimingData(); + case 'W' -> new WebVitalData(); + + default -> + { + // use reflection to create the instance + final Constructor c = constructors[src.charAt(0) - offset]; + yield c.newInstance(); + } + }; } }