技巧:使用自己的内存管理器来优化程序的执行效率。(50分)

  • 主题发起人 主题发起人 shenloqi
  • 开始时间 开始时间
S

shenloqi

Unregistered / Unconfirmed
GUEST, unregistred user!
这里是我参阅相关资料之后写的自己的内存管理器,用于频繁的要求分配内存时效果要
比Delphi自带的ShareMeM.pas(与BorlndMM.dll搭配使用的)要好。

因为Delphi是按照深度优先的原则来初始化单元的,所以请尽量把ShenShareMeM.pas放在
工程主要源文件的开头处(SysUtils前面),如同BorlndMM.dll一样,发布时需要在Exe
的目录下发布SHenMM.dll(未使用Aspack压缩的时候,D6编译后14k)。

在需要使用Dll的时候使用ShenShareMem,如果无需,则使用CheckMemMgr就可以了。

这里贴出源代码,在我的主页上有源程序以及编译好的Dll下载。
(http://shenloqi.51.net)
(http://shenloqi.51.net/html/wdymindex.htm)

代码:
{-----------------------------------------------------------------------------
 Unit Name: ShenMM.dpr
 Author:    slq (沈龙强)
 E-Mail:    Chinbo@eyou.com
 Homepage:  http://shenloqi.delphibbs.com
            http://www.shen.h58.net
 Purpose:   用来代替BorlndMM.dll的内存管理器。
            做成动态连接库的目的是因为Dll的特性(引用计数等)。

            用于在BorlndMM.dll不适用的场合,如以不断增加的尺寸增加内存时。

 History:
-----------------------------------------------------------------------------}


library ShenMM;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  CheckMemMgr in 'CheckMemMgr.pas';

exports
  //导出函数
  CheckGet, CheckFree, CheckRealloc;

begin
end.

代码:
{-----------------------------------------------------------------------------
 Unit Name: CheckMemMgr
 Author:    slq (沈龙强)
 E-Mail:    Chinbo@eyou.com
 Homepage:  http://shenloqi.delphibbs.com
            http://www.shen.h58.net
 Purpose:   这个单元用来替换Delphi的内存管理。
            主要是知道TMemoryManager这个记录类型的类的用法然后再
            加上简单的指针应用就可以了。

            处理内存泄漏的时候采用了Win32API的Messagebox或许不是一个好办法:)
 History:
-----------------------------------------------------------------------------}


unit CheckMemMgr;

interface

uses
  Windows;

//Dll导出函数

//Mgr.GetMem
function CheckGet(Size: Integer): Pointer;
//Mgr.FreeMem
function CheckFree(Mem: Pointer): Integer;
//Mgr.ReallocMem
function CheckRealloc(Mem: Pointer
Size: Integer): Pointer;

var
  //堆栈标识
  HeapFlags: DWord;

implementation

const
  //指针列表的最多元素
  MaxSize = MaxInt div 4;

type
  //指针列表类型
  TPointerArray = array[1..MaxSize] of Pointer;
  //指向指针列表的指针
  PPointerArray = ^TPointerArray;

var
  //堆栈
  Heap: THandle;
  //列表
  List: PPointerArray;
  //列表大小,最多到MaxSize
  ListSize: Integer;
  //列表分配大小,最多到MaxSize+256
  ListAlloc: Integer;

{-----------------------------------------------------------------------------
  Procedure: MemoryLeak
  Author:    slq
  Date:      21-三月-2002
  Arguments: None
  Result:    None
  Purpose:   内存泄漏时处理函数。
-----------------------------------------------------------------------------}

procedure MemoryLeak;
begin
  MessageBox(0, 'It Seemed Something Wrong , Memory Leak!', 'Warning...',
    MB_OK);
end;

{-----------------------------------------------------------------------------
  Procedure: AddMem
  Author:    slq
  Date:      21-三月-2002
  Arguments: Mem: Pointer
  Result:    None
  Purpose:   增加一个内存指针到列表
-----------------------------------------------------------------------------}

procedure AddMem(Mem: Pointer);
begin
  if List = nil then
  begin
    //新的指针列表
    ListAlloc := 8;
    List := HeapAlloc(Heap, HeapFlags, ListAlloc * SizeOf(Pointer));
  end
  else if ListSize >= ListAlloc then
  begin
    //列表不够大,增加列表大小,每次增加的少一些,可以满足频繁的分配要求
    if ListAlloc < 256 then
      ListAlloc := ListAlloc * 2
    else
      ListAlloc := ListAlloc + 256;
    List := HeapReAlloc(Heap, HeapFlags, List, ListAlloc * SizeOf(Pointer));
  end;
  //增加一个指针到列表
  Inc(ListSize);
  List[ListSize] := Mem;
end;

{-----------------------------------------------------------------------------
  Procedure: RemoveMem
  Author:    slq
  Date:      21-三月-2002
  Arguments: Mem: Pointer
  Result:    Boolean
  Purpose:   查找并删除列表中的指针。
             成功返回True,失败返回False(指针不在列表中)。
-----------------------------------------------------------------------------}

function RemoveMem(Mem: Pointer): Boolean;
var
  I: Integer;
begin
  for I := 1 to ListSize do
    if List[I] = Mem then
    begin
      MoveMemory(@List[I], @List[I + 1], (ListSize - I) * SizeOf(Pointer));
      Dec(ListSize);
      Result := True;
      Exit;
    end;

  Result := False;
end;

{-----------------------------------------------------------------------------
  Procedure: CheckGet
  Author:    slq
  Date:      21-三月-2002
  Arguments: Size: Integer
  Result:    Pointer
  Purpose:   替换内存分配器。
-----------------------------------------------------------------------------}

function CheckGet(Size: Integer): Pointer;
begin
  //分配内存
  Result := SysGetMem(Size);
  //增加指针
  AddMem(Result);
end;

{-----------------------------------------------------------------------------
  Procedure: CheckFree
  Author:    slq
  Date:      21-三月-2002
  Arguments: Mem: Pointer
  Result:    Integer
  Purpose:   如果指针在列表中则删除实际内存。
             返回值非零则错误。
-----------------------------------------------------------------------------}

function CheckFree(Mem: Pointer): Integer;
begin
  if not RemoveMem(Mem) then
    Result := 1
  else
    //释放内存
    Result := SysFreeMem(Mem);
end;

{-----------------------------------------------------------------------------
  Procedure: CheckRealloc
  Author:    slq
  Date:      21-三月-2002
  Arguments: Mem: Pointer
Size: Integer
  Result:    Pointer
  Purpose:   用新的指针代替旧的指针。
             如果不能移走旧的指针返回值为nil,这样Delphi会自动抛出一个异常。
-----------------------------------------------------------------------------}

function CheckRealloc(Mem: Pointer
Size: Integer): Pointer;
begin
  if not RemoveMem(Mem) then
    Result := nil
  else
  begin
    //重分配;
    Result := SysReallocMem(Mem, Size);
    //增加指针
    AddMem(Result);
  end;
end;

{-----------------------------------------------------------------------------
  Procedure: SetNewManager
  Author:    slq
  Date:      21-三月-2002
  Arguments: None
  Result:    None
  Purpose:   设置为新的内存管理器。
             需要了解TMemoryManager的结构。
-----------------------------------------------------------------------------}

procedure SetNewManager;
var
  Mgr: TMemoryManager;
begin
  Mgr.GetMem := CheckGet;
  Mgr.FreeMem := CheckFree;
  Mgr.ReallocMem := CheckRealloc;
  SetMemoryManager(Mgr);
end;

//初始化的时候分配一块堆栈,并设置为新的内存管理器。
initialization
  Heap := HeapCreate(0, HeapFlags, 0);
  SetNewManager;

//结束的时候检查是否有内存泄漏并释放堆栈。
finalization
  if ListSize <> 0 then
    MemoryLeak;
  HeapDestroy(Heap);
end.

代码:
{-----------------------------------------------------------------------------
 Unit Name: ShenShareMem
 Author:    slq (沈龙强)
 E-Mail:    Chinbo@eyou.com
 Homepage:  http://shenloqi.delphibbs.com
            http://www.shen.h58.net
 Purpose:   这个单元用来代替ShareMem单元,使用了ShenMM.dll这个动态连接库。


            适用范围是频繁的分配新的小内存的时候。
            发布的时候需要带上ShenMM.dll(很小,还没有Aspack压缩过)
 History:
-----------------------------------------------------------------------------}


unit ShenShareMem;

interface

//设置TMemoryManager时使用
function CheckGet(Size:Integer):Pointer;
function CheckFree(Mem:Pointer):Integer;
function CheckRealloc(Mem:Pointer;Size:Integer):Pointer;

implementation

const
  DLL = 'ShenMM.dll';

//导入ShenMM.dll的三个导出函数
function CheckGet(Size:Integer):Pointer;external DLL;
function CheckFree(Mem:Pointer):Integer;external DLL;
function CheckRealloc(Mem:Pointer;Size:Integer):Pointer;external DLL;

{-----------------------------------------------------------------------------
  Procedure: SetNewManager
  Author:    slq
  Date:      21-三月-2002
  Arguments: None
  Result:    None
  Purpose:   设置为新的内存管理器。
             需要了解TMemoryManager的结构。
-----------------------------------------------------------------------------}
procedure SetNewManager;
var
  Mgr: TMemoryManager;
begin
  Mgr.GetMem := CheckGet;
  Mgr.FreeMem := CheckFree;
  Mgr.ReallocMem := CheckRealloc;
  SetMemoryManager(Mgr);
end;

//初始化的时候设置新的内存管理器
initialization
  SetNewManager;

end.

明天面试去了,早点休息了:)
 
收藏,有空时再看看。
 
能否用数据说明效率高多少?
 
不会吧?
我刚刚回答的东西没有记录到数据库?!

再说一次:

我认为这个效率的提升(甚至是是否提升)应该是无法用数字来表达的,因为:
1.两种内存管理器各有各自的最适用的用途,这个内存管理器对于频繁的分配内存的程序
来说是很适合的,但是如果不是这样,就不能看出它比Delphi自带的什么优点了。
2.根具体的机器配置有关。如果内存本来就不大,用Delphi自己的会浪费的比较多,如果
运行时间长了之后程序乃至整个系统就会变慢,而这个可以较好的减轻这种现象。
3.这个内存管理器的具备的好处是可以检查内存泄漏。
 
先看看再说话
 
看书来了。
 
酷啊。。
 
好人呀! 让人学习还给分! 佩服
 
感谢并学习中。。。
 
多人接受答案了。
 
to shenloqi:
你的这个怎么用呀?能不能告诉我用法?我很想知道,谢谢!
 
我崇拜您哦[:)]
 

Similar threads

后退
顶部