你如何检测 JavaScript 中的内存限制?

IT技术 javascript
2021-03-07 17:48:30

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

默认情况下,Firefox 似乎不会:

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

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

由于我们无法检测到可用内存,有没有其他方法可以告诉我们正在接近该限制?

更新

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

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

4个回答

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

大多数繁重的 Web 应用程序都会使用大约 10MB 的 JavaScript 堆大小。似乎没有指南。但我认为在桌面上消耗超过 100MB 并且在移动设备上消耗超过 20MB 并不是很好。之后查看本地存储的所有内容,例如FileSystem API(您可以完全使其持久化)

更新

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

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

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

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

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

似乎到那时,人们开始接受 50 MB 的 RAM 用于有用的网站。一旦你构建了你的 DOM 树,用测试数据填充你的数据结构,看看在 RAM 中保留多少是可以的。

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

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

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

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

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

其中,FileSystem 受支持最多,可以使用相当大的存储块

在 facebook 上滚动将内存从 13.7MB 增加到 30MB。在 Pinterest 上滚动一分钟左右,内存增加到 70MB,但它们有很多图像。
2021-05-14 17:48:30
在 Chrome 86+ 中,有一个measureMemory()performance.memory. web.dev/monitor-total-page-memory-usage
2021-05-15 17:48:30
+1 表示“消耗所有可用内存从来都不是一个好的选择
2021-05-20 17:48:30

在 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
在找到文档后我正要发布它,但我没有找到任何有关此功能的文档。这是可以依靠的东西吗?
2021-04-21 17:48:30
@RobW 它似乎是 Chrome 特定的功能(即它绝对不在 FF 中),我也找不到文档,它也不出现在 Web Performance 推荐轨道的一部分 - 请参阅w3.org/2010/webperfblogs.msdn.com/b/ie/archive/2013/05/21/...
2021-04-22 17:48:30
现在是 2017 年,我需要通过 JavaScript 网页传递数十 GB 的内存 - 而 Chrome 在达到其内存限制之前崩溃 - 会因回调而终止。
2021-05-04 17:48:30
@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/优化杀手
2021-05-19 17:48:30
@RobW我喜欢为yes告诉你,因为我看不出有任何理由为它在将来被移除(和Chrome的人使用它),但在所有诚实-我不知道。一旦我学会了如何编写更快的 JS(避免闭包、内联所有内容、单态函数、位掩码、回收属性),我就从未在客户端代码中以一种迫使我进行功能检测内存的方式达到性能限制(功能检测 CPU 负载是一个更可行和更简单)。我已经问过我熟悉的相关人员,希望我最终能得到答案。
2021-05-21 17:48:30

我想你会想要这样的东西:

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

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

由于 Web 应用程序无法访问任何与系统相关的信息(例如可用内存量),并且您不想让用户手动设置他们的性能设置,因此您必须依赖一种解决方案,允许您无需询问用户即可获取有关用户系统(可用内存)的此类信息。似乎不可能?嗯,差不多……

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

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

我不认为有一个简单的解决方案。这里是一些弊端,无论你选择做什么。请记住,Web 应用程序没有速度快的名声,因此如果性能至关重要,您应该考虑编写传统的桌面应用程序。

一个 Java 小程序?耶。我相当确定大多数 iPhone 浏览器不能运行 Java applet
2021-05-21 17:48:30