【问题标题】:Possible to check 'available memory' within a browser?可以在浏览器中检查“可用内存”吗?
【发布时间】:2021-04-07 11:03:17
【问题描述】:

我只是在编一个场景,假设我有一个 500MB 的文件,我想为客户端提供一个 html 表来查看数据。假设有两种情况:

  • 他们正在通过具有 1.2GB 可用内存的桌面查看它。他们可以下载整个文件。
  • 稍后,他们尝试在手机上查看同一张表。我们检测到他们只有 27MB 的可用内存,因此向他们发出警告说“我们检测到您的设备没有足够的内存来查看整个表格。您要下载一个示例吗?”

忽略分页或虚拟表之类的东西,我只关心“如果完整的数据集可以容纳在用户的可用内存中”。这是否可以在浏览器中检测到(即使有用户确认)。如果是这样,如何做到这一点?

更新

这个答案大约在 6 年前就有了答案,the question 指向了 10 年前的答案。我想知道目前的状态是什么,因为从那时起浏览器已经发生了很大的变化,而且还有 webassembly 等。

【问题讨论】:

  • 我不相信有任何方法可以在任何网络浏览器中获取“可用内存”
  • 这能回答你的问题吗? How do you detect memory limits in JavaScript?
  • @ControlAltDel 我们可以删除那个重复的建议吗?这个答案是 6 年前的,我敢肯定从那以后情况发生了很大变化......
  • @David542 事情不会无缘无故地改变……首先,那里的答案有效吗? (阅读第一个答案!)
  • @user202729 感谢您指出这一点:web.dev/monitor-total-page-memory-usage

标签: javascript google-chrome memory v8


【解决方案1】:

使用performance.memory.usedJSHeapSize。虽然它是非标准的并且正在开发中,但它足以测试所使用的内存。您可以在 edge/chrome/opera 上试用,但遗憾的是不能在 firefox 或 safari 上试用(截至撰写时)。

属性 (performance.memory)

jsHeapSizeLimit:上下文可用的堆的最大大小,以字节为单位。

totalJSHeapSize: 分配的总堆大小,以字节为单位。

usedJSHeapSize:JS堆当前活跃的段,以字节为单位。

阅读更多关于performance.memoryhttps://developer.mozilla.org/en-US/docs/Web/API/Performance/memory

CanIUse.com:https://caniuse.com/mdn-api_performance_memory

CanIUse.com 2020/01/22

【讨论】:

    【解决方案2】:

    前段时间我遇到了这个问题(JSON 表的非分页渲染,因为我们不能使用分页,因为 :-(),但问题更严重比你描述的要好:

    • 客户端拥有 8 GB 内存并不意味着该内存可供浏览器使用。
    • 任何关于通用设备“空闲内存”的报告最终都是虚假的(有多少用作缓存和缓冲区?)。
    • 即使确切地知道“Javascript 有多少内存可用”也会导致维护噩梦,因为从 可用内存可显示行 的转换公式涉及“用于单行”是未知的,并且在平台、浏览器和版本之间可变

    经过一番激烈的讨论,我和我的同事一致认为这是一个 XY 问题。我们不想知道客户端有多少内存,我们想知道它可以合理安全地显示多少表行

    我们进行的一些测试——但这是大流行前几个月或三个月,所以 2019 年 9 月,情况可能已经改变——显示了以下有趣的效果:如果我们在屏幕外渲染,客户端,一张桌子使用同一行、重复和随机数据,并计算添加每一行所需的时间,这个时间大致与设备性能和限制相关,并允许合理估计我们可以显示的实际行的允许数量。

    我试图从我的记忆中重新实现一个非常粗略的测试,它沿着这些线路运行,并在登录时通过 AJAX 调用传输结果:

    var tr = $('<tr><td>...several columns...</td></tr>')
    $('body').empty();
    $('body').html('<table id="foo">');
    var foo = $('#foo');
    
    var s = Date.now();
    for (i = 0; i < 500; i++) {
        var t = Date.now();
        // Limit total runtime to, say, 3 seconds
        if ((t - s) > 3000) {
            break;
        }
        for (j = 0; j < 100; j++) {
            foo.append(tr.clone());
        }
        var dt = Date.now() - t;
        // We are interested in when dt exceeds a given guard time
        if (0 == (i % 50)) { console.debug(i, dt) };
    }
    // We are also interested in the maximum attained value
    console.debug(i*j);
    

    以上是对更复杂的测试设备的重新创建(它被分配给我的一个朋友,我不知道最初讨论后的细节)。在 Windows 10 上的 Firefox 上,我注意到 dt 呈线性增长,在 i=450 左右显着增加(我必须增加运行时间才能达到该值;我使用的笔记本电脑是胖 Precision M6800)。在之后大约一秒钟,Firefox 警告我一个脚本正在减慢机器的速度(这确实是我们在将 JSON 数据发送到客户端时遇到的问题之一)。我确实记得曲线的“肘部”是我们最终使用的参数。

    在实践中,如果整体 i*j 足够高(测试以所有行结束),我们知道我们不必担心;如果它较低(测试因超时而终止),但没有“肘部”,我们会显示警告并选择继续;低于某个阈值或如果“dt”超过了保护限制,则诊断甚至在超时之前就停止了,我们只是告诉客户它无法完成,并以 PDF 格式下载综合报告。

    【讨论】:

      【解决方案3】:

      有点。

      在撰写本文时,设备内存规范正在开发中。它指定 navigator.deviceMemory 属性以包含对设备总内存的粗略估计数量级(以 GiB 为单位);此 API 仅适用于通过 HTTPS 提供服务的网站。这两个限制都是为了减少对客户进行指纹识别的可能性,尤其是第三方。 (规范还定义了一个“客户端提示”HTTP 标头,允许直接在服务器端检查可用内存。)

      但是,W3C Working Draft 的日期为 2018 年 9 月,而 the Editor’s Draft 的日期为 2020 年 11 月,the changes in that time span 仅限于内务和编辑修复。因此,这方面的发展充其量似乎不冷不热。另外,目前是only implemented in Chromium derivatives

      请记住:仅仅因为客户端确实有一定数量的内存,并不意味着它可供使用。也许还有其他他们想要使用它的目的。知道存在大量内存并不是允许将其全部使用到排除其他所有人的权限。此 API 的最佳用途可能就像问题中指定的那样:检测我们要发送的数据是否太大而客户端无法处理。

      【讨论】:

        【解决方案4】:

        您可能希望将IndexedDB APIStorage API 一起使用:

        使用navigator.storage.estimate().then((storage) =&gt; console.log(storage)),您可以估计浏览器允许站点使用的可用存储空间。然后,您可以决定是将数据存储在 IndexedDB 中,还是提示存储空间不足的用户下载样本。

        void async function() {
          try {
            let storage = await navigator.storage.estimate();
            print(`Available: ${storage.quota/(1024*1024)}MiB`);
          } catch(e) {
            print(`Error: ${e}`);
          }
        }();
        
        function print(t) {
          document.body.appendChild(document.createTextNode(
            t
          ));
        }

        (此 sn-p 可能无法在此 sn-p 上下文中工作。您可能需要在本地测试服务器上运行它)


        广泛的浏览器支持

        【讨论】:

        • 好的,但是存储!= 内存,还是我遗漏了什么?
        • 内存通常指的是 RAM,而存储通常指的是磁盘(取决于浏览器的实现)。如果您想存储大量可以被视为表的数据,那么使用数据库通常更有效。索引数据库正是为此目的而优化的。您可能只需要以不同的格式存储数据。
        • @b colin -- 同意并同意。但这不是问题。
        • 是的,内存!=存储,这是正确的。索引数据库不使用内存(RAM),它使用磁盘(存储):见“耐用”developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/…
        猜你喜欢
        • 2019-02-22
        • 1970-01-01
        • 1970-01-01
        • 2013-09-21
        • 1970-01-01
        • 2016-10-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多