【问题标题】:How do you detect memory limits in JavaScript?你如何检测 JavaScript 中的内存限制?
【发布时间】:2014-06-23 17:42:14
【问题描述】:

浏览器能否对可存储在 JavaScript 对象中的数据量施加任何形式的限制?如果是这样,有什么方法可以检测到这个限制吗?

默认情况下,Firefox 似乎没有:

var data;
$("document").ready(function() {
  data = [];
  for(var i = 0; i < 100000000000; i++) {
    data.push(Math.random());
  }
});

这会继续消耗越来越多的内存,直到我的系统用完为止。

既然我们can't detect available memory,有没有其他方法可以告诉我们正在接近这个限制?

更新

我正在开发的应用程序依赖于非常快的响应时间才能使用(这是核心卖点)。不幸的是,它也有一个非常大的数据集(超过了在较弱的客户端机器上的内存)。通过策略性地抢先加载数据(猜测将点击什么)可以大大提高性能。当猜测不正确时,从服务器加载数据的回退是有效的,但服务器往返并不理想。我可以利用每一点内存使应用程序尽可能高效。

目前,它允许用户“配置”他们的性能设置(最大数据设置),但用户不想管理它。此外,由于它是一个 Web 应用程序,我必须处理用户对每台计算机的设置(因为功能强大的桌面比旧 iPhone 具有更多的内存)。如果它只使用系统上可用的最佳设置,那就更好了。但是猜测太高也会导致客户端计算机出现问题。

【问题讨论】:

  • 如果您正在处理非常大的数据集,请考虑使用惰性流或迭代器。那里有几个库,不要脸的插件github.com/elclanrs/continuous.js
  • 这是一个很好的问题,但您可能应该讨论您的实际问题/用例,因为它可能有一个更倾斜的解决方案。
  • @elclanrs 服务器端其实是多种语言。 Ruby 和 NodeJS 可能是最相关的。数据纯粹是性能优势。加载数据后,用户会立即单击一次。通过服务器往返(甚至通过 websocket),用户可以感觉到延迟。同样,这是应用程序有用性的核心。
  • 假设磁盘寻道延迟没问题,您可以将数据缓存在 IndexedDB 中,并仅在需要时将其加载到内存中。
  • @LeviStanley 为什么要将所有数据保存在内存中?

标签: javascript


【解决方案1】:

由于网络应用无法访问任何与系统相关的信息(例如可用内存量),并且您不希望让用户手动设置其性能设置,您必须依靠一种解决方案,该解决方案允许您在不询问用户的情况下获取有关用户系统(可用内存)的此类信息。似乎不可能?嗯,差不多……

但我建议您执行以下操作:制作一个 Java 小程序,它将自动获取可用内存大小(例如,使用带有适当命令的 Runtime.exec(...)),前提是您的小程序已签名,并将该信息返回到服务器或直接返回到网页(用JSObject,见http://docs.oracle.com/javafx/2/api/netscape/javascript/JSObject.html)。

但是,这假设您的用户都可以在他们的浏览器中运行 Java 小程序,但情况并非总是如此。因此,您可以要求他们在他们的机器上安装一个小软件,该软件将测量您的应用程序在不使浏览器崩溃的情况下应该使用多少内存,并将该信息发送到您的服务器。当然,你必须为每个操作系统和架构(Windows、Mac、Linux、iPhone、Android……)重新编写那个小程序,但是为了获得一些东西而重新编写整个应用程序更简单表现。这是一种介于两者之间的解决方案。

我认为没有简单的解决方案。无论您选择做什么,都会有一些缺点。请记住,Web 应用程序并不以速度快而著称,因此如果性能至关重要,您应该考虑编写传统的桌面应用程序。

【讨论】:

【解决方案2】:

在 Chrome 中,答案是肯定的!

转到控制台并输入:

performance.memory.jsHeapSizeLimit; // will give you the JS heap size
performance.memory.usedJSHeapSize; // how much you're currently using

arr = []; for(var i = 0; i < 100000; i++) arr.push(i);
performance.memory.usedJSHeapSize; // likely a larger number now

【讨论】:

  • 我正要在找到文档后发布,但我没有找到任何有关此功能的文档。这是可以依靠的东西吗?
  • @RobW 这似乎是 Chrome 特有的功能(即它绝对不在 FF 中),我也找不到文档,也没有出现在 Web Performance 推荐轨道中 - 请参阅w3.org/2010/webperf , blogs.msdn.com/b/ie/archive/2013/05/21/…
  • @RobW 我喜欢告诉你是的,因为我认为将来没有理由将其删除(Chrome 用户也会使用它),但老实说 -我不知道。一旦我学会了如何编写更快的 JS(避免闭包、内联所有内容、单态函数、位掩码、回收属性),我就再也没有以迫使我检测 memory 的方式达到客户端代码的性能极限(检测 CPU 负载的功能更加可行和简单)。我已经问过我熟悉的相关人员,希望最终能得到答案。
  • @falsarella 是的,但是如何编写快速的 JS 是一本书的主题,而不是 Stack Overflow 的答案。这里有一些提示可以帮助您入门 addyosmani.com/blog/writing-fast-memory-efficient-javascript mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html github.com/petkaantonov/bluebird/wiki/Optimization-killers
  • 现在是 2017 年,我需要通过 JavaScript 网页传递数十 GB 的内存 - Chrome 在达到内存限制之前会崩溃 - 会因为回调而终止。
【解决方案3】:

虽然在某些浏览器上可能可行,但正确的方法应该是确定典型客户可以接受的限制,并可选择提供 UI 来定义他们的限制。

大多数繁重的 Web 应用程序都使用大约 10MB 的 JavaScript 堆大小。似乎没有指导方针。但我想在台式机上消耗超过 100MB 而在移动设备上消耗 20MB 并不是很好。对于之后的所有内容,请查看本地存储,例如FileSystem API(你完全可以让它持久化)

更新

这个答案背后的原因如下。几乎从不用户只运行一个应用程序。依靠只打开一个标签的浏览器更是如此。最终,消耗所有可用内存绝不是一个好的选择。因此不需要确定上边界。

用户想要分配给网络应用程序的合理内存量是一种猜测。例如。高度交互的数据分析工具在 JS 中是很有可能的,并且可能需要数百万个数据点。一种选择是默认为较低的分辨率(例如,每天而不是每秒测量一次)或更小的窗口(一天与十年秒)。但随着用户不断探索数据集,将需要越来越多的数据,这可能会削弱代理端的底层操作系统。

好的解决方案是采用一些合理的初始假设。让我们打开一些流行的Web应用程序,然后去开发工具-配置文件-堆快照看看:

  • FB:18.2 MB
  • GMail:33 MB
  • Google+:53.4 MB
  • YouTube:54 MB
  • 必应地图:55 MB

注意:这些数字包括堆上的 DOM 节点和 JS 对象。

似乎在那时,人们开始接受 50MB 的 RAM 用于一个有用的网站。 2022 年更新: 现在平均接近 100MB。) 构建 DOM 树后,用测试数据填充数据结构,看看可以在 RAM 中保留多少。

在 Chrome 中打开设备模拟​​时使用类似的测量值,可以看到平板电脑和手机上相同网站的消费情况,顺便说一句。

这就是我在台式机上达到 100 MB,在手机上达到 20 MB 的方式。似乎也很有道理。当然,对于偶尔的重度用户来说,可以选择将最大堆增加到 2 GB。

现在,如果每次从服务器抽取所有这些数据的成本太高,你会怎么做?

一件事是使用应用程序缓存。它确实会造成轻微的版本管理问题,但允许您存储大约 5 MB 的数据。与存储数据相比,将应用代码和资源保存在其中更有用。

除此之外,我们还有三个选择:

其中,文件系统最受支持,可以使用sizable chunk of storage

【讨论】:

  • +1 表示“消耗所有可用内存绝不是一个好的选择
  • 在 facebook 上滚动将内存从 13.7MB 增加到 30MB。在 Pinterest 上滚动一分钟左右后内存增加到 70MB,但它们有很多图像。
  • 在 Chrome 86+ 中有一个新的 API measureMemory(),它比 performance.memory 更准确。见web.dev/monitor-total-page-memory-usage
【解决方案4】:

我认为您会想要以下内容:

const memory = navigator.deviceMemory
console.log (`This device has at least ${memory}GiB of RAM.`)

您可以查看以下内容:https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory

注意:并非所有浏览器都支持此功能。

【讨论】:

    猜你喜欢
    • 2021-09-27
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 2016-12-11
    • 1970-01-01
    • 2014-02-06
    相关资源
    最近更新 更多