misc optimisation of http2 field creation
This commit is contained in:
parent
636c7eaeae
commit
d7f2c42e2d
|
@ -69,9 +69,14 @@ public class HttpField
|
|||
return _value;
|
||||
}
|
||||
|
||||
public int getIntValue()
|
||||
{
|
||||
return Integer.valueOf(_value);
|
||||
}
|
||||
|
||||
public long getLongValue()
|
||||
{
|
||||
return StringUtil.toLong(_value);
|
||||
return Long.valueOf(_value);
|
||||
}
|
||||
|
||||
public String[] getValues()
|
||||
|
@ -416,21 +421,65 @@ public class HttpField
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static class IntValueHttpField extends HttpField
|
||||
{
|
||||
final int _int;
|
||||
|
||||
public IntValueHttpField(HttpHeader header, String value, int intValue)
|
||||
{
|
||||
super(header,value);
|
||||
_int=intValue;
|
||||
}
|
||||
|
||||
public IntValueHttpField(HttpHeader header, String value)
|
||||
{
|
||||
this(header,value,Integer.valueOf(value));
|
||||
}
|
||||
|
||||
public IntValueHttpField(HttpHeader header, int value)
|
||||
{
|
||||
this(header,Integer.toString(value),value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntValue()
|
||||
{
|
||||
return _int;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongValue()
|
||||
{
|
||||
return _int;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LongValueHttpField extends HttpField
|
||||
{
|
||||
final long _long;
|
||||
|
||||
public LongValueHttpField(HttpHeader header, long value)
|
||||
public LongValueHttpField(HttpHeader header, String value, long longValue)
|
||||
{
|
||||
super(header,Long.toString(value));
|
||||
_long=value;
|
||||
super(header,value);
|
||||
_long=longValue;
|
||||
}
|
||||
|
||||
public LongValueHttpField(HttpHeader header, String value)
|
||||
{
|
||||
super(header,value);
|
||||
_long=StringUtil.toLong(value);
|
||||
this(header,value,StringUtil.toLong(value));
|
||||
}
|
||||
|
||||
public LongValueHttpField(HttpHeader header,long value)
|
||||
{
|
||||
this(header,Long.toString(value),value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getIntValue()
|
||||
{
|
||||
return (int)_long;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -119,20 +119,20 @@ public class HpackContext
|
|||
switch(i)
|
||||
{
|
||||
case 2:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.GET));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.GET));
|
||||
break;
|
||||
case 3:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.POST));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.POST));
|
||||
break;
|
||||
case 6:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTP));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTP));
|
||||
break;
|
||||
case 7:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTPS));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTPS));
|
||||
break;
|
||||
case 8:
|
||||
case 11:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
break;
|
||||
|
||||
case 9:
|
||||
|
@ -140,7 +140,7 @@ public class HpackContext
|
|||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -429,6 +429,7 @@ public class HpackContext
|
|||
public static class StaticEntry extends Entry
|
||||
{
|
||||
private final byte[] _huffmanValue;
|
||||
private final byte _encodedField;
|
||||
|
||||
StaticEntry(int index,HttpField field)
|
||||
{
|
||||
|
@ -450,6 +451,8 @@ public class HpackContext
|
|||
}
|
||||
else
|
||||
_huffmanValue=null;
|
||||
|
||||
_encodedField=(byte)(0x80|index);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -463,6 +466,11 @@ public class HpackContext
|
|||
{
|
||||
return _huffmanValue;
|
||||
}
|
||||
|
||||
public byte getEncodedField()
|
||||
{
|
||||
return _encodedField;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class HpackDecoder
|
||||
{
|
||||
public static final Logger LOG = Log.getLogger(HpackDecoder.class);
|
||||
public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 = new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
|
||||
public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 =
|
||||
new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
|
||||
|
||||
private final HpackContext _context;
|
||||
private final MetaDataBuilder _builder;
|
||||
|
@ -191,41 +192,26 @@ public class HpackDecoder
|
|||
HttpField field;
|
||||
if (header==null)
|
||||
{
|
||||
// just make a normal field and bypass header name lookup
|
||||
field = new HttpField(null,name,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// might be worthwhile to create a value HttpField if it is indexed
|
||||
// and/or of a type that may be looked up multiple times.
|
||||
switch(header)
|
||||
{
|
||||
case C_METHOD:
|
||||
HttpMethod method=HttpMethod.CACHE.get(value);
|
||||
if (method!=null)
|
||||
field = new StaticValueHttpField(HttpHeader.C_METHOD,method.asString(),method);
|
||||
else
|
||||
field = new AuthorityHttpField(value);
|
||||
break;
|
||||
|
||||
case C_STATUS:
|
||||
Integer code = Integer.valueOf(value);
|
||||
field = new StaticValueHttpField(HttpHeader.C_STATUS,value,code);
|
||||
break;
|
||||
|
||||
case C_SCHEME:
|
||||
HttpScheme scheme=HttpScheme.CACHE.get(value);
|
||||
if (scheme!=null)
|
||||
field = new StaticValueHttpField(HttpHeader.C_SCHEME,scheme.asString(),scheme);
|
||||
if (indexed)
|
||||
field = new HttpField.IntValueHttpField(header,value);
|
||||
else
|
||||
field = new AuthorityHttpField(value);
|
||||
field = new HttpField(header,name,value);
|
||||
break;
|
||||
|
||||
case C_AUTHORITY:
|
||||
field = new AuthorityHttpField(value);
|
||||
break;
|
||||
|
||||
case C_PATH:
|
||||
field = new HttpField(HttpHeader.C_PATH,value);
|
||||
break;
|
||||
|
||||
case CONTENT_LENGTH:
|
||||
if ("0".equals(value))
|
||||
field = CONTENT_LENGTH_0;
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.jetty.http.HttpScheme;
|
|||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry;
|
||||
import org.eclipse.jetty.io.ByteBufferPool.Lease;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
@ -78,6 +79,7 @@ public class HpackEncoder
|
|||
}
|
||||
|
||||
private final HpackContext _context;
|
||||
private final boolean _debug;
|
||||
private int _remoteMaxHeaderTableSize;
|
||||
private int _localMaxHeaderTableSize;
|
||||
|
||||
|
@ -96,6 +98,7 @@ public class HpackEncoder
|
|||
_context=new HpackContext(remoteMaxHeaderTableSize);
|
||||
_remoteMaxHeaderTableSize=remoteMaxHeaderTableSize;
|
||||
_localMaxHeaderTableSize=localMaxHeaderTableSize;
|
||||
_debug=LOG.isDebugEnabled();
|
||||
}
|
||||
|
||||
public HpackContext getContext()
|
||||
|
@ -154,15 +157,13 @@ public class HpackEncoder
|
|||
int code=response.getStatus();
|
||||
HttpField status = code<__status.length?__status[code]:null;
|
||||
if (status==null)
|
||||
status=new HttpField(HttpHeader.C_STATUS,Integer.toString(code));
|
||||
status=new HttpField.IntValueHttpField(HttpHeader.C_STATUS,code);
|
||||
encode(buffer,status);
|
||||
}
|
||||
|
||||
// Add all the other fields
|
||||
for (HttpField field : metadata)
|
||||
{
|
||||
encode(buffer,field);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(String.format("CtxTbl[%x] encoded %d octets",_context.hashCode(), buffer.position() - pos));
|
||||
|
@ -179,7 +180,7 @@ public class HpackEncoder
|
|||
|
||||
private void encode(ByteBuffer buffer, HttpField field)
|
||||
{
|
||||
final int p=LOG.isDebugEnabled()?buffer.position():-1;
|
||||
final int p=_debug?buffer.position():-1;
|
||||
|
||||
String encoding=null;
|
||||
|
||||
|
@ -190,16 +191,24 @@ public class HpackEncoder
|
|||
if (entry!=null)
|
||||
{
|
||||
// Known field entry, so encode it as indexed
|
||||
int index=_context.index(entry);
|
||||
if (p>=0)
|
||||
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,index);
|
||||
if (entry.isStatic())
|
||||
{
|
||||
buffer.put(((StaticEntry)entry).getEncodedField());
|
||||
if (_debug)
|
||||
encoding="IdxFieldS1";
|
||||
}
|
||||
else
|
||||
{
|
||||
int index=_context.index(entry);
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,index);
|
||||
if (_debug)
|
||||
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown field entry, so we will have to send literally.
|
||||
|
||||
final Entry name;
|
||||
final boolean indexed;
|
||||
final boolean never_index;
|
||||
|
@ -211,6 +220,7 @@ public class HpackEncoder
|
|||
if (header==null)
|
||||
{
|
||||
name = _context.get(field.getName());
|
||||
|
||||
// has the custom header name been seen before?
|
||||
if (name==null)
|
||||
{
|
||||
|
@ -226,7 +236,7 @@ public class HpackEncoder
|
|||
else
|
||||
{
|
||||
// known custom name, but unknown value.
|
||||
// This is probably a custom field with changing value, so don't index now.
|
||||
// This is probably a custom field with changing value, so don't index.
|
||||
indexed=false;
|
||||
never_index=false;
|
||||
huffman=true;
|
||||
|
@ -267,7 +277,7 @@ public class HpackEncoder
|
|||
}
|
||||
}
|
||||
|
||||
if (p>=0)
|
||||
if (_debug)
|
||||
{
|
||||
encoding="Lit"+
|
||||
((name==null)?"HuffN":("IdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(bits,_context.index(name)))))+
|
||||
|
@ -316,7 +326,7 @@ public class HpackEncoder
|
|||
_context.add(field);
|
||||
}
|
||||
|
||||
if (p>=0)
|
||||
if (_debug)
|
||||
{
|
||||
int e=buffer.position();
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -72,9 +72,9 @@ public class MetaDataBuilder
|
|||
if (_size>_maxSize)
|
||||
throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_size+">"+_maxSize);
|
||||
|
||||
if (field instanceof StaticValueHttpField)
|
||||
if (field instanceof StaticTableHttpField)
|
||||
{
|
||||
StaticValueHttpField value = (StaticValueHttpField)field;
|
||||
StaticTableHttpField value = (StaticTableHttpField)field;
|
||||
switch(field.getHeader())
|
||||
{
|
||||
case C_STATUS:
|
||||
|
@ -98,7 +98,7 @@ public class MetaDataBuilder
|
|||
switch(field.getHeader())
|
||||
{
|
||||
case C_STATUS:
|
||||
_status=Integer.parseInt(field.getValue());
|
||||
_status=field.getIntValue();
|
||||
break;
|
||||
|
||||
case C_METHOD:
|
||||
|
@ -114,6 +114,7 @@ public class MetaDataBuilder
|
|||
break;
|
||||
|
||||
case HOST:
|
||||
// :authority fields must come first. If we have one, ignore the host header as far as authority goes.
|
||||
if (_authority==null)
|
||||
_authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
|
||||
_fields.add(field);
|
||||
|
|
|
@ -23,19 +23,11 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public class StaticValueHttpField extends HttpField
|
||||
public class StaticTableHttpField extends HttpField
|
||||
{
|
||||
private final Object _value;
|
||||
|
||||
public StaticValueHttpField(HttpHeader header,String name, String valueString, Object value)
|
||||
{
|
||||
super(header,name,valueString);
|
||||
if (value==null)
|
||||
throw new IllegalArgumentException();
|
||||
_value=value;
|
||||
}
|
||||
|
||||
public StaticValueHttpField(HttpHeader header,String valueString, Object value)
|
||||
public StaticTableHttpField(HttpHeader header,String valueString, Object value)
|
||||
{
|
||||
super(header,header.asString(),valueString);
|
||||
if (value==null)
|
||||
|
@ -43,7 +35,7 @@ public class StaticValueHttpField extends HttpField
|
|||
_value=value;
|
||||
}
|
||||
|
||||
public StaticValueHttpField(String name, String valueString, Object value)
|
||||
public StaticTableHttpField(String name, String valueString, Object value)
|
||||
{
|
||||
super(name,valueString);
|
||||
if (value==null)
|
Loading…
Reference in New Issue