134 lines
5.2 KiB
ObjectPascal
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.
|