降低Winform占用系统内存的方法-将物理内存的占用挪到虚拟内存里

  降低Winform占用系统内存的方法-将物理内存的占用挪到虚拟内存里:

刚刚验收项目是通过Socket通信控制一个库室中所有板子的项目,通过C# WinForm实现的一个PC客户端,但是.NET 的问题一直就是狂吃内存,虽然说内部提供了GC 的功能和智能化,但是内存的回收问题,一直存在困扰,特别是本项目使用的 Winform 程序,由于.NET程序在启动时,是需要由JIT动态编译并加载的,这个加载会把所有需要的资源都加载进来,很多资源是只有启动时才用的。同时由于通过socket控制的板子比较多,运行一天后程序占的内存很多

  常用来降低Winform占用系统内存的方法有大概下面几种:

1. 使用性能测试工具dotTrace 3.0,它能够计算出你程序中那些代码占用内存较多

2. 强制垃圾回收

3. dispose,close

4. 用timer,每几秒钟调用:SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1)

5. 什么情况下会在堆(栈)上分配数据?它们有性能上的区别吗?

6.“结构”对象可能分配在堆上吗?什么情况下会发生,有什么需要注意的吗?

7. 发布的时候选择Release

8. 注意代码编写时少产生垃圾,比如String + String就会产生大量的垃圾,可以用StringBuffer.Append

9. this.Dispose(); this.Dispose(True); this.Close(); GC.Collect();

10. 注意变量的作用域,具体说某个变量如果只是临时使用就不要定义成成员变量。GC是根据关系网去回收资源的

11. 说说值类型和引用类型的生命周期?

12. 检测是否存在内存泄漏的情况

 

  认识SetProcessWorkingSetSize的方法:

可以,试试看把一个程序最小化到任务栏,再看看任务管理器,看到没,你的程序占用的实际内存一下子减少了,看来并不是我有什么方法能够压缩内存,而是操作系统本身就有这个机制,即当程序不使用时(最小化),操作系统会调用某些命令,来将该程序占用的内存移至虚拟内存,只保留一小部分常规代码

所以我们就看到了 这种情景,占用的内存一下子就缩小了。 那么:系统到底调用了什么指令呢?能不能在不缩小窗体的情况下来释放内存呢?

看看这个API SetProcessWorkingSetSize 这是从MSDN摘下的原话

Using the SetProcessWorkingSetSize function to set an application's minimum and maximum working set sizes does not guarantee that the requested memory will be reserved, or that it will remain resident at all times. When the application is idle, or a low-memory situation causes a demand for memory, the operating system can reduce the application's working set. An application can use the VirtualLock function to lock ranges of the application's virtual address space in memory; however, that can potentially degrade the performance of the system. 使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存。当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存。应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放。

When you increase the working set size of an application, you are taking away physical memory from the rest of the system. This can degrade the performance of other applications and the system as a whole. It can also lead to failures of operations that require physical memory to be present; for example, creating processes, threads, and kernel pool. Thus, you must use the SetProcessWorkingSetSize function carefully. You must always consider the performance of the whole system when you are designing an application. 当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立 进程,线程,内核池,就必须小心的使用该函数。

事实上,使用该函数并不能提高什么性能,也不会真的节省内存。 因为他只是暂时的将应用程序占用的内存移至虚拟内存,一旦,应用程序被激活或者有操作请求时,这些内存又会被重新占用。如果你强制使用该方法来 设置程序占用的内存,那么可能在一定程度上反而会降低系统性能,因为系统需要频繁的进行内存和硬盘间的页面交换。

BOOL SetProcessWorkingSetSize
( HANDLE hProcess, SIZE_T dwMinimumWorkingSetSize, SIZE_T dwMaximumWo )

  

将 2个 SIZE_T 参数设置为 -1 ,即可以使进程使用的内存交换到虚拟内存,只保留一小部分代码

当然,该函数也并非无一是处,

1 。当我们的应用程序刚刚加载完成时,可以使用该操作一次,来将加载过程不需要的代码放到虚拟内存,这样,程序加载完毕后,保持较大的可用内存。

2.程序运行到一定时间后或程序将要被闲置时,可以使用该命令来交换占用的内存到虚拟内存

  具体实现:

 1 //需要引用的命名空间
 2 using System.Diagnostics;
 3 using System.Runtime.InteropServices;
 4 
 5 [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
 6 public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);
 7 /// <summary>
 8 /// 释放内存
 9 /// </summary>
10 public static void ClearMemory()
11 {
12     GC.Collect();
13     GC.WaitForPendingFinalizers();
14     if (Environment.OSVersion.Platform == PlatformID.Win32NT)
15     {
16         SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
17     }
18 }
19 /// <summary>
20 /// 获取应用内存
21 /// </summary>
22 /// <returns></returns>
23 public static float getMem()
24 {
25     string procName = Process.GetCurrentProcess().ProcessName;
26     using (PerformanceCounter pc = new PerformanceCounter("Process", "Working Set - Private", procName))
27     {
28         float r = (pc.NextValue() / 1024 / 1024);
29         return r;
30     }
31 }

 

版权所有,文章来源:http://www.cnblogs.com/sagecheng/articles/5961383.html

个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。

.NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引

 

 

posted @ 2016-10-14 17:34  小智Owner  阅读(271)  评论(0编辑  收藏  举报