2012年12月6日星期四

【转】delphi包程序啟動慢的問題的解

公司系統是以BPL來模塊化各個模塊的,但是目前遇到了一個瓶頸,就是啟動一個模塊的時間讓用戶無法接受,需要10秒甚至10秒以上。以下內容摘自我發出的郵件。

=========================

  以下是我的排查過程,其中包括了測試的結果和對一些問題的排查,以p42.8,1G RAM的電腦來測試。

 

  根據之前測試的情況,以及您告訴我的情況,我開始懷疑LoadPackage花了比較多的時間。后來我寫代碼來顯示loadPackage的時間,wck3110花了10秒,wop1120花了7秒。

  經過幾個其他的作業的測試,基本驗證了猜測,把問題確定在LoadPackage

  所以其實到這里我心里基本排除了因為框架上使用了過多的控件或其他類,需要在create的時候花費了很多時間的懷疑,因為loadpackage只是把包加載到內存,還沒有做任何的類的create的動作。

 

接下來做了一些測試,發現一個有趣的現象,編寫一支新的單據作業,沒有代碼,loadpackage這個作業,只需要1秒,但是如果先loadPackage其他的單據作業比如wop1120,再loadpackage這個新作業時,盡然花了8秒。這就讓我對delphi的這個LoadPackage到底再做些什么有了一些好奇和猜測,包括是否是因為派生層次太多,還是代碼量太大,還是怎么樣。。

我追蹤Loadpackage的源碼,可以把它分為兩部分:

   Handle := SafeLoadLibrary(bplname); //這里調用winAPIloadLibrary函數來加載bpl(因此其實bpl也可以認為是一個dll

   InitializePackage(Handle); //初始化這個bpl

我同樣編寫代碼來測試SafeLoadLibrary(bplname)這個部分需要花的時間,測試結果是0.6秒。因此進一步把問題確定在InitializePackage(Handle),我再進一步分解InitializePackage(Handle),發現它其實包括兩個部分

  CheckForDuplicateUnits(Module); //這個部分我通過參考其他書籍和看它的代碼知道,這里是用來檢測是否多個不同的bpl是否有包含相同的unit.如果是,則raise一個exception

  @PackageLoad := GetProcAddress(Module, 'Initialize'); //這個部分是取得包的入口點函數的地址,然后調用這個入口點函數,接著這個入口點函數會執行包的初始化,比如建立類的vmt等等。

  if Assigned(PackageLoad) then

    PackageLoad

  else

    raise EPackageError.CreateFmt(sInvalidPackageFile, [GetModuleName(Module)]);

由于我們的作業使用了很多的第三方控件,和幾乎引用了所有的基礎包。所以我很有理由懷疑CheckForDuplicateUnits(Module)的代碼寫得再好,也可能需要很多時間,需要遞歸調用之類的動作。但是,對于我們的ERP系統來說多個不同的bpl是否有包含相同的unit的情況是不會存在的。Dephi的這種設計應該是考慮到了不同系統之間共享包的情況。所以在我們系統中,這個檢查可以略去。

為了證實這個猜測,我修改了我們系統中加載包的代碼,原來是直接調用loadPackage,現在改為如下:

    hPackage := SafeLoadLibrary(ASvcFileName);

    if hPackage = 0 then

      raise EPackageError.CreateResFmt(@sErrorLoadingPackage,

        [Name,SysErrorMessage(GetLastError)]);

    try

      //CheckForDuplicateUnits(hPackage); //這一行注釋掉

      @PackageLoad := GetProcAddress(hPackage, 'Initialize'); //Do not localize

      if Assigned(PackageLoad) then

        PackageLoad

      else

        raise EPackageError.CreateFmt(sInvalidPackageFile, [GetModuleName(hPackage)]);

    except

      FreeLibrary(hPackage);

    end;

然后再運行erp測試,結果把我樂壞了之前的猜測完全正確。最終的測試結果是

Wck3110應付票據領票,原來整個過程需要11秒,loadpackage的部分就需要10秒,現在整個過程只需要1.8秒而已。

Wop1120銷貨單,原來整個過程需要11秒,loadpackage的部分就需要8秒,現在整個過程只需要4秒而已。

 

且昨天下午至今天上午,我反復測試,包括作業調用作業,增刪改,簽核。一切正常。

摘自:http://blog.csdn.net/truexf/article/details/3852375

没有评论: