为什么node.js需要比c#更多的ram?

时间:2017-01-20 03:02:57

标签: .net memory-management v8

今天我测试了与Node.js相比,在c#命令行应用程序中需要多少内存。 这是我在Node.js中的代码:

"use strict";

class User{
    constructor(firstname, lastname){
        this.firstName = firstname;
        this.lastName = lastname;
    }
}

const count = 10000000;
const users = [];

console.time('Allocating Elements');

for (let i = 0; i < count; i++) {
    users.push(new User(`John${i}`,`Doe${i}`));
}

console.timeEnd('Allocating Elements');
console.log('Finished');

这是我在C#中的代码:

class User
    {
        public string firstName { get; set; }
        public string lastName { get; set; }

        public User(string firstname, string lastname)
        {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var count = 10000000;
            var users = new List<User>();

            var sw = Stopwatch.StartNew();

            for (var i = 0; i < count; i++)
            {
                users.Add(new User($"John{i}", $"Doe{i}"));
            }

            sw.Stop();
            Console.WriteLine($"Allocating Elements: {sw.ElapsedMilliseconds}");
            Console.WriteLine("Finished");
        }
    }

两个程序都以64位执行。

当我在c#中使用类型对象列表时,ram消耗大致相同。

所以我的问题是:如果我在c#中使用User类,为什么Node需要大约4倍的ram?这样的优化怎么可能?

我附上了两个进程的ram用法的截图,当它们最后站在一个断点时。

Screenshot

2 个答案:

答案 0 :(得分:1)

我无法对C#发表评论,但我可以告诉你V8为你的例子消耗了多少内存。对于每个User对象,它都需要:

&#34;用户&#34;对象本身:

  • &#34;隐藏的课程&#34;指针(对象布局描述)
  • &#34;属性&#34;指针(用于清​​空后备存储)
  • &#34;元件&#34;指针(用于清​​空后备存储)
  • &#34;的firstName&#34; in-object属性(到firstNameString,见下文)
  • &#34; lastName的&#34; in-object属性(to lastNameString,见下文)

firstNameString,lastNameString:

  • &#34;隐藏的课程&#34;指针(将此对象标识为字符串)
  • string hash
  • 字符串长度
  • 字符串字符:&#34; John1234&#34;
  • 字符串字符:&#34; 567 _____&#34;

(字符串对象向上舍入到指针大小对齐。前10,000和#34; John&#34;字符串和前100,000&#34; Doe&#34;字符串每个只包含四个单词,但与总共有20,000,000个字符串,这个影响可以忽略不计。)

最后:

  • users数组
  • 中的一个广告位

当你全部添加时,你有5 + 2 * 5 + 1 = 16个指针,每个8字节,或者1220MB,1000万用户。 当我在d8(V8的开发人员shell)中运行代码并强制GC最终清理剩余的废弃物时,我看到消耗了1258MB。区别在于:

  • 一般环境开销(JavaScript全局变量,在启动时设置的某些引擎内部)
  • 阵列后备存储的一些过度分配(正如Joel Coehoorn已经指出的那样)
  • 在node.js中的
  • ,我的猜测是配置了一个更大的最大堆大小,所以GC还没有启动。一旦出现内存压力或空闲时间,它应该清理得更多。

答案 1 :(得分:0)

抱歉,我花了这么长时间才写下来。但似乎我忽略了一些东西。这很尴尬,但我真的没有先看到它。实际上,两个程序在执行期间几乎都需要相同数量的RAM。我的失败是C#代码中User对象的构造函数。

    public User(string firstname, string lastname)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }

我分配了&#34; firstName&#34;和&#34; lastName&#34;变量本身而不是传递给构造函数的参数。因为这个错误&#34; firstName&#34;和&#34; lastName&#34;在跑步期间是空的。这当然导致了所需RAM量的减少。

对不起伙计们。但感谢答案。我无法相信我没有看到它。