54

Can browsers enforce any sort of limit on the amount of data that can be stored in JavaScript objects? If so, is there any way to detect that limit?

It appears that by default, Firefox does not:

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

That continues to consume more and more memory until my system runs out.

Since we can't detect available memory, is there any other way to tell we are getting close to that limit?

Update

The application I'm developing relies on very fast response times to be usable (it's the core selling point). Unfortunately, it also has a very large data set (more than will fit into memory on weaker client machines). Performance can be greatly improved by preemptively loading data strategically (guessing what will be clicked). The fallback to loading the data from the server works when the guesses are incorrect, but the server round trip isn't ideal. Making use of every bit of memory I can makes the application as performant as possible.

Right now, it works to allow the user to "configure" their performance settings (max data settings), but users don't want to manage that. Also, since it's a web application, I have to handle users setting that per computer (since a powerful desktop has a lot more memory than an old iPhone). It's better if it just uses optimal settings for what is available on the systems. But guessing too high can cause problems on the client computer too.

Community
  • 1
  • 1
  • If you're dealing with very large data sets, consider using lazy streams, or iterators. There are a few libs out there, shameless plug https://github.com/elclanrs/continuous.js – elclanrs May 06 '14 at 23:15
  • 1
    It's a good question but you should probably discuss your real problem / use case, as it may have a more oblique solution. – djechlin May 06 '14 at 23:16
  • @djechlin I've updated the question to include some background. Thanks for the suggestion. –  May 06 '14 at 23:36
  • What language you use on the backend? You can stream data using websockets... But why do you need to send so much data at the same time? – elclanrs May 06 '14 at 23:44
  • possible duplicate of [Javascript Memory Limit](http://stackoverflow.com/questions/2936782/javascript-memory-limit) – InternalFX May 06 '14 at 23:50
  • 1
    @elclanrs Server side is actually a variety of languages. Ruby and NodeJS are probably the most relevant. The data is purely a performance benefit. With data loaded, a click appears instantaneous to the user. With a server round trip (even through a websocket), the user can feel the delay. Again, this is core to the usefulness of the application. –  May 06 '14 at 23:54
  • This largely depends on the client machine and how much free memory it has. As you have mentioned, there is no way you can query the OS to tell you how much free memory it has, from JavaScript. I would suggest lazy-loading or streaming. – Vivin Paliath May 07 '14 at 00:08
  • how can it be usefull to display 10000000000 'somehtings' in a screen? who in this world can process that? that's what computers are for, dont do this, show just the necesary records if they need the full data just give then a cvs file wich can be opened and processed by excel – bto.rdz May 07 '14 at 00:09
  • @LeviStanley Does this have to run on a variety of browsers, or do you control that? If you can dictate the browser, then you can implement all sorts of useful things in extension/addon code -- including knowing how much memory is left. – David-SkyMesh May 07 '14 at 00:20
  • @bto.rdz It seems you're completely missing the point of the question. The idea isn't to display all of the data at the same time but instead have likely hits preloaded in the background providing a faster user experience. – Etheryte May 07 '14 at 00:35
  • @bto.rdz The large number was just to simulate memory growth. The actual data is compiled and display graphically on a canvas. The user can change how the data is displayed, drill in, drill out, that sort of thing. –  May 07 '14 at 02:29
  • @David-SkyMesh Unfortunately I don't control the browser. The latest versions of anything mainstream need to be supported. That includes mobile device browsers. Old IE versions do NOT need to be supported though, thankfully. Sorry XP users. Extensions are an interesting idea, but I think asking users to choose a memory setting is more palatable than asking them to install addons. –  May 07 '14 at 02:40
  • @LeviStanley Then you're SOL. – David-SkyMesh May 07 '14 at 02:58
  • 1
    Assuming disk seek latency is alright you can just cache your data in [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) and only load it into memory when needed. – Erin May 07 '14 at 03:14
  • 1
    @LeviStanley why are you keeping all the data in memory? – Benjamin Gruenbaum May 16 '14 at 22:50
  • @BenjaminGruenbaum for performance reasons. A round trip to the server every time the user clicks, drags, mousewheels, or otherwise interacts with the canvas starts to really add up (that's all the users do in this application), especially when a significant amount of the data can be reused. –  May 19 '14 at 22:12
  • @LeviStanley so keep it in the local hard drive? What about indexeddb? – Benjamin Gruenbaum May 19 '14 at 22:13
  • @BenjaminGruenbaum IndexedDB might be a good option. I'll have to do more reading on that. I'm suspicious mobile support might be lacking, but it sounds like there are some workarounds for Safari/iOS at least. Thanks. –  May 19 '14 at 22:24
  • There's also [navigator.deviceMemory](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory) ; however it might be (much) larger than the amount that the browser want to give to JavaScript. – user202729 Dec 31 '20 at 03:36

4 Answers4

39

While it might be possible on some browsers, the right approach should be to decide what limit is acceptable for the typical customer and optionally provide a UI to define their limit.

Most heavy web apps get away with about 10MB JavaScript heap size. There does not seem to be a guideline. But I would imagine consuming more than 100MB on desktop and 20MB on mobile is not really nice. For everything after that look into local storage, e.g. FileSystem API (and you can totally make it PERSISTENT)

UPDATE

The reasoning behind this answer is the following. It is next to never user runs only one application. More so with counting on the browser having only one tab open. Ultimately, consuming all available memory is never a good option. Hence determining the upper boundary is not necessary.

Reasonable amount of memory user would like to allocate to the web app is a guess work. E.g. highly interactive data analytics tool is quite possible in JS and might need millions of data points. One option is to default to less resolution (say, daily instead of each second measurements) or smaller window (one day vs. a decade of seconds). But as user keeps exploring the data set, more and more data will be needed, potentially crippling the underlying OS on the agent side.

Good solution is to go with some reasonable initial assumption. Let's open some popular web applications and go to dev tools - profiles - heap snapshots to take a look:

  • FB: 18.2 MB
  • GMail: 33 MB
  • Google+: 53.4 MB
  • YouTube: 54 MB
  • Bing Maps: 55 MB

Note: these numbers include DOM nodes and JS Objects on the heap.

It seems to be then, people come to accept 50MB of RAM for a useful web site. (Update 2022: nowadays averaging closer to 100MB.) Once you build your DOM Tree, fill your data structures with test data and see how much is OK to keep in RAM.

Using similar measurements while turning device emulation in Chrome, one can see the consumption of the same sites on tablets and phones, BTW.

This is how I arrived at 100 MB on desktop and 20 MB on mobile numbers. Seemed to be reasonable too. Of course, for occasional heavy user it would be nice to have an option to bump max heap up to 2 GB.

Now, what do you do if pumping all this data from the server every time is too costly?

One thing is to use Application Cache. It does create mild version management headaches but allows you to store around 5 MB of data. Rather than storing data though, it is more useful to keep app code and resources in it.

Beyond that we have three choices:

Of them, FileSystem is most supported and can use sizable chunk of storage.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Alex Pakka
  • 9,466
  • 3
  • 45
  • 69
  • 2
    +1 for "*consuming all available memory is never a good option*" – Bergi Jun 06 '14 at 03:34
  • 2
    Scrolling on facebook increased the memory from 13.7MB to 30MB. Scrolling on Pinterest the memory went up to 70MB after a minute or so, but they have a lot of images. – Zephyr was a Friend of Mine Apr 06 '16 at 19:05
  • 1
    In Chrome 86+ there is a new API `measureMemory()` that is more accurate than `performance.memory`. see https://web.dev/monitor-total-page-memory-usage/ – John Henckel Oct 21 '20 at 20:35
35

In Chrome the answer is Sure!

Go to the console and type:

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
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • 1
    I was about to post that after finding documentation, but I did not find any documentation for this feature. Is this something that can be relied on? – Rob W May 16 '14 at 22:30
  • @RobW It appears to be a Chrome-specific feature (i.e. it is definitely not in FF) and I can't find documentation either, nor does it appear part of the Web Performance recommendation track - see http://www.w3.org/2010/webperf/ , http://blogs.msdn.com/b/ie/archive/2013/05/21/web-performance-apis-rapidly-become-w3c-recommendations.aspx – user2864740 May 16 '14 at 22:37
  • 3
    @RobW I'd _like_ to tell you yes as I see no reason for it to be removed in the future (and Chrome people use it) but in all honesty - I don't know. Once I learned how to write faster JS (avoid closures, inline everything, monomorphic functions, bitmasks, recycle properties) I never hit the performance limit in client side code in a way that forced me to feature detect _memory_ (feature detecting cpu load is a lot more doable and simpler). I've asked the people involved I'm familiar with and hopefully I'll have an answer eventually. – Benjamin Gruenbaum May 16 '14 at 22:37
  • The closest I found is this http://docs.webplatform.org/wiki/apis/timing/properties/memory which is not a big comfort – Benjamin Gruenbaum May 16 '14 at 22:40
  • @BenjaminGruenbaum "I see no reason for it to be removed in the future". Since the transition to Blink, the Chromium team has removed lots of web platform features from Chrome, even when they were used. Since this API has existed for at least a year (based on the mentions on cbrug.com) and there are no alternatives, it's the closest one can get. Besides, because it is supported in only one browser, you have to account for the unavailability of the API any way. – Rob W May 16 '14 at 22:41
  • When I said "I see no reason" what I implied is "I know that the people who are building chrome, use it, and show people how to use it in tutorials in order to debug their code" - while that's not anywhere near a "standard", it's good enough for "I see no reason for it to be removed" imo. I'll hopefully have more information soon :) – Benjamin Gruenbaum May 16 '14 at 22:43
  • @BenjaminGruenbaum I think that the best answer to the OP's question is actually `Once I learned how to write faster JS (avoid closures, inline everything, monomorphic functions, bitmasks, recycle properties) I never hit the performance limit in client side code in a way that forced me to feature detect memory` – falsarella May 16 '14 at 22:48
  • 1
    @falsarella yes, but how to write fast JS is the subject for a book, not a Stack Overflow answer. Here are some pointers to get you started http://addyosmani.com/blog/writing-fast-memory-efficient-javascript/ http://mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html https://github.com/petkaantonov/bluebird/wiki/Optimization-killers – Benjamin Gruenbaum May 16 '14 at 22:50
  • 1
    It is now 2017, I need to pass tens of gigabytes of memory through a JavaScript web page - and Chrome crashes before when it reaches its memory limit - would kill for a callback. – Benjamin Gruenbaum Jul 28 '17 at 21:09
3

I think you'll want something like the following:

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

You can check out the following: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory

Note: This feature is not supported across all browsers.

Jack
  • 39
  • 1
2

Since a web app can't have access to any system-related information (like the available amount of memory), and since you would prefer not having to ask users to manually set their performance settings, you must rely on a solution that allows you to get such information about the user's system (available memory) without asking them. Seems impossible ? Well, almost...

But I suggest you do the following : make a Java applet that will automatically get the available memory size (e.g. using Runtime.exec(...) with an appropriate command), provided your applet is signed, and return that information to the server or directly to the web page (with JSObject, see http://docs.oracle.com/javafx/2/api/netscape/javascript/JSObject.html).

However, that would assume your users can all run a Java applet within their browsers, which is not always the case. Therefore, you could ask them to install a small piece of software on their machines that will measure how much memory your app should use without crashing the browser, and will send that information to your server. Of course, you would have to re-write that little program for every OS and architecture (Windows, Mac, Linux, iPhone, Android...), but it's simpler that having to re-write the whole application in order to gain some performance. It's a sort of in-between solution.

I don't think there is an easy solution. There will be some drawbacks, whatever you choose to do. Remember that web applications don't have the reputation of being fast, so if performance is critical, you should consider writing a traditional desktop application.

Maxim Bernard
  • 307
  • 1
  • 7
  • 14
    A Java applet? Yech. I'm fairly sure the majority of iPhone browsers [cannot run Java applets](http://stackoverflow.com/questions/2368166/can-i-run-a-webpage-embedded-java-applet-on-the-iphones-web-browser). – JLRishe May 07 '14 at 03:30