【问题标题】:How to fill memory as fast as possible in c#如何在 C# 中尽可能快地填充内存
【发布时间】:2015-09-08 08:19:55
【问题描述】:

一位面试官刚刚问了我一个我以前从未想过的奇怪问题。

“如何在 C# 中尽可能快地填充计算机的内存?”

我回答说我可能会使用某种递归函数,但他指出我可能会在填充内存之前发生堆栈溢出。

我的问题很简单,如何使用 C# 尽可能快地填充计算机的内存?

【问题讨论】:

  • “尝试访问 Oracle 数据库”。
  • 也许这个问题暗示了堆上的非托管资源,如图像或 gdi 对象。
  • 我会选择“我不会”:D
  • 面试官。当前的 JIT 编译器和之前的 x64 编译器使用尾递归优化,因此递归函数可能会也可能不会导致堆栈溢出
  • @Luaan 哈哈哈我开玩笑说这是我的第一个答案。这么奇怪的问题真是让我措手不及!

标签: c# memory-management


【解决方案1】:

我会选择一个叉形炸弹:

while (true) Process.Start(Assembly.GetExecutingAssembly().Location);

这个概念很熟悉,程序无休止地开始自己的新实例。

【讨论】:

  • 分配多个大缓冲区不是更快吗?
  • @TheodorosChatzigiannakis 是的,快得多。但是,空缓冲区不一定是从 RAM 中获取的——为此目的,有预置零的内存页面——它们仅在您实际写入一些数据时才分配。这是在操作系统级别完成的,因此很难绕过。制作一些图像的副本可能是一个更好的选择。不过,fork 炸弹的主要“优势”不是内存使用——而是它倾向于通过高优先级工作淹没整个计算机来杀死整个计算机。
  • 如何填充但不会导致页面错误并将页面移动到磁盘。
  • 这最终会使 CPU 占用更多,使系统无响应。这并不能完全回答问题。
  • @Josh 不是暗示吗?我们会编写任何程序,它应该可以在不崩溃的情况下运行吗?否则不会是“写程序崩溃”?
【解决方案2】:

我还没有尝试过,但我会选择类似的东西:

while(true) { Marshal.AllocHGlobal(1024); }

【讨论】:

  • 这肯定会引发 Out of Memory 异常。感谢您的回答,我认为这更多是我想要的,我的问题应该更清楚!
  • 我的意思不是消极的,这就是我想要的!填满内存但不让系统崩溃!
  • 是的,除非你编辑它,否则它看起来就像是一件坏事。我删除了我的评论:-)
  • 抱歉!我去打了一个新的线路,并在西方发布,再次感谢您的回答!
【解决方案3】:
  1. Fork-Bomb,这最终会使 CPU 非常繁忙,但不一定会填满内存。如果您有 GB 的内存和一个小程序,Windows MMU 最终可能会将未使用的(以前的分叉)交换到磁盘,并且仍然为其他程序保留可用内存。唯一的问题是,这不会填满内存,只会让系统无响应。

  2. 虚拟内存,通过使用 Marshal.AllocHGlobal 或类似函数分配巨大的对象,您可能认为您正在填充内存,但再次,但操作系统更聪明,如果您只是分配内存而不使用它们来读取再次,操作系统将再次将它们分页回磁盘,仍然没有占用所有内存。这仍然是虚拟内存,操作系统将允许您根据 .net 准则提供 MAX 内存,然后它将开始不再抛出内存,而不会实际消耗所有内存。

  3. 物理内存,现在这很棘手,首先,在任何应用程序中,在正常情况下,您都无法访问 Windows 中的物理内存。如果你真的要填充内存(物理内存)那么你必须编写一个内核模式驱动程序来做到这一点。

  4. AllocateUserPhysicalPages 函数。这是唯一允许您分配物理内存的 Windows API(以某种方式更快地填充内存)使其对其他进程不可用。 https://msdn.microsoft.com/en-us/library/aa366528(VS.85).aspx SQL Server 使用这个,我相信即使是其他数据库也会使用它来预分配物理内存,这个内存更快并且主要用于缓存目的。

【讨论】:

    【解决方案4】:

    创建一堆对象并避免它们被垃圾回收。

    调用 kill() 并享受。

    void kill()
    {
        while(true)
            ThreadPool.QueueUserWorkItem(fill));
    }
    
    void fill(Object o)
    {
        List<Object> list = new List<Object>();
        while(true)
            list.Add(new Object());
    }
    

    【讨论】:

      【解决方案5】:

      创建一个具有有效负载并实现终结器的类。然后产生一些最高优先级的线程,它们都创建这个类的实例。他们不必坚持他们,因为他们将进入终结者队列。终结器线程将无法跟上要终结的传入对象的速率,您将有效地填满进程内存。在 32 位系统上可能不足以填满计算机内存,但在 64 位系统上,您应该能够在大多数系统上使用。

      【讨论】:

        【解决方案6】:
        string text = File.ReadAllText("C:\\Test\\BigFile.any");
        

        更新

        我认为代码本身说明了一切。因此,请在您的计算机中找到任何大文件,例如位于“D:\Movies\BigMovieFile.mp4”之类的电影文件。并将该文件作为字符串读取,因为string 是非常消耗内存的类型。在 32 位应用程序中,1Gb 文件足以炸毁内存。由于 64 位应用程序将使用您计算机的所有内存,因此必须选择更大的文件或必须重复读取过程。 我认为这种方法会尽可能快。

        【讨论】:

        • 不鼓励使用纯代码的答案。请解释您的答案为何以及如何解决问题。
        • 找不到文件。
        猜你喜欢
        • 2014-08-18
        • 2021-06-23
        • 1970-01-01
        • 2016-08-23
        • 2011-03-13
        • 2016-01-23
        • 2015-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多