Delphi TIdHTTPServer逐渐增加内存
Delphi TIdHTTPServer gradually increase memory
我有一个在 XE6 上使用 TIdHTTPServer 构建的服务器(默认 Indy 10 安装和组件上的默认选项设置)用于文件下载:
procedure CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
AResponseInfo.ContentStream := TFileStream.Create('C:\MyFile.Exe', fmOpenRead or fmShareDenyNone);
end;
在许多个月(6 个月)和大量请求(少于或多于 1'000'000)之后,服务器进程增加了私人内存(在任务管理器上)超过 50 MB。
TIdHTTPServer 是否泄漏内存?
更新:
在
的小型测试应用程序中
initialization
ReportMemoryLeaksOnShutdown := True;
不漏水
我也尝试过使用 FastMM dll,这是报告(我的 SO 是意大利语)
--------------------------------2015/11/2 14:52:38-------------------------
Leak di un blocco. La dimensione è: 20
Questo blocco è stato allocato dal thread 0x730, e lo stack trace
(indirizzo restituito) in quel momento era: 40678A 4087AF 408ED6
640996
[IdThreadSafe][IdThreadSafe][IdThreadSafe..TIdThreadSafeObjectList][144]
6C996F
[IdGlobalProtocols.pas][IdGlobalProtocols][IdGlobalProtocols.IdGlobalProtocols][4743]
6C9984
[IdGlobalProtocols.pas][IdGlobalProtocols][IdGlobalProtocols.IdGlobalProtocols][4744]
6C99D5 [IdThread.pas][IdThread][IdThread.IdThread][732] 409F80 409FEC
40F4B7 [SysInit.pas][SysInit][SysInit.@InitExe][1191] 6CA144
[WMain.pas][WMain][WMain.WMain][295] 75C6337A [BaseThreadInitThunk]
77AF9882 [Unknown function at RtlInitializeExceptionChain] 77AF9855
[Unknown function at RtlInitializeExceptionChain]
Il blocco è attualmente usato da una istanza della classe:
TIdThreadSafeInteger
Il numero di allocazione è: 475
Dump della memoria di 256 byte partendo dall'indirizzo del puntatore
7EF3D2C0: FC 02 64 00 60 0F FA 7E 00 00 00 00 00 00 00 00 0B 12 7A 17
80 80 80 80 00 00 00 00 B1 D5 F3 7E 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 E2 01 00 00 8A 67 40 00 AF 87 40 00 D6 8E 40 00 A4 88
40 00 8D 85 D2 00 BA 85 D2 00 15 FC 4C 00 9E FB 4C 00 05 43 4B 00 ED
91 66 00 5D 9A 6C 00 80 9F 40 00 EC 9F 40 00 B7 F4 40 00 44 A1 6C 00
7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00
00 30 07 00 00 30 07 00 00 A6 67 40 00 CD 87 40 00 21 8F 40 00 C6 88
40 00 D3 88 40 00 38 FD 4C 00 D3 88 40 00 62 43 4B 00 D3 88 40 00 3E
92 66 00 14 9F 40 00 14 A3 40 00 87 A1 6C 00 7A 33 C6 75 82 98 AF 77
55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 08 00 00 00 BC 69 4E 00 45 BC CB 52 A0 41 D3 00 80 80 80 80 BA 43
34 AD 80 80 80 80 ü . d . ` . ú ~ . . . . . . . . . .
z . € € € € . . . . ± Õ ó ~ . . . . . . . . . .
. . . . . . â . . . Š g @ . ¯ ‡ @ . Ö Ž @ . ¤ ˆ
@ . … Ò . º … Ò . . ü L . ž û L . . C K . í ‘
f . ] š l . € Ÿ @ . ì Ÿ @ . · ô @ . D ¡ l . z 3
Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . 0 .
. . 0 . . . ¦ g @ . Í ‡ @ . ! @ . Æ ˆ @ . Ó ˆ
@ . 8 ý L . Ó ˆ @ . b C K . Ó ˆ @ . > ’ f . . Ÿ
@ . . £ @ . ‡ ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . .
. . . . . . . . . . . . . . . . . . . . . . ¼ i
N . E ¼ Ë R A Ó . € € € € º C 4 € € € €
--------------------------------2015/11/2 14:52:38-------------------------
Leak di un blocco. La dimensione è: 36
Questo blocco è stato allocato dal thread 0x730, e lo stack trace
(indirizzo restituito) in quel momento era: 40678A 4087AF 408ED6
440106
[System.SyncObjs.pas][System][System.SyncObjs.TEvent.Create][827]
412FEA
[Winapi.Windows.pas][Winapi][Winapi.Windows.GetProcAddress][34295]
6C98AB [IdStack.pas][IdStack][IdStack.IdStack][1138] 409F80 409FEC
40F4B7 [SysInit.pas][SysInit][SysInit.@InitExe][1191] 6CA144
[WMain.pas][WMain][WMain.WMain][295] 75C6337A [BaseThreadInitThunk]
77AF9882 [Unknown function at RtlInitializeExceptionChain] 77AF9855
[Unknown function at RtlInitializeExceptionChain]
Il blocco è attualmente usato da una istanza della classe:
TIdCriticalSection
Il numero di allocazione è: 458
Dump della memoria di 256 byte partendo dall'indirizzo del puntatore
7EFA0A60: 90 D7 60 00 C0 9B 8A 00 FF FF FF FF 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 16 CC A7 B0 80 80 80 80 00 00 00
00 91 0B FA 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D1 01
00 00 8A 67 40 00 A3 A4 40 00 D4 A6 40 00 D1 E3 40 00 0E B4 AF 77 B5
33 AF 77 E3 2F AF 77 FA FA AD 77 2B D7 C6 75 48 D7 C6 75 BA D6 C6 75
7E D6 C6 75 91 D6 C6 75 32 FA AD 77 1A D6 C6 75 04 D4 C6 75 FE D5 C6
75 34 47 B1 77 A1 47 B1 77 09 F2 AE 77 74 F2 AE 77 30 07 00 00 30 07
00 00 A6 67 40 00 5D A5 40 00 41 A1 40 00 4B B4 62 00 14 9F 40 00 14
A3 40 00 87 A1 6C 00 7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00 00 B0 04
02 00 70 93 97 CA × ` . À › Š . ÿ ÿ ÿ ÿ . . . . . .
. . . . . . . . . . . . . . . Ì § ° € € € € . .
. . ‘ . ú ~ . . . . . . . . . . . . . . . . Ñ .
. . Š g @ . £ ¤ @ . Ô ¦ @ . Ñ ã @ . . ´ ¯ w µ 3
¯ w ã / ¯ w ú ú w + × Æ u H × Æ u º Ö Æ u ~ Ö
Æ u ‘ Ö Æ u 2 ú w . Ö Æ u . Ô Æ u þ Õ Æ u 4 G
± w ¡ G ± w . ò ® w t ò ® w 0 . . . 0 . . . ¦ g
@ . ] ¥ @ . A ¡ @ . K ´ b . . Ÿ @ . . £ @ . ‡ ¡
l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . " . . . ° . . . p “ — Ê
--------------------------------2015/11/2 14:52:38-------------------------
Leak di un blocco. La dimensione è: 36
Questo blocco è stato allocato dal thread 0x730, e lo stack trace
(indirizzo restituito) in quel momento era: 40678A 4087AF 408ED6
440106
[System.SyncObjs.pas][System][System.SyncObjs.TEvent.Create][827]
4087B8 6409AF
[IdThreadSafe][IdThreadSafe][IdThreadSafe..TIdThreadSafeObjectList][144]
6C99D5 [IdThread.pas][IdThread][IdThread.IdThread][732] 409F80 409FEC
40F4B7 [SysInit.pas][SysInit][SysInit.@InitExe][1191] 6CA144
[WMain.pas][WMain][WMain.WMain][295] 75C6337A [BaseThreadInitThunk]
77AF9882 [Unknown function at RtlInitializeExceptionChain] 77AF9855
[Unknown function at RtlInitializeExceptionChain]
Il blocco è attualmente usato da una istanza della classe:
TIdCriticalSection
Il numero di allocazione è: 476
Dump della memoria di 256 byte partendo dall'indirizzo del puntatore
7EFA0F60: 90 D7 60 00 E8 9B 8A 00 FF FF FF FF 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 76 7F C8 17 80 80 80 80 00 00 00
00 91 10 FA 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF 01
00 00 8A 67 40 00 A3 A4 40 00 30 A9 40 00 26 6D 4B 00 81 68 4B 00 12
3B 66 00 2D 9A 6C 00 80 9F 40 00 EC 9F 40 00 B7 F4 40 00 44 A1 6C 00
7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 07 00 00 30 07
00 00 5D A5 40 00 95 BA 40 00 DD B9 40 00 DD BA 40 00 45 C8 40 00 E9
C4 40 00 25 C5 40 00 FA C6 40 00 9B 6E 4B 00 B6 67 4B 00 D3 88 40 00
7A 40 66 00 14 9F 40 00 14 A3 40 00 87 A1 6C 00 7A 33 C6 75 82 98 AF
77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 18 00 00 00 B0 04
02 00 29 94 D2 50 × ` . è › Š . ÿ ÿ ÿ ÿ . . . . . .
. . . . . . . . . . . . . . v È . € € € € . .
. . ‘ . ú ~ . . . . . . . . . . . . . . . . ß .
. . Š g @ . £ ¤ @ . 0 © @ . & m K . h K . . ;
f . - š l . € Ÿ @ . ì Ÿ @ . · ô @ . D ¡ l . z 3
Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . . .
. . . . . . . . . . . . . . 0 . . . 0 . . . ] ¥
@ . • º @ . Ý ¹ @ . Ý º @ . E È @ . é Ä @ . % Å
@ . ú Æ @ . › n K . ¶ g K . Ó ˆ @ . z @ f . . Ÿ
@ . . £ @ . ‡ ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . .
. . . . . . . . . . . . . . ° . . . ) ” Ò P
长 运行ning 进程在 运行ning 时间后的内存占用大于启动后不久的内存占用,这并不异常。即使进程暂时不处理请求。由于内存分配需要一些时间,一些内存管理器(我认为 FastMM 也是这样做的)将保留不再使用的内存仍然分配,以备软件需要分配新对象或变量时使用,因此内存可以重新使用。
对于您的情况,如果可能的话,让进程 运行 再过几个月,看看内存使用量是否稳定并且不再持续增长。如果此内存应该再次可供其他进程使用很重要,请检查您是否可以使用选项或配置设置调整 FastMM。
我有一个在 XE6 上使用 TIdHTTPServer 构建的服务器(默认 Indy 10 安装和组件上的默认选项设置)用于文件下载:
procedure CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
AResponseInfo.ContentStream := TFileStream.Create('C:\MyFile.Exe', fmOpenRead or fmShareDenyNone);
end;
在许多个月(6 个月)和大量请求(少于或多于 1'000'000)之后,服务器进程增加了私人内存(在任务管理器上)超过 50 MB。
TIdHTTPServer 是否泄漏内存?
更新:
在
的小型测试应用程序中initialization
ReportMemoryLeaksOnShutdown := True;
不漏水
我也尝试过使用 FastMM dll,这是报告(我的 SO 是意大利语)
--------------------------------2015/11/2 14:52:38-------------------------
Leak di un blocco. La dimensione è: 20
Questo blocco è stato allocato dal thread 0x730, e lo stack trace (indirizzo restituito) in quel momento era: 40678A 4087AF 408ED6 640996 [IdThreadSafe][IdThreadSafe][IdThreadSafe..TIdThreadSafeObjectList][144] 6C996F [IdGlobalProtocols.pas][IdGlobalProtocols][IdGlobalProtocols.IdGlobalProtocols][4743] 6C9984 [IdGlobalProtocols.pas][IdGlobalProtocols][IdGlobalProtocols.IdGlobalProtocols][4744] 6C99D5 [IdThread.pas][IdThread][IdThread.IdThread][732] 409F80 409FEC 40F4B7 [SysInit.pas][SysInit][SysInit.@InitExe][1191] 6CA144 [WMain.pas][WMain][WMain.WMain][295] 75C6337A [BaseThreadInitThunk] 77AF9882 [Unknown function at RtlInitializeExceptionChain] 77AF9855 [Unknown function at RtlInitializeExceptionChain]
Il blocco è attualmente usato da una istanza della classe: TIdThreadSafeInteger
Il numero di allocazione è: 475
Dump della memoria di 256 byte partendo dall'indirizzo del puntatore 7EF3D2C0: FC 02 64 00 60 0F FA 7E 00 00 00 00 00 00 00 00 0B 12 7A 17 80 80 80 80 00 00 00 00 B1 D5 F3 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E2 01 00 00 8A 67 40 00 AF 87 40 00 D6 8E 40 00 A4 88 40 00 8D 85 D2 00 BA 85 D2 00 15 FC 4C 00 9E FB 4C 00 05 43 4B 00 ED 91 66 00 5D 9A 6C 00 80 9F 40 00 EC 9F 40 00 B7 F4 40 00 44 A1 6C 00 7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 30 07 00 00 30 07 00 00 A6 67 40 00 CD 87 40 00 21 8F 40 00 C6 88 40 00 D3 88 40 00 38 FD 4C 00 D3 88 40 00 62 43 4B 00 D3 88 40 00 3E 92 66 00 14 9F 40 00 14 A3 40 00 87 A1 6C 00 7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 BC 69 4E 00 45 BC CB 52 A0 41 D3 00 80 80 80 80 BA 43 34 AD 80 80 80 80 ü . d . ` . ú ~ . . . . . . . . . . z . € € € € . . . . ± Õ ó ~ . . . . . . . . . . . . . . . . â . . . Š g @ . ¯ ‡ @ . Ö Ž @ . ¤ ˆ @ . … Ò . º … Ò . . ü L . ž û L . . C K . í ‘ f . ] š l . € Ÿ @ . ì Ÿ @ . · ô @ . D ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . 0 . . . 0 . . . ¦ g @ . Í ‡ @ . ! @ . Æ ˆ @ . Ó ˆ @ . 8 ý L . Ó ˆ @ . b C K . Ó ˆ @ . > ’ f . . Ÿ @ . . £ @ . ‡ ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . . . . . . . . . . . . . ¼ i N . E ¼ Ë R A Ó . € € € € º C 4 € € € €
--------------------------------2015/11/2 14:52:38------------------------- Leak di un blocco. La dimensione è: 36
Questo blocco è stato allocato dal thread 0x730, e lo stack trace (indirizzo restituito) in quel momento era: 40678A 4087AF 408ED6 440106 [System.SyncObjs.pas][System][System.SyncObjs.TEvent.Create][827] 412FEA [Winapi.Windows.pas][Winapi][Winapi.Windows.GetProcAddress][34295] 6C98AB [IdStack.pas][IdStack][IdStack.IdStack][1138] 409F80 409FEC 40F4B7 [SysInit.pas][SysInit][SysInit.@InitExe][1191] 6CA144 [WMain.pas][WMain][WMain.WMain][295] 75C6337A [BaseThreadInitThunk] 77AF9882 [Unknown function at RtlInitializeExceptionChain] 77AF9855 [Unknown function at RtlInitializeExceptionChain]
Il blocco è attualmente usato da una istanza della classe: TIdCriticalSection
Il numero di allocazione è: 458
Dump della memoria di 256 byte partendo dall'indirizzo del puntatore 7EFA0A60: 90 D7 60 00 C0 9B 8A 00 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 CC A7 B0 80 80 80 80 00 00 00 00 91 0B FA 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D1 01 00 00 8A 67 40 00 A3 A4 40 00 D4 A6 40 00 D1 E3 40 00 0E B4 AF 77 B5 33 AF 77 E3 2F AF 77 FA FA AD 77 2B D7 C6 75 48 D7 C6 75 BA D6 C6 75 7E D6 C6 75 91 D6 C6 75 32 FA AD 77 1A D6 C6 75 04 D4 C6 75 FE D5 C6 75 34 47 B1 77 A1 47 B1 77 09 F2 AE 77 74 F2 AE 77 30 07 00 00 30 07 00 00 A6 67 40 00 5D A5 40 00 41 A1 40 00 4B B4 62 00 14 9F 40 00 14 A3 40 00 87 A1 6C 00 7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00 00 B0 04 02 00 70 93 97 CA × ` . À › Š . ÿ ÿ ÿ ÿ . . . . . . . . . . . . . . . . . . . . . Ì § ° € € € € . . . . ‘ . ú ~ . . . . . . . . . . . . . . . . Ñ . . . Š g @ . £ ¤ @ . Ô ¦ @ . Ñ ã @ . . ´ ¯ w µ 3 ¯ w ã / ¯ w ú ú w + × Æ u H × Æ u º Ö Æ u ~ Ö Æ u ‘ Ö Æ u 2 ú w . Ö Æ u . Ô Æ u þ Õ Æ u 4 G ± w ¡ G ± w . ò ® w t ò ® w 0 . . . 0 . . . ¦ g @ . ] ¥ @ . A ¡ @ . K ´ b . . Ÿ @ . . £ @ . ‡ ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " . . . ° . . . p “ — Ê
--------------------------------2015/11/2 14:52:38------------------------- Leak di un blocco. La dimensione è: 36
Questo blocco è stato allocato dal thread 0x730, e lo stack trace (indirizzo restituito) in quel momento era: 40678A 4087AF 408ED6 440106 [System.SyncObjs.pas][System][System.SyncObjs.TEvent.Create][827] 4087B8 6409AF [IdThreadSafe][IdThreadSafe][IdThreadSafe..TIdThreadSafeObjectList][144] 6C99D5 [IdThread.pas][IdThread][IdThread.IdThread][732] 409F80 409FEC 40F4B7 [SysInit.pas][SysInit][SysInit.@InitExe][1191] 6CA144 [WMain.pas][WMain][WMain.WMain][295] 75C6337A [BaseThreadInitThunk] 77AF9882 [Unknown function at RtlInitializeExceptionChain] 77AF9855 [Unknown function at RtlInitializeExceptionChain]
Il blocco è attualmente usato da una istanza della classe: TIdCriticalSection
Il numero di allocazione è: 476
Dump della memoria di 256 byte partendo dall'indirizzo del puntatore 7EFA0F60: 90 D7 60 00 E8 9B 8A 00 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 76 7F C8 17 80 80 80 80 00 00 00 00 91 10 FA 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF 01 00 00 8A 67 40 00 A3 A4 40 00 30 A9 40 00 26 6D 4B 00 81 68 4B 00 12 3B 66 00 2D 9A 6C 00 80 9F 40 00 EC 9F 40 00 B7 F4 40 00 44 A1 6C 00 7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 07 00 00 30 07 00 00 5D A5 40 00 95 BA 40 00 DD B9 40 00 DD BA 40 00 45 C8 40 00 E9 C4 40 00 25 C5 40 00 FA C6 40 00 9B 6E 4B 00 B6 67 4B 00 D3 88 40 00 7A 40 66 00 14 9F 40 00 14 A3 40 00 87 A1 6C 00 7A 33 C6 75 82 98 AF 77 55 98 AF 77 00 00 00 00 00 00 00 00 00 00 00 00 18 00 00 00 B0 04 02 00 29 94 D2 50 × ` . è › Š . ÿ ÿ ÿ ÿ . . . . . . . . . . . . . . . . . . . . v È . € € € € . . . . ‘ . ú ~ . . . . . . . . . . . . . . . . ß . . . Š g @ . £ ¤ @ . 0 © @ . & m K . h K . . ; f . - š l . € Ÿ @ . ì Ÿ @ . · ô @ . D ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 . . . 0 . . . ] ¥ @ . • º @ . Ý ¹ @ . Ý º @ . E È @ . é Ä @ . % Å @ . ú Æ @ . › n K . ¶ g K . Ó ˆ @ . z @ f . . Ÿ @ . . £ @ . ‡ ¡ l . z 3 Æ u ‚ ˜ ¯ w U ˜ ¯ w . . . . . . . . . . . . . . . . ° . . . ) ” Ò P
长 运行ning 进程在 运行ning 时间后的内存占用大于启动后不久的内存占用,这并不异常。即使进程暂时不处理请求。由于内存分配需要一些时间,一些内存管理器(我认为 FastMM 也是这样做的)将保留不再使用的内存仍然分配,以备软件需要分配新对象或变量时使用,因此内存可以重新使用。
对于您的情况,如果可能的话,让进程 运行 再过几个月,看看内存使用量是否稳定并且不再持续增长。如果此内存应该再次可供其他进程使用很重要,请检查您是否可以使用选项或配置设置调整 FastMM。