diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java index 7e0e6017b88..687d2a18c5f 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java @@ -60,7 +60,12 @@ public class HttpFields implements Iterable private HttpField[] _fields; private int _size; - + + + private int iterations = 0; + private int lookups; + + /** * Initialize an empty HttpFields. */ @@ -98,17 +103,20 @@ public class HttpFields implements Iterable @Override public Iterator iterator() { + iterations++; return new Itr(); } public ListIterator listIterator() { + iterations++; return new Itr(); } public Stream stream() { + iterations++; return StreamSupport.stream(Arrays.spliterator(_fields,0,_size),false); } @@ -151,6 +159,7 @@ public class HttpFields implements Iterable public HttpField getField(HttpHeader header) { + lookups++; for (int i=0;i<_size;i++) { HttpField f=_fields[i]; @@ -162,6 +171,7 @@ public class HttpFields implements Iterable public HttpField getField(String name) { + lookups++; for (int i=0;i<_size;i++) { HttpField f=_fields[i]; @@ -173,6 +183,7 @@ public class HttpFields implements Iterable public boolean contains(HttpField field) { + lookups++; for (int i=_size;i-->0;) { HttpField f=_fields[i]; @@ -184,6 +195,7 @@ public class HttpFields implements Iterable public boolean contains(HttpHeader header, String value) { + lookups++; for (int i=_size;i-->0;) { HttpField f=_fields[i]; @@ -195,6 +207,7 @@ public class HttpFields implements Iterable public boolean contains(String name, String value) { + lookups++; for (int i=_size;i-->0;) { HttpField f=_fields[i]; @@ -206,6 +219,7 @@ public class HttpFields implements Iterable public boolean contains(HttpHeader header) { + lookups++; for (int i=_size;i-->0;) { HttpField f=_fields[i]; @@ -217,6 +231,7 @@ public class HttpFields implements Iterable public boolean containsKey(String name) { + lookups++; for (int i=_size;i-->0;) { HttpField f=_fields[i]; @@ -234,6 +249,7 @@ public class HttpFields implements Iterable public String get(HttpHeader header) { + lookups++; for (int i=0;i<_size;i++) { HttpField f=_fields[i]; @@ -251,6 +267,7 @@ public class HttpFields implements Iterable public String get(String header) { + lookups++; for (int i=0;i<_size;i++) { HttpField f=_fields[i]; @@ -268,6 +285,7 @@ public class HttpFields implements Iterable */ public List getValuesList(HttpHeader header) { + lookups++; final List list = new ArrayList<>(); for (HttpField f : this) if (f.getHeader()==header) @@ -283,6 +301,7 @@ public class HttpFields implements Iterable */ public List getValuesList(String name) { + lookups++; final List list = new ArrayList<>(); for (HttpField f : this) if (f.getName().equalsIgnoreCase(name)) @@ -394,6 +413,7 @@ public class HttpFields implements Iterable */ public List getCSV(HttpHeader header,boolean keepQuotes) { + lookups++; QuotedCSV values = null; for (HttpField f : this) { @@ -417,6 +437,7 @@ public class HttpFields implements Iterable */ public List getCSV(String name,boolean keepQuotes) { + lookups++; QuotedCSV values = null; for (HttpField f : this) { @@ -903,6 +924,9 @@ public class HttpFields implements Iterable public void clear() { + System.err.printf("iterations=%d lookups=%d%n",iterations,lookups); + iterations = 0; + lookups = 0; _size=0; } diff --git a/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ListVsTrieBenchmark.java b/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ListVsMapBenchmark.java similarity index 84% rename from jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ListVsTrieBenchmark.java rename to jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ListVsMapBenchmark.java index 84c8c6f5789..e3a25c6ffe3 100644 --- a/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ListVsTrieBenchmark.java +++ b/jetty-jmh/src/main/java/org/eclipse/jetty/server/jmh/ListVsMapBenchmark.java @@ -20,14 +20,11 @@ package org.eclipse.jetty.server.jmh; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.util.ArrayTrie; -import org.eclipse.jetty.util.TreeTrie; -import org.eclipse.jetty.util.Trie; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Level; @@ -48,7 +45,7 @@ import org.openjdk.jmh.runner.options.OptionsBuilder; @Threads(1) @Warmup(iterations = 6, time = 2000, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 3, time = 2000, timeUnit = TimeUnit.MILLISECONDS) -public class ListVsTrieBenchmark +public class ListVsMapBenchmark { @Param({ "12" }) // Chrome has 12 for HTTP/1.1 and 16 for HTTP/2 (including meta headers) public static int size; @@ -165,35 +162,28 @@ public class ListVsTrieBenchmark @Benchmark @BenchmarkMode({Mode.Throughput}) - public long testTreeTrie() throws Exception + public long testSortedMap() throws Exception { - Trie trie = new TreeTrie<>(); - fill(p->trie.put(p.key,p)); - return test(trie::get); - } - - @Benchmark - @BenchmarkMode({Mode.Throughput}) - public long testArrayTrie() throws Exception - { - Trie trie = new ArrayTrie<>(length*size); - fill(p->trie.put(p.key,p)); - return test(trie::get); - } - - @Benchmark - @BenchmarkMode({Mode.Throughput}) - public long testMap() throws Exception - { - Map map = new HashMap<>(size); - fill(p->map.put(p.key.toLowerCase(),p)); - return test(k->map.get(k.toLowerCase())); + Map> map = new LinkedHashMap<>(size); + fill(p-> + { + List list = new ArrayList<>(); + list.add(p); + map.put(p.key.toLowerCase(),list); + }); + return test(k-> + { + List list = map.get(k.toLowerCase()); + if (list==null || list.isEmpty()) + return null; + return list.get(0); + }); } public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() - .include(ListVsTrieBenchmark.class.getSimpleName()) + .include(ListVsMapBenchmark.class.getSimpleName()) // .addProfiler(GCProfiler.class) .forks(1) .build();