xtool/contrib/mORMot/SQLite3/Samples/34 - Socket Polling/Project34RTSPproxy.dpr

134 lines
5.2 KiB
ObjectPascal

program Project34RTSPproxy;
{$APPTYPE CONSOLE}
(*
Synopse mORMot framework
Sample 34 - RTSP over HTTP proxy
Implements RTSP stream tunnelling over HTTP.
Purpose of this sample is to illustrate low-level use of TAsynchConnections,
on both Windows and Linux.
The HTTP transport is built from two separate HTTP GET and POST requests
initiated by the client. The server then binds the connections to form a
virtual full-duplex connection.
See https://goo.gl/CX6VA3 for reference material about this horrible, but
widely accepted, Apple's hack.
Version 1.18
- Initial Release
first line of uses clause below must be {$I SynDprUses.inc} to enable FastMM4
*)
uses
{$I SynDprUses.inc}
SysUtils,
SynCommons,
SynTable,
SynLog,
SynCrtSock,
SynBidirSock,
mORMot, // just for object serialization in logs
SynProtoRTSPHTTP;
{$R *.res}
const
CONCURRENT = 500;
// one socket consumes two file descriptors, so each stream opens 6 files;
// under Linux with "ulimit -H -n" = 4096, maximum is 4096/6 = 680 streams:
// add "* hard nofiles 65535" to /etc/security/limits.conf to make it higher
{
Some rough numbers, on various Operating Systems:
CONCURRENT OS API Time Sockets Polled Steps
100 Windows XP select 190 ms 300 200 10
100 Windows Seven select 190 ms 300 200 10
100 Linux poll 200 ms 300 200 10
100 Linux epoll 190 ms 300 200 10
500 Windows XP select 544 ms 1500 1000 10
500 Windows Seven select 990 ms 1500 1000 10
500 Linux poll 380 ms 1500 1000 10
500 Linux epoll 344 ms 1500 1000 10
5000 Windows XP N/A
5000 Windows Seven select 27.61 s 15000 10000 10
5000 Windows Seven WSAPoll 33.70 s 15000 10000 10
5000 Linux poll 2.70 s 15000 10000 10
5000 Linux epoll 2.59 s 15000 10000 10
10000 Windows XP N/A
10000 Windows Seven select 116.32 s 30000 20000 10
10000 Windows Seven WSAPoll 118.23 s 30000 20000 10
10000 Linux poll 9.48 s 30000 20000 10
10000 Linux epoll 9.33 s 30000 20000 10
10000 Linux epoll 65.1 s 30000 20000 100
10000 Linux epoll 10 min 30000 20000 1000
10000 Linux epoll 20 min 30000 20000 2000
Purpose of this test is to create a given number of concurrent GET/POST HTTP
requests, creating one RTSP connection each. Then we run POST and GET small
operations on all connections, in a loop, and check the proper RTSP transfer.
So here polling will have most of the sockets notified with a few pending
bytes proxied during each loop, which is probably the worse case possible.
Above numbers are published to give a performance idea of this micro-benchmark
testing, on various systems and APIs.
All process did take place with logs enabled, on the same physical PC.
Note that the Windows Seven native system (not a VM) may be slow down by its
AntiVirus software, whereas the XP VM did not have any AntiVirus installed.
WSAPoll API was very disappointing: it is slightly slower than plain Select!
In the future, we will eventually uses the IOCP API on Windows, which is told
to be much faster (but also much more difficult to implement). An alternative
may be to use https://github.com/piscisaureus/wepoll (eventually statically
linked), to keep the epoll API and reduce time-to-market.
Memory consumption was similar on all OS and API methods.
In all cases, the Linux VM with poll/epoll did show the best scaling abilities.
The latest test case, creating a lot of traffic, was very stable about its
CPU and memory consumption (most time spent in the kernel), and reported
"reads=22,520,000 (1 GB) writes=2,510,000 (426 MB)" impressive statistics.
}
var
server: TRTSPOverHTTPServer;
timer: TPrecisionTimer;
clients, steps: integer;
begin
if (paramcount = 0) or not TryStrToInt(paramstr(1), clients) then
clients := CONCURRENT
else if (paramcount = 1) or not TryStrToInt(paramstr(2), steps) then
steps := 10;
TSynLog.Family.HighResolutionTimeStamp := true;
TSynLog.Family.PerThreadLog := ptIdentifiedInOnFile;
if steps<200 then
TSynLog.Family.Level := LOG_VERBOSE
else
TSynLog.Family.Level := LOG_STACKTRACE + [sllCustom1];
TSynLog.Family.EchoToConsole := LOG_STACKTRACE + [sllCustom1];
server := TRTSPOverHTTPServer.Create('127.0.0.1', '4999', '4998', TSynLog, nil, nil);
try
//server.Clients.Options := [paoWritePollOnly];
//server.Options := [acoVerboseLog];
writeln(server.ClassName, ' running');
writeln(' performing tests with ', clients, ' concurrent streams using ',
server.Clients.PollRead.PollClass.ClassName, #10);
timer.Start;
server.RegressionTests(nil, clients, steps);
writeln(#10' tests finished in ', timer.Stop);
{$ifdef MSWINDOWS}
writeln('Press [Enter] to close server.');
Readln;
{$endif}
finally
server.Free;
end;
end.