即使是C#中的简单记事本应用程序也会消耗数百万字节的RAM,如任务管理器中所示.在最小化应用程序时,任务管理器中的内存大小显着下降,并在应用程序最大化时备份.
我在某处读到.NET进程预先为运行时分配保留了大量内存.这就是.NET应用程序开始时拥有更大内存占用的原因.但是可以使用Win32 API调用释放此内存.权衡是运行时分配变慢 - 这是真的吗?
在以下程序中,虽然执行了垃圾收集,但不会重新获得内存初始大小的大小.1.内存的初始大小是总内存:16,940字节专用字节8134656
在循环内创建对象,以便在循环外部完成gc collect时释放这些对象,因为这些对象没有其范围.
但GC收集后的内存与初始大小不同总内存:29,476字节专用字节8540160处理数:115
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MemoryLeakTest
{
class Program
{
static void DisplayMemory()
{
Console.WriteLine("Total memory: {0:###,###,###,##0} bytes", GC.GetTotalMemory(true));
Console.WriteLine("Private bytes {0}", System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64);
Console.WriteLine("Handle count: {0}", System.Diagnostics.Process.GetCurrentProcess().HandleCount);
Console.WriteLine();
}
static void Main()
{
DisplayMemory();
GC.Collect();
for (int i = 0; i < 5; i++)
{
Console.WriteLine("--- New object #{0} ---", i + 1);
object o = new object();
GC.Collect();
DisplayMemory();
}
Console.WriteLine("--- press any key to quit ---");
Console.WriteLine();
Console.Read();
GC.Collect();
DisplayMemory(); …Run Code Online (Sandbox Code Playgroud) 我如何获得C#应用程序中使用的实际内存?
我不知道该相信哪一个.
我有一个C#/ .NET 4.0应用程序,当我启动时显示两个窗口,其中包含大约十几个控件.当我运行我的程序(调试或发布无关紧要)时,在我甚至做任何事情之前,我在任务管理器/资源监视器中看到我的程序已经有超过450MB的私有内存.我意识到任务管理器不是测量内存使用率最可靠的方法,但它是我用户最明显的方法之一.
当我运行VS2010 .NET内存分配性能分析时,对于我的程序的完整运行,它报告实际分配给托管对象的大约5MB的RAM(我的程序通常也使用一些非托管对象,但它们非常小并且对于简化这项调查我已禁用它们,但没有显着效果).同样,如果我在显示主表单后从psapi.dll调用EmptyWorkingSet(),我的私有内存将降至~3.5 MB.
我已经在这里和这里查看了有关内存占用的问题,但这些问题似乎与处理几十兆字节的程序有关.我的程序显示近500MB,看起来更令人担忧.
我无法想象所有这一切都来自开销; 为什么VS Profiler和任务管理器之间存在如此巨大的差异?
更新:有趣的是,如果我注释掉设置ImageLists的InitializeComponent()部分,任务管理器中的数字将保持在10MB以下.我有两套PictureBoxes和ImageLists,其中PictureBox显示四个图像中的一个,具体取决于选中单选按钮组中的哪个单选按钮.
这些代码行似乎会触发大量内存增加:
//
// directionImageList
//
this.directionImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("directionImageList.ImageStream")));
this.directionImageList.TransparentColor = System.Drawing.Color.White;
this.directionImageList.Images.SetKeyName(0, "Dir1.png");
this.directionImageList.Images.SetKeyName(1, "Dir2.png");
this.directionImageList.Images.SetKeyName(2, "Dir3.png");
this.directionImageList.Images.SetKeyName(3, "Dir4.png");
//
// modeImageList
//
this.modeImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("modeImageList.ImageStream")));
this.modeImageList.TransparentColor = System.Drawing.Color.White;
this.modeImageList.Images.SetKeyName(0, "Mode1.png");
this.modeImageList.Images.SetKeyName(1, "Mode2.png");
this.modeImageList.Images.SetKeyName(2, "Mode3.png");
Run Code Online (Sandbox Code Playgroud)
我正在使用ImageLists,所以我可以使用透明度.模式图像为100x100,每个占用<26KB的磁盘空间.方向图像默认为208x277,磁盘大约为75KB.我知道png是一种压缩格式,但即使在内存中未压缩,我也不会期望这七张图片有数百兆字节.
是否有一些我所知道的低效率,是否有另一种动态显示透明图片的方法?
结论: ImageList类有些东西可疑.有时它会丢失alpha通道,这导致我的程序保留了比它需要的更多内存.它也减慢了最初绘制主窗体的时间(在运行时和在设计器中).
倾倒两个ImageLists使我的程序降低到更健康的10MB RAM.感谢大家的所有建议!
基于StackOverflow 上的Memory Efficient Programming问题.....我想了解Memory Efficient C#Programming ....任何关于Memory Efficient C#编程的好网站/博客/书籍......
编辑:
一些提示如何编写内存高效的C#编程....
我们有一种情况,我们正在考虑在RAM非常低的服务器上强制进行垃圾收集(平均使用3.6/4GB).不,不幸的是,升级此服务器并不是一个真正的选择.
我们的一个服务进程(用C++间接编写(不要问...))可以使用.NET组件,然后睡10分钟.当该服务处于休眠状态时,它通常会挂在可以与其他进程共享的600MB RAM上.似乎某种方式与WSE跟踪有关,用于调试.我可以看到它在第一次COM调用.NET的下一次迭代时唤醒和GC - 然而这个过程做了一些工作,当它进入睡眠状态时,RAM使用量恢复到大约600MB ......好吧,你可以看出这是怎么回事......
问题:我正在考虑在进程进入睡眠状态之前添加垃圾收集.此框中还有其他服务正在执行与.NET相关的任务.当我在此服务进程中调用垃圾收集时,该GC是否影响该框上的所有其他.NET相关进程或仅影响请求收集的进程?我有点担心为我所关心的流程之外的流程创建某种性能问题.
我可以配置C#应用程序将其内存消耗限制为200MB吗?IOW,我不想等待自动GC(这似乎使堆的增长超出了此应用程序的实际需求)。
我知道在Java中有一个命令行开关,您可以将其传递给实现此目标的JVM。.在C#中是否等效?
ps
我知道我可以从代码中调用GC,但这是我宁愿不必定期执行的操作。我宁愿以某种方式在启动时设置它,然后忘记它。
我寻求建议,要么证明或消除我团队中的信念(显然没有理由).相信是开始一个新的.Net应用程序进程是昂贵的内存(每个进程20MB及以上).虽然我指出应用程序显然没有使用那么多(如内存分析器中所见),但他们反驳说它不是应用程序,而是.Net Framework的运行时消耗内存.
这是基于他们在某处听到的东西,所以没有确凿的证据存在,但这种信念在团队中根深蒂固.我已经google了一下,但是我找不到对.Net Framework运行时的每个进程成本的任何认真分析.虽然我根本无法接受每个.Net过程都很昂贵(虽然我愿意承认我可能错了),但我不太了解我的观点.另一方面,我的队友不足以证明我是错的.有谁知道有关此事的任何研究/分析?
谢谢.
我注意到通常的高内存大小.我写的一个应用程序是一个使用<50lines的控制台应用程序,只使用WebRequest下载一系列文件.另一个不重要的应用程序(mysql,dls,多线程,包含100个项目的列表框).第一个使用21 MB(debug,ide),另一个使用39mb(debug,ide).我还有另一个应用程序轮询我的网站(也使用WebRequest)进行状态更新,该更新位于我的托盘上并使用26mbs通知我(发布,不通过ide).
为什么这么高?我知道我上面写了一个C++应用程序,使用curl运行<2mb,我最大的C++ prj是11mb,加载100kb dll和200kb二进制文件(使用带有win32图标和声音的directx).我如何编译我的C#代码,使其更加空间友好.我想将这些部署到一台服务器,该服务器可能只有128或256mb ram,其中一些应用程序会杀死它.
网站注意:我在发布模式(并通过ide)运行了第一个提到的应用程序(控制台DLer),它跳到了32mb.为什么!?!这更令人困惑.
我在我的一本大学书中遇到了一个令人困惑的问题:在那里声明"堆不是静态的,可以根据需要通过从操作系统请求更多内存来增长".
所以我很困惑的是:假设我运行我的应用程序,并在堆上分配对象.在某些时候,应用程序内存不足:现在发生了什么?
根据我的理解,Gc(垃圾收集器)开始并开始它的标记和扫描操作.我想知道不管怎样,而不是通过CLR调用Gc,堆是否有可能从操作系统请求更多内存?
我读到在C++语言中,有一种方法可以实现这一点,但在C#.Net Framework 4.5中是否可行?