【问题标题】:How to free virtual memory?如何释放虚拟内存?
【发布时间】:2011-02-27 00:29:49
【问题描述】:

我有一个从 web 下载页面的爬虫应用程序(使用 C#)。 应用程序占用更多的虚拟内存, 甚至我处理所有对象,甚至使用GC.Collect() .

这个,有 10 个线程,每个线程都有一个下载页面的套接字。 在每个线程中,我都有一个byte[] buffer 来存储页面内容,并且有 我存储在其中的string str_content,字符串中的页面内容。 我有一个Sytem.Timer,每 3 秒检查一次,如果每个线程都已停止, 为其分配新线程并启动它。

我使用 dispose 方法,甚至在我的应用程序中使用 GC.Collect(),但在 3 小时内我的应用程序需要 500 MB 虚拟内存(进程资源管理器中的私有字节 500 MB)。然后我的系统 将挂起,我应该重新启动我的电脑。

  1. 如果我将我的 byte[]string 分配为 null 会很粗鲁吗?

  2. 有什么方法可以释放虚拟内存吗?

谢谢。

【问题讨论】:

  • 使用分析器查找内存泄漏。

标签: c# memory virtual garbage-collection


【解决方案1】:

首先,无论如何,您都不应该调用 gc.collect(),因为这是一个代价高昂的调用,而且没有必要。

如果您看到增长并且仍在致电gc.collect(),则您的资源仍有参考,因此无法收集。

我将开始查看您的代码并确保您的所有对象都在适当的范围内声明,您使用 Using 语句语法来确保正确清理实现 IDisposable 的项目并全面审查您的代码。

下一步是使用 ANTS profiler 之类的工具,查看内存中实际存储的内容。

【讨论】:

  • 实际上调用 GC 收集可能是问题所在 - 对象进入更高代最终进入“从不收集”区域。
  • @TomTom - 实际上,如果您查看文档,这不是真的,所有世代都是用 gc.collect() 收集的 - msdn.microsoft.com/en-us/library/xe0c2357.aspx
【解决方案2】:

需要探索您的代码才能查看内存泄漏的位置。您正在绑定的事件(手动或自动)可能会导致明显超出范围的对象无法正确处置。

【讨论】:

    【解决方案3】:

    在 C#(和 Java)中,只要您引用了对象,程序环境就会假定您仍在使用该对象。调用释放内存只会释放未使用的对象。关键是停止使用对象。

    你有这样的机会非常好:

    Object mine = new Object();
    

    关键是你还需要类似的东西:

    mine = null;
    

    表示“我的”对象不再被使用。通常这些问题不会发生在这样的代码块中,因为一旦您离开代码块,就无法再访问变量了:

    public void process() {
      Object mine = new Object();
    }
    

    这些问题通常发生在这样的代码块中,因为 Collection 会随着时间的推移积累对象:

    static List tasks = new ArrayList();
    
    public void process(String item) {
      tasks.add(item);
    }
    

    关键是如果没有相应的tasks.remove(item),列表将永远保存对项目的引用,从而阻碍垃圾收集工作。

    【讨论】:

    • 这似乎解决了我的内存泄漏问题!!我清除了一个列表,但实际上并没有“取消引用”它,所以它没有被收集。谢谢!!
    • @mgrenier 很高兴听到。清除列表会做很多事情,但取消引用它将获得“最后一个”列表对象。
    • 它实际上只是我的问题的一部分,我有一个锁,它占用了几个内存位置,结果证明这是一个很大的瓶颈。我把它分成 5 个锁来处理不同的内存位置,并释放了一堆根本不需要锁定的代码。只是想我会提到它,以防它可以帮助其他人......对我来说有一段时间来解决这个问题!
    猜你喜欢
    • 2015-12-17
    • 1970-01-01
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    相关资源
    最近更新 更多