Use LinkedHashMap<List<Pair>>

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2019-05-21 13:59:52 +02:00
parent 2831bfb159
commit 1458854d24
2 changed files with 43 additions and 29 deletions

View File

@ -61,6 +61,11 @@ public class HttpFields implements Iterable<HttpField>
private HttpField[] _fields; private HttpField[] _fields;
private int _size; private int _size;
private int iterations = 0;
private int lookups;
/** /**
* Initialize an empty HttpFields. * Initialize an empty HttpFields.
*/ */
@ -98,17 +103,20 @@ public class HttpFields implements Iterable<HttpField>
@Override @Override
public Iterator<HttpField> iterator() public Iterator<HttpField> iterator()
{ {
iterations++;
return new Itr(); return new Itr();
} }
public ListIterator<HttpField> listIterator() public ListIterator<HttpField> listIterator()
{ {
iterations++;
return new Itr(); return new Itr();
} }
public Stream<HttpField> stream() public Stream<HttpField> stream()
{ {
iterations++;
return StreamSupport.stream(Arrays.spliterator(_fields,0,_size),false); return StreamSupport.stream(Arrays.spliterator(_fields,0,_size),false);
} }
@ -151,6 +159,7 @@ public class HttpFields implements Iterable<HttpField>
public HttpField getField(HttpHeader header) public HttpField getField(HttpHeader header)
{ {
lookups++;
for (int i=0;i<_size;i++) for (int i=0;i<_size;i++)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -162,6 +171,7 @@ public class HttpFields implements Iterable<HttpField>
public HttpField getField(String name) public HttpField getField(String name)
{ {
lookups++;
for (int i=0;i<_size;i++) for (int i=0;i<_size;i++)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -173,6 +183,7 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpField field) public boolean contains(HttpField field)
{ {
lookups++;
for (int i=_size;i-->0;) for (int i=_size;i-->0;)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -184,6 +195,7 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpHeader header, String value) public boolean contains(HttpHeader header, String value)
{ {
lookups++;
for (int i=_size;i-->0;) for (int i=_size;i-->0;)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -195,6 +207,7 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(String name, String value) public boolean contains(String name, String value)
{ {
lookups++;
for (int i=_size;i-->0;) for (int i=_size;i-->0;)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -206,6 +219,7 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpHeader header) public boolean contains(HttpHeader header)
{ {
lookups++;
for (int i=_size;i-->0;) for (int i=_size;i-->0;)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -217,6 +231,7 @@ public class HttpFields implements Iterable<HttpField>
public boolean containsKey(String name) public boolean containsKey(String name)
{ {
lookups++;
for (int i=_size;i-->0;) for (int i=_size;i-->0;)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -234,6 +249,7 @@ public class HttpFields implements Iterable<HttpField>
public String get(HttpHeader header) public String get(HttpHeader header)
{ {
lookups++;
for (int i=0;i<_size;i++) for (int i=0;i<_size;i++)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -251,6 +267,7 @@ public class HttpFields implements Iterable<HttpField>
public String get(String header) public String get(String header)
{ {
lookups++;
for (int i=0;i<_size;i++) for (int i=0;i<_size;i++)
{ {
HttpField f=_fields[i]; HttpField f=_fields[i];
@ -268,6 +285,7 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public List<String> getValuesList(HttpHeader header) public List<String> getValuesList(HttpHeader header)
{ {
lookups++;
final List<String> list = new ArrayList<>(); final List<String> list = new ArrayList<>();
for (HttpField f : this) for (HttpField f : this)
if (f.getHeader()==header) if (f.getHeader()==header)
@ -283,6 +301,7 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public List<String> getValuesList(String name) public List<String> getValuesList(String name)
{ {
lookups++;
final List<String> list = new ArrayList<>(); final List<String> list = new ArrayList<>();
for (HttpField f : this) for (HttpField f : this)
if (f.getName().equalsIgnoreCase(name)) if (f.getName().equalsIgnoreCase(name))
@ -394,6 +413,7 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public List<String> getCSV(HttpHeader header,boolean keepQuotes) public List<String> getCSV(HttpHeader header,boolean keepQuotes)
{ {
lookups++;
QuotedCSV values = null; QuotedCSV values = null;
for (HttpField f : this) for (HttpField f : this)
{ {
@ -417,6 +437,7 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public List<String> getCSV(String name,boolean keepQuotes) public List<String> getCSV(String name,boolean keepQuotes)
{ {
lookups++;
QuotedCSV values = null; QuotedCSV values = null;
for (HttpField f : this) for (HttpField f : this)
{ {
@ -903,6 +924,9 @@ public class HttpFields implements Iterable<HttpField>
public void clear() public void clear()
{ {
System.err.printf("iterations=%d lookups=%d%n",iterations,lookups);
iterations = 0;
lookups = 0;
_size=0; _size=0;
} }

View File

@ -20,14 +20,11 @@ package org.eclipse.jetty.server.jmh;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; 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.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Level;
@ -48,7 +45,7 @@ import org.openjdk.jmh.runner.options.OptionsBuilder;
@Threads(1) @Threads(1)
@Warmup(iterations = 6, time = 2000, timeUnit = TimeUnit.MILLISECONDS) @Warmup(iterations = 6, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 3, 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) @Param({ "12" }) // Chrome has 12 for HTTP/1.1 and 16 for HTTP/2 (including meta headers)
public static int size; public static int size;
@ -165,35 +162,28 @@ public class ListVsTrieBenchmark
@Benchmark @Benchmark
@BenchmarkMode({Mode.Throughput}) @BenchmarkMode({Mode.Throughput})
public long testTreeTrie() throws Exception public long testSortedMap() throws Exception
{ {
Trie<Pair> trie = new TreeTrie<>(); Map<String,List<Pair>> map = new LinkedHashMap<>(size);
fill(p->trie.put(p.key,p)); fill(p->
return test(trie::get); {
} List<Pair> list = new ArrayList<>();
list.add(p);
@Benchmark map.put(p.key.toLowerCase(),list);
@BenchmarkMode({Mode.Throughput}) });
public long testArrayTrie() throws Exception return test(k->
{ {
Trie<Pair> trie = new ArrayTrie<>(length*size); List<Pair> list = map.get(k.toLowerCase());
fill(p->trie.put(p.key,p)); if (list==null || list.isEmpty())
return test(trie::get); return null;
} return list.get(0);
});
@Benchmark
@BenchmarkMode({Mode.Throughput})
public long testMap() throws Exception
{
Map<String,Pair> map = new HashMap<>(size);
fill(p->map.put(p.key.toLowerCase(),p));
return test(k->map.get(k.toLowerCase()));
} }
public static void main(String[] args) throws RunnerException public static void main(String[] args) throws RunnerException
{ {
Options opt = new OptionsBuilder() Options opt = new OptionsBuilder()
.include(ListVsTrieBenchmark.class.getSimpleName()) .include(ListVsMapBenchmark.class.getSimpleName())
// .addProfiler(GCProfiler.class) // .addProfiler(GCProfiler.class)
.forks(1) .forks(1)
.build(); .build();