论:
1、绝对不可低估开源的力量!我们能由开源学到更多 ...
2、Dexter 抛弃了 BorlandMM,娶了 FastMM,因为 FastMM 勤快(效率更高),会持家(没有而外 DLL 的累赘)...
3、和以往的 Delphi 不同,Delphi 2006 中在 Dll 导出 string、动态数组等不再需要 ShareMem!(因为已经内置了)
=^0^=
-----------------------------------------------------------------------------------------------------------------------------------------
这差不多是一年半前发的一封邮件了,当时强烈推荐使用 FastShareMem 替代 Borland 的 ShareMem 以避免不必要的麻烦(BUG 等)。
之后,Borland 发布了 Delphi 2005,当然,这个相对 Delphi 8 依旧是问题多多。到了 sp3 时 Delphi 2005 依旧存在若干问题。其中一个突出的问题是:IDE 启动速度过慢,爆占内存!不过这个在去年的九月份左右,Borland 的开发人员(Allen Bauer,IDE 的开发者)发布了一个非官方的补丁,据说主要是采用 FastMM 重新编译了 BorlndMM 宝兰这个使用了 NN 年的内存管理器,从而达到加速 IDE 启动,降低内存使用和内存碎片等。当时下载使用,确实非常不错!
当时开始注意这个 FastMM 了。据说 FastMM 是一个法国人主导的一个开源项目。这个在外国 Delphi 社区非常有名(感觉在国内消息闭塞,去年才开始有人用?)主要目的就是重新实现一个高效、安全、稳定的内存管理器(Borland 的内存管理器问题多多,如 Dll 和 Exe 间无法共享,多线程下效率底下--一些情况下甚至于低一个数量级!)
后来,在代号为 Dexter 的 Delphi 2006 没 release 之前已经听李维大肆鼓吹说 Dexter 如何出色,还在 CSDN 上说他 Demo 证明 FastMM 在 Delphi 和 BCB 下能提高 NNN% 的效率!
再后来,Delphi 2006 发布了,确实非常的稳定,带着对 Dexter 和 FastMM 的好奇,对比 Delphi 7 和 2006 的 RTL Source,可以发现 Delphi 的 Source/rtl/sys 中最核心的文件变化最大的是 getmem.ini 和 sysutils.pas
查看主要的差异,sysutils 中一大批基本函数的实现被修改了,按照 pas 中的说明修改内容来源于 FastCode 这个开源项目,而 getmem.inc 这个文件的差异简直就是被“重写”了。按照 getmem 中的说明,使用的就是 FastMM 这个内存管理器!
在
http://sourceforge.net/projects/fastmm 中可以下载到最新 stable 的 FastMM,当前推荐的是 4.62,主要特点包括:
1、彻底实现了 Borland 的内存管理器,可以完全取代现有的内存管理器(“取代”就是第一个 uses FastMM4,that is all ...)
2、实现了内存管理器共享机制,Exe 和 Dll 间共享内存管理器不需要任何 Dll 支持
3、集成了内存泄漏检测功能
4、充分兼容现有的代码、Delphi 旧内存管理器模式
5、为了加速 Delphi IDE(如 Delphi 7、Delphi 2005)的启动速度、管理内存占用等,他提供了 BorlndMM.dll 的替代,直接替换 Bin 中的 Dll 即可!
对于 3 非常吸引人,Demo 一个:
当然,他只会告诉你“发生问题了”,至于“问题如何发生的”还靠 AQTime 等。至少他会“第一时间”告诉你:出问题啦 ...
在 release 版中不会出现这个提示,如果觉得繁,可以让他 log 到文件或 disable 之。
几个引申:
1、由于 Dephi 2006 使用的 getmem.inc 就是 FastMM 的,所以,Delphi 2006 中在 Dll 导出 string、动态数组等不再需要 ShareMem!
2、经过测试,Delphi 7 下 uses FastMM4 会带来约 13K 的大小差异(除非直接集成 ;>),不过同样的 Dll 在 Delphi 2006 下编译竟然比 Delphi 7 下的要小 10K!看到 FastCode 和 FastMM 的威力了吧!
3、既然 getmem.inc 那么好使,一个大胆的设想,能否使用 Delphi 2006 的 getmem.inc 替换调 Delphi 7 的?我没空验证。不过由于接口函数的一致,这个应该是可行的,需要重新编译 System.pas,编译这个 pas 的方法在《delphi 内核源码分析》中有介绍的。
4、打算加到 GrandResource 中。
那么,他稳定么?
1、开源,公测保证
2、google 一下吧,网上 NNN 多项目转用 FastMM 的了 ...
BTW:
据说《delphi 内核源码分析》会出新版,会加入 FastMM 和 FastCode 等,同时详细解说 Delphi 中的 COM 部分。
嗯,如果消息可靠,确实是值得期待的一本书 ...
=^0^=
--------------------------------------------------------------------------------
主题: 宝兰妹妹 (borlandmm、sharemem) 不再是你的唯一 ...
在 exe 和 dll 编程中最容易出现的一个问题是:
这个问题是如何出现的呢?
dll 导出函数:
function GetText: string;
begin
Result := '=^0^=';
end;
exports
GetText;
exe 中使用:
function GetText: string; external 'TestDll.dll' name 'GetText';
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(GetText);
end;
执行 ShowMessage 后将报这个错误 ...
当然,出现这个问题后公司的大虾们会提示说,borland 在每个 dll 向导产生的代码中都会有如下提示:
{ 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. }
问题是由于 dll、exe 间传递动态数组、string 而引起的。
昨天无意中看到一个网站:
http://www.codexterity.com
有对 borland 中关于内存管理的描述,其中对这类问题有非常清晰的解答。直接点,就是由于使用了两套内存管理系统,在堆中同时维护一个 string 而造成的冲突。当然,他也提出了解决方法:让 dll 与 exe 公用一个内存管理器,而且实现的非常的秒!由此带来的好处是:
1、避免使用 ShareMM(发布时需要额外附带 borlandmm.dll)
2、据说相对 ShareMM 速度提高 N 倍
使用方法是第一个引用该单元即可:
uses
FastShareMem in 'FastShareMem.pas',
SysUtils,
Classes;
令人震惊的是,他的代码竟然不到 70 行!
同时,这个网站上还有一篇非常好的文章:borland 中是如何管理字符串的。附件 chm 是该网站的上面几篇文章的打包,rar 是测试例子。
最后的最后,不禁要问,为什么 borland 的工程师没有想到?或者有别的原因?