我将不得不创建一个多线程项目很快我看到实验(delphitools.info/2011/10/13/memory-manager-investigations)显示默认的Delphi内存管理器存在多线程问题.

所以,我找到了这个SynScaleMM.有人可以给它或类似的内存管理器提供一些反馈吗?
谢谢
Arn*_*hez 47
我们的SynScaleMM仍处于试验阶段.
编辑:看看更稳定的ScaleMM2 和全新的SAPMM.但是我的下面的评论仍然值得关注:你做的分配越少,你的规模越大!
但它在多线程服务器环境中按预期工作.对于某些关键测试,缩放比FastMM4要好得多.
但内存管理器可能不是多线程应用程序中的更大瓶颈.如果你没有强调它,FastMM4可以很好地工作.
如果你想在Delphi中编写FAST多线程应用程序,这里有一些(不是教条,只是来自实验和低级Delphi RTL的知识)建议:
const字符串或动态数组参数,MyFunc(const aString: String)以避免每次调用分配一个临时字符串;s := s+'Blabla'+IntToStr(i)),但依赖TStringBuilder于最新版本的Delphi中提供的缓冲写入;TStringBuilder也不是完美的:例如,它会创造大量的临时字符串进行追加一些数值数据,并且将使用非常缓慢SysUtils.IntToStr(),当你添加一些功能integer价值-我不得不重写了很多低级别的功能,以避免大多数字符串我们TTextWriter在SynCommons.pas中定义的类中的分配 ;InterlockedIncrement / InterlockedExchangeAdd;InterlockedExchange(来自SysUtils.pas)是更新缓冲区或共享对象的好方法.您在线程中创建某些内容的更新版本,然后TObject在一个低级CPU操作中交换共享指向数据(例如实例)的指针.它将通过非常好的多线程扩展通知其他线程的更改.您必须处理数据完整性,但它在实践中非常有效.PosEx(),例如;AnsiString/UnicodeString各种变量/函数,并通过Alt-F2检查生成的asm代码以跟踪任何隐藏的不需要的转换(例如call UStrFromPCharLen);var参数procedure而不是function返回一个字符串(返回一个函数string将添加一个UStrAsg/LStrAsg具有LOCK 的调用,该LOCK将刷新所有CPU内核);TMemoryStream每次需要时创建一个,而是依赖类中的私有实例,已经在足够的内存中进行调整,在这个实例中,您将使用数据Position来检索数据而不更改数据Size(这将是内存由MM分配的块);record/object在已经分配的内存缓冲区上使用一些指针,映射数据而不将其复制到临时内存中;我试图在开源框架中遵循这些规则,如果你看看我们的代码,你会发现很多真实的示例代码.
Dav*_*nan 12
如果您的应用程序可以容纳GPL许可代码,那么我建议您使用Hoard.你必须自己编写包装,但这很容易.在我的测试中,我发现没有任何与此代码匹配的内容.如果您的代码无法容纳GPL,那么您可以获得很高的费用获得Hoard的商业许可.
即使您不能在代码的外部版本中使用Hoard,您也可以将其性能与FastMM的性能进行比较,以确定您的应用程序是否存在堆分配可伸缩性问题.
我还发现msvcrt.dll版本中的内存分配器随Windows Vista一起发布,后来在线程争用下可以很好地扩展,肯定比FastMM好得多.我通过以下Delphi MM使用这些例程.
unit msvcrtMM;
interface
implementation
type
size_t = Cardinal;
const
msvcrtDLL = 'msvcrt.dll';
function malloc(Size: size_t): Pointer; cdecl; external msvcrtDLL;
function realloc(P: Pointer; Size: size_t): Pointer; cdecl; external msvcrtDLL;
procedure free(P: Pointer); cdecl; external msvcrtDLL;
function GetMem(Size: Integer): Pointer;
begin
Result := malloc(size);
end;
function FreeMem(P: Pointer): Integer;
begin
free(P);
Result := 0;
end;
function ReallocMem(P: Pointer; Size: Integer): Pointer;
begin
Result := realloc(P, Size);
end;
function AllocMem(Size: Cardinal): Pointer;
begin
Result := GetMem(Size);
if Assigned(Result) then begin
FillChar(Result^, Size, 0);
end;
end;
function RegisterUnregisterExpectedMemoryLeak(P: Pointer): Boolean;
begin
Result := False;
end;
const
MemoryManager: TMemoryManagerEx = (
GetMem: GetMem;
FreeMem: FreeMem;
ReallocMem: ReallocMem;
AllocMem: AllocMem;
RegisterExpectedMemoryLeak: RegisterUnregisterExpectedMemoryLeak;
UnregisterExpectedMemoryLeak: RegisterUnregisterExpectedMemoryLeak
);
initialization
SetMemoryManager(MemoryManager);
end.
Run Code Online (Sandbox Code Playgroud)
值得指出的是,在FastMM中的线程争用成为性能障碍之前,您的应用必须非常努力地锤击堆分配器.通常根据我的经验,这会在您的应用程序执行大量字符串处理时发生.
对于在堆分配上遇到线程争用的任何人,我的主要建议是重新编写代码以避免命中堆.你不仅避免了争用,而且还避免了堆分配的费用 - 一个经典的双人!
| 归档时间: |
|
| 查看次数: |
7100 次 |
| 最近记录: |