• 这个内存不足的家伙是谁?当我有足够的内存,为什么他让我的进程崩溃?


    为了回答这个问题,我们需要讨论几个概念。
    在32位系统上工作时,可以寻址4GB内存,其中2GB通常保留给操作系统,每个用户模式进程(如w3)允许有2GB内存wp.exe文件(asp.net)例如。这个内存称为虚拟内存,2GB是2GB,与系统中添加的RAM数量无关。RAM的数量只是决定了你需要做多少分页和交换,也就是说内存访问的速度。
    当一个进程分配内存时,它首先保留虚拟内存,然后从这个块中提交内存(这是实际使用的内存)。提交的内存称为私有字节。虚拟地址空间用于处理过程中的许多不同项目,例如:

    • Dll’s
    • Native heaps (non .net heaps)
    • Threads (each thread reserves 1 MB for the stack)
    • .net heaps (for managed variables)
    • .net loader heap (for assemblies and related structures)
    • Virtual allocations made by com components

    虚拟内存分配不一定(或很少)在内存中很好地排列。例如,dll具有首选的加载地址,因此它们之间留有间隙,而已取消分配的虚拟分配也将留下间隙。这意味着,即使您可以寻址2GB的虚拟内存,但您可能无法全部使用,因为当使用了足够的内存时,内存将看起来有点像瑞士奶酪,并且您的插头可能没有一个足够大的孔来容纳。
    这是当您得到一个OutOfMemory异常时发生的情况。
    在.net框架中,垃圾收集器(我们的内存管理器)以堆的形式保留虚拟内存。一旦创建了这些堆,并且我们创建了一个.net对象的新实例,这个对象就被存储在这些堆段中,并提交了内存。
    在.NETFramework中,常规的.net堆是在64MB段中创建的。(如果您有8个以上的处理器或手动更改了设置,则会发生变化,但我暂时忽略这一点,并讨论常见情况)
    这些64MB的段需要在一个大的块中分配,你不能在这里分配32 MB,在那里分配32 MB,所以当你填满了其中一个64 MB的段并且需要创建一个新的段时,你需要在2GB内存空间中找到一个64 MB或更多的空白。如果不存在这样的间隙,则会出现内存不足异常。
    这些OutOfMemory异常通常不是致命的,但仍然很糟糕,因为它们使进程处于不稳定状态。但是,当垃圾回收器需要进行收集时,它需要内部结构的空间才能进行此收集,并且使用的内存和对象越多,这些结构就越大。如果垃圾回收器没有足够的空间进行收集,则会出现致命的内存不足异常,进程将停止。
    保留内存(性能监视器中的虚拟字节)将比提交的字节(性能监视器中的专用字节)大得多。通常,当内存使用率很高时,差异大约在500 MB左右,而在大约1.2-1.4 GB左右的虚拟字节时,很难找到这些64MB的漏洞,这意味着一个正常的.net进程将在800 MB左右开始脱离内存异常。
    同样,这个值会因应用程序、加载的dll和本机com组件的内存分配模式等而异。
    现在你知道为什么即使你有很多内存,你也能摆脱内存异常,下一个任务就是找出为什么你要使用这么多内存。

  • 相关阅读:
    Asp.net 后台添加CSS、JS、Meta标签(帮助类)
    Jquery 事件冒泡
    一个例子理解C#位移
    CodeSmith 创建Ado.Net自定义模版(四)
    .NET4.0下网站应用程序用UrlRewriter.dll重写无后缀路径 (在IIS7.5中的配置方法)
    用泛型的IEqualityComparer<T>接口去重复项
    Why MapReduce?
    SYN flood攻击介绍
    tmux使用方法详解
    理解Linux系统负荷
  • 原文地址:https://www.cnblogs.com/yilang/p/13500343.html
Copyright © 2020-2023  润新知