JBTALKS.CC

标题: [分享]如何優化記憶體 [打印本页]

作者: Super-Tomato    时间: 2008-11-8 01:03 PM
标题: [分享]如何優化記憶體
作者 : Super-Tomato


昨天看到了篇帖子寫到 Firefox 記憶體溢出的問題, 所以今天周末有空就來分享如何優化記憶體分配的編程
一開始未看到這篇文章前, 應該很多人都認為這是個很複雜的技術, 但看完之後會偷笑原來這是那麼簡單就可以實現的
沒錯, 在早期要優化記憶體這種技術應該很複雜也輪不到我這種菜鳥來寫, 但 Windows 已經把這項工程給簡化了,
所以我們只要輕鬆的套用 WINAPI 就能夠解決這個問題.


那麼到底要用哪些 WINAPI 呢??
最主要的當然就是使用 EmptyWorkingSet 回收記憶體了, 這一個函數可以大大改善記憶體的使用, 至於說明就請搜索微軟的 WINAPI 吧

p/s: 但是要記得的是縮小了記憶體並非代表程式的執行速度加快了

以下是以 BCB 針對 Firefox 做為範例和演示

  1. //---------------------------------------------------------------------------

  2. #include <vcl.h>
  3. #include <psapi.h>
  4. #pragma comment(lib, "psapi.lib")
  5. #pragma hdrstop

  6. #include "Unit1.h"
  7. //---------------------------------------------------------------------------
  8. #pragma package(smart_init)
  9. #pragma resource "*.dfm"
  10. TForm1 *Form1;
  11. //---------------------------------------------------------------------------
  12. __fastcall TForm1::TForm1(TComponent* Owner)
  13.         : TForm(Owner)
  14. {
  15. }
  16. //---------------------------------------------------------------------------
  17. void __fastcall TForm1::Timer1Timer(TObject *Sender)
  18. {
  19.         HWND firefox = FindWindow("MozillaUIWindowClass", NULL);
  20.         if(firefox)
  21.         {
  22.                 DWORD dProcessID;
  23.                 HANDLE hProcess;

  24.                 GetWindowThreadProcessId(firefox, &dProcessID);
  25.                 if(dProcessID)
  26.                 {
  27.                         hProcess = OpenProcess(PROCESS_ALL_ACCESS, true, dProcessID);
  28.                         if(hProcess)
  29.                         {
  30.                                 SetProcessWorkingSetSize(hProcess, 0, 0);
  31.                                 EmptyWorkingSet(hProcess);
  32.                                 CloseHandle(hProcess);
  33.                         }
  34.                 }
  35.         }
  36. }
  37. //---------------------------------------------------------------------------

复制代码



演示(非永久性連結)

[ 本帖最后由 Super-Tomato 于 2008-11-8 01:09 PM 编辑 ]
作者: goodhermit95    时间: 2008-11-8 08:32 PM

C++ Declare API真方便
请问可以翻译成C#.NET或VB.NET 吗?
作者: goodday    时间: 2008-11-8 11:02 PM
按错 加多了

青菜啦~~
作者: Super-Tomato    时间: 2008-11-9 01:42 AM
原帖由 goodhermit95 于 2008-11-8 08:32 PM 发表

C++ Declare API真方便
请问可以翻译成C#.NET或VB.NET 吗?



所有的語言都一樣, 只是你沒看到 header 檔怎麼定義了 Entry Point
VB.NET 做法也一樣啊, 簡單的例子就是

  1. Public Class Form1

  2.     Declare Function FindWindow Lib "user32" Alias "FindWindowW" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

  3.     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
  4.         Dim firefox As IntPtr

  5.         firefox = FindWindow("MozillaUIWindowClass", vbNullString)
  6.         If Not firefox.Equals(0) Then
  7.             Debug.Print("Found Firefox!!")
  8.         End If
  9.     End Sub
  10. End Class
复制代码

作者: goodhermit95    时间: 2008-11-9 09:09 AM
标题: 回复 #4 Super-Tomato 的帖子

看到了
哪么优化的部分是一样的吧?
如果要优化全部,那么要用For Each吗?
作者: Super-Tomato    时间: 2008-11-9 04:11 PM
原帖由 goodhermit95 于 2008-11-9 09:09 AM 发表

看到了
哪么优化的部分是一样的吧?
如果要优化全部,那么要用For Each吗?



我說了這只是針對 Firefox, 所以我只取唯一一個進程, 不明白的函數最好去搜索 msdn 的說明
至於你說全部, 那麼你就該先學習怎麼弄個 TaskManager, 之後就會明白怎麼用了
作者: goodday    时间: 2008-11-9 04:49 PM
看到了 番茄的功力
佩服

我只专.net 你好像全部都 会
作者: goodhermit95    时间: 2008-11-9 05:58 PM
标题: 回复 #6 Super-Tomato 的帖子
懂了懂了,For Each processs in system.diagnostics.getprocess
作者: late_boy    时间: 2008-11-9 11:48 PM
看似是调用SetProcessWorkingSetSize函数~
作者: Super-Tomato    时间: 2008-11-10 03:02 AM
原帖由 goodday 于 2008-11-9 04:49 PM 发表
看到了 番茄的功力
佩服

我只专.net 你好像全部都 会


都懂一些些混口飯吃而已, 最重要的還是貴在精...



原帖由 goodhermit95 于 2008-11-9 05:58 PM 发表
懂了懂了,For Each processs in system.diagnostics.getprocess


希望你別讓系統崩潰了



原帖由 late_boy 于 2008-11-9 11:48 PM 发表
看似是调用SetProcessWorkingSetSize函数~


SetProcessWorkingSetSize 中說明了大小都設定為 -1 的時候會移除Paging, 但對於 Win2K 和 Win2003 Server 來說沒打上補丁的系統來說完全沒反應, 所以配合 EmptyWorkingSet 是個互補. 當然在有了補丁的情況下使用前者更為方便, 因為根本不用再嵌入任何 dll


補充 :  
http://support.microsoft.com/kb/823684

[ 本帖最后由 Super-Tomato 于 2008-11-10 05:44 AM 编辑 ]
作者: goodhermit95    时间: 2008-11-13 02:34 PM
多谢多谢,我开发一个多功能的
可以可以Set多一点?给多RAM的人用

請問為什麽這個不行呢?
  1. Public Class Form1

  2.     Declare Function FindWindow Lib "user32.dll" Alias "FindWindowW" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
  3.     Private Declare Function SetProcessWorkingSetSize Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal dwMinimumWorkingSetSize As Int32, ByVal dwMaximumWorkingSetSize As Int32) As Int32

  4.     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
  5.         Try
  6.             GC.Collect()
  7.             GC.WaitForPendingFinalizers()
  8.             If Environment.OSVersion.Platform = PlatformID.Win32NT Then
  9.                 SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1)
  10.             End If
  11.         Catch
  12.         End Try
  13.     End Sub
  14. End Class
复制代码

我知道了!要拿processid

[ 本帖最后由 goodhermit95 于 2009-5-21 11:58 AM 编辑 ]
作者: Super-Tomato    时间: 2008-11-13 04:30 PM
原帖由 goodhermit95 于 2008-11-13 02:34 PM 发表
多谢多谢,我开发一个多功能的
可以可以Set多一点?给多RAM的人用

請問為什麽這個不行呢?
Public Class Form1

    Declare Function FindWindow Lib "user32.dll" Alias "FindWindowW" (ByVal lpClass ...


因為你還沒有打開進程, 所以無法對進程中的內存做修改
作者: goodhermit95    时间: 2008-11-13 04:32 PM
标题: 回复 #12 Super-Tomato 的帖子
所以要先用FindWindow再把System.Diagnistics.process.getcurrentprocess 换掉?
作者: Super-Tomato    时间: 2008-11-13 04:44 PM
原帖由 goodhermit95 于 2008-11-13 04:32 PM 发表
所以要先用FindWindow再把System.Diagnistics.process.getcurrentprocess 换掉?



既然你已經可以取得GetCurrentProcessId了, 那麼直接取得PID填入OpenProcess中的參數即可
建議你到 http://msdn.microsoft.com/ 中搜索你所要使用的函數需要哪些類型參數, 然後想辦法怎麼取得會方便了解些
作者: goodhermit95    时间: 2008-11-13 04:53 PM
标题: 回复 #14 Super-Tomato 的帖子

我常常去,只是我先试试看,再去哪里找
1.Handle Process
2.Open
3.Set
4.Clear Empty
5.Exit Handling
作者: late_boy    时间: 2008-11-13 06:08 PM
Super-Tomato,请问可在打开Taks manager让我看看进程优化前与优化后的Virtual memory吗??
作者: goodhermit95    时间: 2008-11-13 06:21 PM
标题: 回复 #16 late_boy 的帖子
演示影片里面有
你的那个软件好像没有优化那么多
作者: late_boy    时间: 2008-11-13 06:36 PM
原帖由 goodhermit95 于 2008-11-13 06:21 PM 发表
演示影片里面有
你的那个软件好像没有优化那么多

=.=!
我是说进程被优化后与前所使用的Virtual Memory(虚拟内存),影片内没显示~~~~
PS:那个软件我只是推荐而已哦,如有问题请发EMAIL询问作者~~~~~~~~~~~~~~~~~~

[ 本帖最后由 late_boy 于 2008-11-13 06:38 PM 编辑 ]
作者: Super-Tomato    时间: 2008-11-13 07:21 PM
原帖由 late_boy 于 2008-11-13 06:08 PM 发表
Super-Tomato,请问可在打开Taks manager让我看看进程优化前与优化后的Virtual memory吗??



好的, 沒問題



作者: late_boy    时间: 2008-11-13 07:37 PM
原帖由 Super-Tomato 于 2008-11-13 07:21 PM 发表



好的, 沒問題



好的~谢谢分享哦~
PS:阁下刚升级FF去3.0.4版本哦~~~~~~~~
作者: Super-Tomato    时间: 2008-11-13 07:48 PM
對啊... 剛升級, 要看看有改善了甚麼
但是有些插件在 3.0.x 中沒辦法使用就有點麻煩, 用慣了也是個禍根
作者: late_boy    时间: 2008-11-13 10:10 PM
原帖由 Super-Tomato 于 2008-11-13 07:48 PM 发表
對啊... 剛升級, 要看看有改善了甚麼
但是有些插件在 3.0.x 中沒辦法使用就有點麻煩, 用慣了也是個禍根

的却是,就如FF刚有版本3时,IE TAB,TAB MIX PLUS等插件都不支持,浏览蛮不方便的~~~em0015
作者: goodhermit95    时间: 2008-11-26 02:16 PM
Tomato可以给我你那个C++ Compileter的下载地址吗?
Visual Studio的BUG多多,我采访一个Include再拿掉Error就10多个了
作者: Super-Tomato    时间: 2008-11-27 12:25 AM
原帖由 goodhermit95 于 2008-11-26 02:16 PM 发表
Tomato可以给我你那个C++ Compileter的下载地址吗?
Visual Studio的BUG多多,我采访一个Include再拿掉Error就10多个了



http://www.codegear.com/downloads/free/cppbuilder
那天我用 vc 來測試沒甚麼問題, 但 vb 我就不清楚
作者: goodday    时间: 2008-11-27 09:40 AM
原帖由 goodhermit95 于 2008-11-26 02:16 PM 发表
Tomato可以给我你那个C++ Compileter的下载地址吗?
Visual Studio的BUG多多,我采访一个Include再拿掉Error就10多个了


我没问题哦
吃生菜咯
作者: goodhermit95    时间: 2008-11-28 03:01 PM
我很多问题啦~~而且很多地方怪怪的
Zero也说不建议用VS的VC++
作者: Super-Tomato    时间: 2008-11-28 03:59 PM
原帖由 goodhermit95 于 2008-11-28 03:01 PM 发表
我很多问题啦~~而且很多地方怪怪的
Zero也说不建议用VS的VC++



這個見仁見智吧, 最主要是看你本身習慣使用哪種編譯器
作者: goodhermit95    时间: 2008-11-28 04:45 PM
标题: 回复 #27 Super-Tomato 的帖子
可能是不适合新手吧
现在我学VB容易得太容易,难的太难,所以想学其他语言




欢迎光临 JBTALKS.CC (https://jbtalks.my/) Powered by Discuz! X2.5