For performance reasons, I have rewritten the ISAPI extension DLL (see my previous post) which simulates HTTP 1.1 GET with range specified.
The DLL now uses the IIS function HSE_REQ_TRANSMIT_FILE which is asynchronous and performance-wise optimized for sending files to clients.
Note: It helps to specify the FILE_FLAG_SEQUENTIAL_SCAN flag when opening the file. For asynchronous I/O operations, the FILE_FLAG_OVERLAPPED flag has to be specified.
For this purpose, I decided not to use Delphi's Web Application framework and wrote a plain ISAPI DLL instead.
Another modification that helped was not to use HTTP GET with parameters encoded directly in the URL. Instead, I now use HTTP POST with parameters encoded in binary POST data. DataSnap uses the same approach and it seems to be the most efficient one.
Unfortunately, our client applications are currently designed so that they send a lot of HTTP requests returning small packets of data. In such scenarios, it's better to specify HSE_IO_NODELAY flag in your HSE_REQ_TRANSMIT_FILE calls. Note: You can also use this flag with the WriteClient function (although it's not mentioned directly in its documentation).
This flag turns off the TCP nagling optimization (enabled by default) which, in case of small packets with Keep-alive connections, actually degrades performance because of the 200 ms timeout.
My subjective ;-) feeling is that the DLL's performance is now approximately the same as that of the standard HTTP 1.1 GET with range specified. I don't have enough statistical data yet to prove or disprove that speculation.
I have also finished a very simple ISAPI Filter DLL, whose only purpose is to be able to define some URL aliases. Again, some people have weird network configurations where their proxies forbid usage of URLs containing the .dll extension. The ISAPI filter modifies the incoming headers before IIS processes the request, so it can translate a URL like http://hostname/httpsrvr to http://hostname/scripts/httpsrvr.dll. Currently, it reads the alias definitions from the registry every time it's called by IIS, so the aliases are configurable without having to restart IIS. So far, this doesn't seem to adversely affect the performance.