简体   繁体   English

Delphi + Linux + 线程 = 内存

[英]Delphi + Linux + Threads = memory

Have a memory problem.有记忆问题。 Small app (server on few ports, TMS+Indy, Delphi 10.3) is using about 2 Gb of memory (to compare - only 6 Mb under Windows).小应用程序(在几个端口上的服务器,TMS+Indy,Delphi 10.3)正在使用大约 2 Gb 的内存(比较 - 在​​ Windows 下只有 6 Mb)。

So, small test, almost empty console app:所以,小测试,几乎是空的控制台应用程序:

var x: TThread;
begin
    x := TThread.Create(true);

after Create (looking internally - after pthread_create ) "pmap" in Ubuntu says that few memory blocks was added as: 4 kb + 132 kb + 8192 kb + 65404 kb在创建之后(在内部查看 - 在pthread_create之后)Ubuntu 中的“pmap”表示添加的内存块很少:4 kb + 132 kb + 8192 kb + 65404 kb

4 + 132 kb - not too large, ok 4 + 132 kb - 不要太大,可以

8 mb - looks as default stack size for a thread, ok 8 mb - 看起来是线程的默认堆栈大小,好的

but what is 64 Mb????但什么是 64 Mb????

The pmap entry is not the consumed memory, it is the reserved/mapped memory. pmap条目不是消耗的内存,而是保留/映射的内存。

RAM is first reserved/mapped, but actually consumed per page (typically 4KB), the first time a page is accessed by the program. RAM 首先被保留/映射,但实际上每页消耗(通常为 4KB),这是程序第一次访问页面时。

IIRC under Linux, the Delphi memory manager is just a wrapper around the libc malloc free API calls. Linux下的IIRC,Delphi内存管理器只是libc malloc free API调用的包装器。 It is typical for this MM to reserve some per-thread memory pages for the thread-specific memory arena.这个 MM 为线程特定的内存领域保留一些每线程内存页面是典型的。 I guess 64MB is a plausible value.我猜 64MB 是一个合理的值。

So don't be afraid about those numbers.所以不要害怕这些数字。 They don't imply that your RAM chips are consumed eagerly.它们并不意味着您的 RAM 芯片已被急切消耗。 You can have a process reserving GB of memory, but actually only using a few 100MB of hardware RAM - the writeable/private value in pmap .您可以有一个保留 GB 内存的进程,但实际上只使用了几个 100MB 的硬件 RAM - pmapwriteable/private值。 And note that a Delphi app will consume typically lower than any GC program.请注意,Delphi 应用程序的消耗通常低于任何 GC 程序。 :) :)

Update/Proposal after comments: If you need to reduce memory, don't use threads, but non-blocking inet libraries, or a thread pool and a reverse proxy (eg nginx) to maintain the inet connections.评论后更新/建议:如果你需要减少内存,不要使用线程,而是使用非阻塞 inet 库,或者一个线程池和一个反向代理(例如 nginx)来维护 inet 连接。 You can have your server handle HTTP/1.0 in a thread pool, and your nginx proxy maintain HTTP/1.1 or HTTP/2 long standing connections.您可以让您的服务器在线程池中处理 HTTP/1.0,并且您的 nginx 代理维护 HTTP/1.1 或 HTTP/2 长期连接。 If you use Posix sockets between nginx and the service on the loopback, it is very efficient.如果在 nginx 和环回上的服务之间使用 Posix 套接字,则非常高效。 We use this configuration with our mORMot services on high production Linux systems, with great stability.我们将此配置与我们在高生产 Linux 系统上的 mORMot 服务一起使用,具有很高的稳定性。

Update/More Info: This 64MB mapping seems indeed the per-thread-arena reserved mapped memory from malloc.更新/更多信息:这个 64MB 映射似乎确实是来自 malloc 的 per-thread-arena 保留映射内存。 Check https://codearcana.com/posts/2016/07/11/arena-leak-in-glibc.html and MALLOC_ARENA_MAX as detailed in https://siddhesh.in/posts/malloc-per-thread-arenas-in-glibc.html检查https://codearcana.com/posts/2016/07/11/arena-leak-in-glibc.html和 MALLOC_ARENA_MAX,详见https://siddhesh.in/posts/malloc-per-thread-arenas-in -glibc.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM