Delphi-Cross-Socket
Delphi-Cross-Socket copied to clipboard
feature request
hello Souledge, I propose a little modify to raise the throughput of HTTP GET files, using NT TransmitFile() async over IOCOMP.
https://docs.microsoft.com/it-it/windows/desktop/api/mswsock/nf-mswsock-transmitfile
TF_USE_KERNEL_APC and TF_WRITE_BEHIND will make sendfile completely asynchronous with a callback when completed or failed (using overlapped IOCP binding), is the same way used in IIS https://docs.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms525816%28v%3dvs.90%29
before call transmitfile use this flag when open the file handle that the TransmitFile function transmits. Since the operating system reads the file data sequentially, you can improve caching performance by opening the handle with FILE_FLAG_SEQUENTIAL_SCAN
perhaps you can do a DEFINE USEKERNEL, $IFDEF WIN64 $IFDEF USEKERNEL -> then use this way, we will have a lot better throughput thanks to the kernel cache and async callback
目前的 SendFile 是可以支持分块压缩发送的,如果改用 TransmitFile,那就无法分块压缩,而且改造起来也颇费时间
我觉得你应该换个思路,你的目的是为了提高发送文件的效率,即便改用 TransmitFile,也只是减少了“用户/内核模式”的切换,TransmitFile 也还是需要从磁盘去读取数据,内存的读写速度远高于磁盘,更高效的方式是实现一个文件缓存的机制,常用的直接从内存中读取发送,这一定比 TransmitFile 效率更高,而且更通用,各平台通吃,还支持分块压缩
不过我暂时实在没啥时间去做这件事,你要是有兴趣的话可以尝试修改,我可以把你修改的代码合并
do you use TFileStream VCL class doing buffering of .READ .WRITE? if the HTTP is NOT chunked-encoding you should benefit of TransmitFile async, put a pointer to the header https://docs.microsoft.com/it-it/windows/desktop/api/mswsock/ns-mswsock-_transmit_file_buffers I sure you, using FLAG_SEQUENTIAL_READ you get a lot better thoughput and scalability, and use the cache of the kernel, way faster than a usermode memory
in the past I did a cache for files, yyou should check for size and for age, well for small files is ok, but for today json blobs, img, video, etc. transmitfile is a must to do
also consider to use TBufferedStream if you want stay with Delphi classes, it's faster for files > 4kb
对于很大的文件,的确不适合放到内存中,这种情况使用 TransmitFile 的效率提升应该很可观
由于 SendFile 每次都会重新打开文件,所以 TBufferedStream 其实并不适用
thanks for your precious support in low level how you send a file? what are the steps? in which files I can see your methods? I try only to see if I can help to better this great library
我这套库,就在我们公司的生产环境中运行,用于编写后台的 REST 接口,发送文件也就是库里面的 SendFile,并没有觉得效率不够用,可能我们的应用场景还没有出现需要频繁发送文件的情况吧,所以并没有针对性的做特别优化
如果你有兴趣,欢迎进行改进
yes, I will implement TransmitFile in which units you manage the HTTP answer, chuck-encoding checking, so I can do this change? Also I will provide a patched System.Zlib with Intel SIMD version, making 5x faster the deflate this library can become the new standard in the Delphi community for server applications
就是直接使用 Net.CrossHttpServer.pas 单元呀,使用 ICrossHttpServer.Get Put Post Delete 生成各种 REST 接口的应答
你如果要做改进的话,直接修改 TCrossHttpResponse.SendFile 即可
I see in some places potentially leaks in some conditions, also can be possible avoid mem copy superflous ops avoiding @uniquestring or similar conversion using direct pointers instead of Pchars[indexed]
wish to have some time to bring some changes, thanks
ok the next week I'll implement TransmitFile() and will see the performance difference, cu soon :-)
if you wish add me to QQ, my QQ id is BOB74 account number 3470314349
IOCP support File IOs. For higher performance, All File RW should use IOCP. Delphi Cross Socket is only focused on network IO, To support File IO and network IO in the same IOCP queue, you should reconstruct this framework.
Probably is enough to do little changes using TransmitFile API over the same IOCOMP. I have no time now, maybe next month will do it.