2014-12-05 52 views
1

我有一个25MB的json文件,我“需要”为什么我的应用程序启动。初看起来,node.js进程似乎占用了将近200MB的内存。为什么node.js突然使用更少的内存?

但是如果我让它运行并回到它,活动监视器报告它只使用了9MB,这根本没有意义!至少,它应该是更多MB,因为即使是一个简单的node.js应用程序几乎不做任何事(就像服务器一样),使用9MB。

该应用程序似乎工作正常 - 它是一个服务器,提供搜索建议形成一个220,000字的单词列表。

活动监视器是否错误? 为什么它只使用9MB,但最初在应用程序启动时使用〜200MB?

+5

因为它做的东西使用了大量的内存,那么该内存得到GCed? – 2014-12-05 15:38:38

+0

它最初将使用内存卡来加载程序并进行编译,一旦完成,它将清除相当一部分内存。怀疑这将占据200mb的头脑。 – DoctorMick 2014-12-05 15:39:20

+2

加载一个25mb的字符串并处理它会花费很多,但是一旦发生这种情况,解析25mb json所需的所有内存都可以被收集,只剩下一个(精简的)内存结构。 – spender 2014-12-05 15:41:33

回答

1

由于是JavaScript,不再使用的东西通过垃圾收集器(GC)被移除,释放内存。一切(或许多事情)在开始时可能已经加载到内存中。然后不再需要的项目被GC从内存中移除。通常情况下,生成过程可能会占用更多内存,之后会丢失一些内存,例如临时数据结构可能正在使用中,但在完成此过程时不再需要。

这也可能是内存中的项目暂时交换出来并写入磁盘(可能稍后会检索),这种交换是由您的操作系统完成的,并且倾向于更多地用于保留大量内存的程序。

0

加载文件需要多少内存取决于许多因素

正在使用什么文本编码来存储文件? JavaScript在内部使用UTF-16,因此如果这不是磁盘上使用的内容,则大小可能不同。例如,如果文件采用UTF-32格式,那么内存中的UTF-16版本将会变小,除非它充满了星体。如果文件使用UTF-8格式,则情况会相反:内存版本将更大,除非它充满了星体。但现在,让我们假设它们的大小差不多,或者是因为它们使用了相同的编码,或者是星际模式恰好使文件大小差不多相同。

你说得对,加载文件需要至少25MB(假设编码不会干扰)。 JSON API的语义就是它们,你需要将整个文件作为一个字符串存储在内存中,所以当时应用程序至少占用了那么多内存。这不会计算解析器需要运行的任何内容,所以您至少需要34MB:25的文件,9的Node,然后无论您的特定应用程序用于自己。

但是你的应用并不需要所有的内存。根据你编写应用程序的方式,你可能在某些时候摧毁了你对文件的引用。 由于JSON的语义,没有办法避免将整个文件加载到内存中,这需要25MB,因为这是文件的大小。也无法避免占用JSON解析器完成工作和构建对象所需的任何内存。

但是,根据您编写应用程序的方式,当您不再需要该数据时,可能会出现一个问题。您可以退出您用于加载文件的函数,也可以将该变量分配给其他项或其他任何可能的项。然而,它发生,JavaScript回收不再使用的内存。这被称为垃圾回收,它在所谓的“脚本语言”中很受欢迎(尽管其他编程语言也可以使用它)。

还有文字表示与内存表示的问题。除非您更改编码,否则字符串需要的内存空间与磁盘空间相同,但Numbers和Booleans完全是另一回事。在JavaScript中,所有Numbers都是64位浮点数,所以如果磁盘上的大部分数字长度超过四个字符,则内存中的表示将会更小,可能会相当多。请注意,我说的是字符,而不是数字:数字是字符,但是+, - ,e和。也是字符,因此-1e0在写为文本时占用的空间是-1的两倍,尽管它们在内存中表示相同的值。作为另一个例子,3.14占用与文本1000一样多的空间(并且恰好占用相同数量的内存空间:每个64位)。但-0.00000001和100000000占用的内存空间比磁盘少得多,因为内存中的表示更小。布尔变得更小:不同的引擎以不同的方式存储它们,但是理论上你可以在一个小时内完成它。这与存储“真”所需的8个字节或存储“假”的10个字节相差甚远。

因此,如果您的数据主要是关于Numbers和Booleans,那么内存中的表示会变得更小。如果它主要是弦乐,那么不是那么多。

相关问题