1 module HttpBenchmark; 2 3 import hunt.http.codec.http.decode.HttpParser; 4 import hunt.http.codec.http.model; 5 // import hunt.http.codec.http.model.HttpComplianceSection; 6 7 import hunt.lang.exception; 8 import hunt.lang.Charset; 9 10 import hunt.container.BufferUtils; 11 import hunt.container.ByteBuffer; 12 import hunt.container.ArrayList; 13 import hunt.container.List; 14 15 import hunt.logging; 16 17 import std.conv; 18 import std.range; 19 import std.stdio; 20 21 alias State = HttpParser.State; 22 23 24 class HttpBenchmark { 25 26 private string _host; 27 private int _port; 28 private string _bad; 29 private string _content; 30 private string _methodOrVersion; 31 private string _uriOrStatus; 32 private string _versionOrReason; 33 private List!HttpField _fields; 34 private List!HttpField _trailers; 35 private string[] _hdr; 36 private string[] _val; 37 private int _headers; 38 private bool _early; 39 private bool _headerCompleted; 40 private bool _messageCompleted; 41 private List!HttpComplianceSection _complianceViolation; 42 43 this() { 44 _fields = new ArrayList!HttpField(); 45 _trailers = new ArrayList!HttpField(); 46 _complianceViolation = new ArrayList!HttpComplianceSection(); 47 HttpParser.RequestHandler handler = new Handler(); 48 parser = new HttpParser(handler); 49 } 50 private HttpParser parser; 51 52 void benchmark(int number = 10) { 53 import core.time; 54 import std.datetime; 55 import hunt.datetime; 56 MonoTime startTime = MonoTime.currTime; 57 foreach(j ; 0..number) { 58 testParseRequest(); 59 } 60 Duration timeElapsed = MonoTime.currTime - startTime; 61 size_t t = timeElapsed.total!(TimeUnit.Microsecond)(); 62 tracef("time consuming (%d), total: %d microseconds, avg: %d microseconds", number, t, t/number); 63 } 64 65 void initialize() { 66 _bad = null; 67 _host = null; 68 _content = null; 69 _methodOrVersion = null; 70 _uriOrStatus = null; 71 _versionOrReason = null; 72 _hdr = null; 73 _val = null; 74 _headers = 0; 75 _headerCompleted = false; 76 _messageCompleted = false; 77 _complianceViolation.clear(); 78 } 79 80 void testParseRequest() { 81 initialize(); 82 string str = `GET /plaintext HTTP/1.1 83 cache-control: no-cache 84 Postman-Token: f290cab4-ac2b-46c7-9db8-ca07f5758989 85 User-Agent: PostmanRuntime/7.4.0 86 Accept: */* 87 Host: 127.0.0.1:8080 88 accept-encoding: gzip, deflate 89 Connection: keep-alive 90 91 `; 92 ByteBuffer buffer = BufferUtils.toBuffer(str); 93 // HttpParser.RequestHandler handler = new Handler(); 94 // parser = new HttpParser(handler); 95 parser.parseNext(buffer); 96 parser.reset(); 97 } 98 99 100 private class Handler : HttpParser.RequestHandler, HttpParser.ResponseHandler, HttpParser.ComplianceHandler { 101 102 bool content(ByteBuffer buffer) { 103 if (_content == null) 104 _content = ""; 105 string c = BufferUtils.toString(buffer); 106 _content = _content ~ c; 107 buffer.position(buffer.limit()); 108 return false; 109 } 110 111 112 bool startRequest(string method, string uri, HttpVersion ver) { 113 version (HUNT_DEBUG) { 114 tracef("server received the request line, %s, %s, %s", method, uri, ver); 115 } 116 _fields.clear(); 117 _trailers.clear(); 118 _headers = -1; 119 _hdr = new string[10]; 120 _val = new string[10]; 121 _methodOrVersion = method; 122 _uriOrStatus = uri; 123 _versionOrReason = ver == HttpVersion.Null ? null : ver.asString(); 124 _messageCompleted = false; 125 _headerCompleted = false; 126 _early = false; 127 return false; 128 } 129 130 131 void parsedHeader(HttpField field) { 132 _fields.add(field); 133 _hdr[++_headers] = field.getName(); 134 _val[_headers] = field.getValue(); 135 136 if (typeid(field) == typeid(HostPortHttpField)) { 137 HostPortHttpField hpfield = cast(HostPortHttpField) field; 138 _host = hpfield.getHost(); 139 _port = hpfield.getPort(); 140 } 141 } 142 143 144 bool headerComplete() { 145 _content = null; 146 _headerCompleted = true; 147 return false; 148 } 149 150 151 void parsedTrailer(HttpField field) { 152 _trailers.add(field); 153 } 154 155 156 bool contentComplete() { 157 return false; 158 } 159 160 161 bool messageComplete() { 162 _messageCompleted = true; 163 return true; 164 } 165 166 167 void badMessage(BadMessageException failure) { 168 string reason = failure.getReason(); 169 _bad = reason.empty ? failure.getCode().to!string : reason; 170 } 171 172 void badMessage(int status, string reason) { 173 174 } 175 176 177 bool startResponse(HttpVersion ver, int status, string reason) { 178 _fields.clear(); 179 _trailers.clear(); 180 _methodOrVersion = ver.asString(); 181 _uriOrStatus = status.to!string; 182 _versionOrReason = reason; 183 _headers = -1; 184 _hdr = new string[10]; 185 _val = new string[10]; 186 _messageCompleted = false; 187 _headerCompleted = false; 188 return false; 189 } 190 191 192 void earlyEOF() { 193 _early = true; 194 } 195 196 197 int getHeaderCacheSize() { 198 return 512; 199 } 200 201 202 void onComplianceViolation(HttpCompliance compliance, HttpComplianceSection violation, string reason) { 203 _complianceViolation.add(violation); 204 } 205 } 206 }