2

I have a webapp with many (1000) buttons.
Each button reads an image (4032x3024 ~1.5MB - high resolution is needed) from a webserver when being clicked.
When running on a phone (Android Pixel3), after multiple clicks, when clicking on a button that was not clicked before, results in an error: net::ERR_OUT_OF_MEMORY when getting the image from the webserver.

I tried 2 use cases:

  • Use case1 - previously read images are released before loading the next image.
    In this case I don't see the out-of-memory problem but the user experience is poor, because each image is retrieved from the webserver regardless if it has been read before.

  • Use case2 - previously read images are not released.
    In this case the experience is better when re-reading the same image (while the app is still responding), because the image is already cached. But at some point the program runs out of memory, and stops responding.

I use Chrome (version 79.0.3945.88) DevTools Memory and Perfomance tabs, and followed techniques from here to analyze the memory.

I don't see anything non-ordinary.
For example, I looked at the Allocation instrumentation over time In useCase2, the memory grows as expected, when adding more images, but seems to be well below limit. Checking the window.performance.memory.jsHeapSizeLimit gives ~1GB. Yet, when the out-of-memory problem occurs, the memory (in Javascript heap) is less than 20 MB

To avoid exceeding the memory limit, I want to check the amount of used memory, before reading the next image, and if the value exceed some threshold, release some used images.
In this way, the user may have better experience (e.g. if toggling between few images) and always avoid the out-of-memory error.

Is there a way to check the memory used, programatically via Javascript in the browser?
(In Node.js "process.memoryUsage().heapUsed" can be used, but this does not work in the browser)

Thanks, Avner

Avner Moshkovitz
  • 1,138
  • 1
  • 18
  • 35
  • 1
    *"each image is retrieved from the webserver regardless if it has been read before"* — This should be a solvable problem with proper caching. You don't need to store the images *in memory*, the browser can cache them if you use caching techniques properly. Worst case, write them to local storage or such. Anything but keeping them *in memory*. – deceze Jan 30 '20 at 08:20
  • 1
    Your huge resolution is certainly an issue on Android - I have seen this asked before – mplungjan Jan 30 '20 at 08:23
  • 1
    @deceze I read that local storage is limited to ~ 5MB here: https://medium.com/@onejohi/offline-web-apps-using-local-storage-and-service-workers-5d40467117b9 I'm looking at hundreds of MB. Would e.g. IndexDB via service worker be better? – Avner Moshkovitz Jan 30 '20 at 08:31
  • 1
    "Is there a way to check the memory used, programatically via Javascript in the browser?" From the other posts I've read on that exact question, the answer is "Not always in all browsers". However, you know the size of the images already "4032x3024 ~1.5MB" so just do some math on you're own. It should be trivial for you to keep track of how many images have been loaded already. Pick a number that is a good compromise between performance and memory usage and then just start rotating them out when you hit that number. – gforce301 Jan 30 '20 at 08:36
  • Some answers to the memory usage question: https://stackoverflow.com/a/9860215/1819684 https://stackoverflow.com/a/31172693/1819684 – gforce301 Jan 30 '20 at 08:36
  • I wouldn't go down the route of calculating any memory at all. 1) Ensure you're sending *reasonably* sized images to the browser in the first place. 2) Use caching. 3) Keep only as many images in memory as you need for a reasonable user experience and discard anything else. Don't assume how many images you may be able to store in memory. If the phone has to quit all other background activity just to display your website, that's a negative user experience as well. – deceze Jan 30 '20 at 08:42

0 Answers0