-
-
Notifications
You must be signed in to change notification settings - Fork 137
/
Copy pathhttpServerRaw.dpr
173 lines (148 loc) · 4.66 KB
/
httpServerRaw.dpr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
program httpServerRaw;
{
Some numbers on my dev PC (Core i5-13500 running Debian 12 at that time):
usr@pc:~ sudo apt install wrk
usr@pc:~ wrk -c 1024 -t 8 http://localhost:8888/echo
Running 10s test @ http://localhost:8888/echo
8 threads and 1024 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 612.25us 566.42us 31.92ms 99.69%
Req/Sec 184.44k 12.24k 217.95k 71.12%
14680687 requests in 10.10s, 2.16GB read
Requests/sec: 1453501.13
Transfer/sec: 219.01MB
usr@pc:~ sudo apt install apache2-utils
usr@pc:~ ab -t 20 -n 100000 -c 1000 -k http://localhost:8888/echo
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Benchmarking localhost (be patient)
Finished 100000 requests
Server Software: mORMot2
Server Hostname: localhost
Server Port: 8888
Document Path: /echo
Document Length: 53 bytes
Concurrency Level: 1000
Time taken for tests: 0.313 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 100000
Total transferred: 18200000 bytes
HTML transferred: 5300000 bytes
Requests per second: 319062.72 [#/sec] (mean)
Time per request: 3.134 [ms] (mean)
Time per request: 0.003 [ms] (mean, across all concurrent requests)
Transfer rate: 56708.41 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.0 0 17
Processing: 1 3 0.2 3 17
Waiting: 0 3 0.2 3 5
Total: 1 3 1.1 3 22
}
{$I mormot.defines.inc}
{$ifdef OSWINDOWS}
{$apptype console}
{$R ..\..\src\mormot.win.default.manifest.res}
{$endif OSWINDOWS}
uses
{$I mormot.uses.inc} // may include mormot.core.fpcx64mm.pas
sysutils,
classes,
mormot.core.base,
mormot.core.os,
mormot.core.rtti,
mormot.core.log,
mormot.core.text,
mormot.net.sock,
mormot.net.http,
mormot.net.server,
mormot.net.async;
type
TSimpleHttpAsyncServer = class
private
fHttpServer: THttpServerSocketGeneric;
protected
// this is where the process would take place
function DoOnRequest(Ctxt: THttpServerRequestAbstract): cardinal;
public
constructor Create;
destructor Destroy; override;
end;
{ TSimpleHttpAsyncServer }
var
RequestID: integer;
function TSimpleHttpAsyncServer.DoOnRequest(Ctxt: THttpServerRequestAbstract): cardinal;
begin
{ if fHttpServer is THttpAsyncServer then
with THttpAsyncServer(fHttpServer) do
if Assigned(Async.Log) then
Async.Log.Add.Log(sllInfo, 'DoOnRequest %', [Ctxt], self);}
if IsPost(Ctxt.Method) then
begin
// POST = echo
Ctxt.OutContent := Ctxt.InContent;
Ctxt.OutContentType := TEXT_CONTENT_TYPE;
end
else
// GET or HEAD
Ctxt.SetOutText('got % request #% from connection #%',
[Ctxt.Url, CardinalToHexShort(InterlockedIncrement(RequestID)),
CardinalToHexShort(Ctxt.ConnectionID)]);
// CardinalToHexShort() to keep the same length (as request by ab)
result := HTTP_SUCCESS;
end;
constructor TSimpleHttpAsyncServer.Create;
begin
inherited Create;
fHttpServer := THttpAsyncServer.Create(
'8888', nil, nil, '', SystemInfo.dwNumberOfProcessors + 1, 30000,
[hsoNoXPoweredHeader,
hsoNoStats,
hsoHeadersInterning,
hsoThreadSmooting
//, hsoLogVerbose
]);
//writeln('DropPriviledges=', DropPriviledges('abouchez'));
fHttpServer.HttpQueueLength := 100000; // needed e.g. from wrk/ab benchmarks
fHttpServer.OnRequest := DoOnRequest;
fHttpServer.WaitStarted; // raise exception e.g. on binding issue
end;
destructor TSimpleHttpAsyncServer.Destroy;
begin
fHttpServer.Free;
inherited Destroy;
end;
var
simpleServer: TSimpleHttpAsyncServer;
begin
with TSynLog.Family do
begin
Level :=
//LOG_VERBOSE +
LOG_FILTER[lfErrors];
//EchoToConsole := Level;
PerThreadLog := ptIdentifiedInOneFile;
HighResolutionTimestamp := true;
AutoFlushTimeOut := 1;
end;
simpleServer := TSimpleHttpAsyncServer.Create();
try
{$I-}
writeln;
TextColor(ccLightGreen);
writeln(simpleServer.fHttpServer.ClassName, ' running on localhost:8888'#10);
TextColor(ccWhite);
writeln('try curl http://localhost:8888/echo'#10);
TextColor(ccLightGray);
writeln('Press [Enter] to quit'#10);
TextColor(ccCyan);
ConsoleWaitForEnterKey;
writeln(ObjectToJson(simpleServer.fHttpServer, [woHumanReadable]));
TextColor(ccLightGray);
{$ifdef FPC_X64MM}
WriteHeapStatus(' ', 16, 8, {compileflags=}true);
{$endif FPC_X64MM}
finally
simpleServer.Free;
end;
end.