技术解析

js 将大量图片保存在内存中会有问题吗?
0
2021-08-20 10:51:36
idczone

较多的图片(预计 100 张共计 10-15M )需要随取随用,我打算将他们保存在内存中,

const imgs: Image[] = []

不知道会不会对程序的运行有什么不好的影响?比方说卡顿啊、图片内容丢失啊之类的?能推荐这方面(我也不知道哪方面...)的科普文就更好了。


没有影响,放在内存速度只会更快。你硬件到位,内存随便用,但是你应该明白内存跟 磁盘的区别吧。

现在的浏览器下,一般情况下没问题的,内存基本都够用

好歹放 local storage 吧

淘宝就是将很多图片放内存的,没有问题,前提是你的程序不会爆内存

window.performance.memory.jsHeapSizeLimit
应该足够你用的

这种应该不是直接存在了内存里吧。
就和你页面加载了 100 张图片,js 里肯定只是对这些资源的引用。
具体你通过 html 加载图片还是 js 都是一样的

对于现在浏览器动辄几个 G 的内存占用,这点不算什么 doge

楼主的意思应该是直接存 blob

首选考虑的应该是你需要多少时间来把这上 G 的图片加载进内存里。

只是我不知道操作系统 /运行环境会不会对单个页面可用内存做限制,比方说虽然我手机内存 6G,但是手机只分配给微信 1G,微信只分配给单个 html 页面 100M,数值是随便说的,意思到位就行。
图片取用 /增删会很频繁,比方说 10 次 /s,这些图片说多不多,说少不少的,不太想放到 localStorage 里面,还得写兼容杂七杂八的,如果没大问题就直接放内存了,毕竟我看 three.js 也是直接保存在内存的

Chrome 单个 tab 有内存使用上限,不多的话,没有问题的。

感谢,很有用!
不是啊,我描述里面有,直接就是简单的 `const imgs: Image[] = []` 。。。

15M 不是事,我存视频数据到内存都是几个 G 的。

总共 10-15M,不是单张。。。

哦抱歉抱歉没看仔细,那才这么点大一点事情没有

看你楼说的,这么大的时间间隙,最佳还是按需实时从网络加载更好些,全部缓存到内存是否有提前优化的嫌疑?
另外猜测意图并非同时需要显示大量图片,如果真需要全部缓存到内存时,尽量不要用 Image 对象来加载图片,自己写 xhr 请求得到二进制 ArrayBuffer,最多内存占用也就比 15M 多点,按需实时从内存实例化 Image 图片对象( onload 非常快)。直接用 Image 来进行缓存内存占用会翻个 10 几倍也是正常。

为什麽要保存在内存中呢,图片用 new image 加载一次回就有缓存了,之后直接用 src 就好了

业务需求实际是同一时刻只有 3-7 张图片,然而需要根据鼠标动作频繁切换这几张图片的 src,再讲细一点就是比较特殊的环物展示。我还没想过直接处理 buffer,回去考虑一下,谢谢。

其实本来就是利用的浏览器的缓存,或许是我描述有误

实测一下不就知道了。

缓存一般没有问题,楼上说的爆内存和这个关系应该不大。移动端图片爆内存的情况是一般是图片尺寸的原因,和文件大小无关。你可以计算所有展示的图片 w*h*4 来估算一下渲染时所占用的内存。

我之前用过同时显示 8 张 4096*2048 的图片,手机动不动就黑屏……现在仅仅是 3-6 张 2000*1000,这么算的话大概百来 M,应该问题不大。

设备太多了,没法一一测试啊,就怕内存占用处在临界点,这台设备好用,那台设备崩了,或者由于不同设备的缓存策略不同,缓存太多,如果动不动给我自动清掉一些缓存,也很烦啊。

图片太大结合 oss 的图片处理用,可以压缩为 webp 的格式 再控制下长宽就会好很多

没啥问题,渲染出来的图片才会影响性能

大小不能压缩,还要支持放大了看也清楚,已经压缩的足够了,2000*1000 的图片现在已经 100k 不到了

display:none 的图片好像也可以用在 canvas 里面,所以其实加几个隐藏的 div 加载图片就行

不过楼主这种增加抽象复杂度的随取随用也没啥用,随便找个预加载库就是了

不太清楚"增加抽象复杂度"是什么意思,是说我这么搞让问题更复杂了嘛?

比如常规方法是通过图片 url 现场 new Image 插入网页,哪个 Image 是哪个 url 对应关系都很清楚,你先把所有的 Image 预生成再存到一个数组里,(别人接手项目)可能就不能马上理清每个 Image 对应哪个图片

由于我这边时不时需要操作这一组有序的图片,这一组 url 将会按照一定的规律画到同一个 canvas 上,所以才将他们放在一个数组里面的。。。

道理我都懂,可是你这个就顶多是个图片懒加载啊,你如何证明是保存到 js 了?

url 现场生成 image 再画到 canvas 上,中间的步骤可以当做黑箱不用去太关心,更符合直觉

更符合直觉指的是我输入了一个 url,在 canvas 上就渲染了对应的图片

对,但是我必须预加载他,不能我需要了再临时加载,这是我做的一个小 demo https://m.lmoar.com/vrs/t/dist-example/example.html
对,是图片预加载,如果仅仅 new Image.src = url,那么浏览器很快就会清掉缓存,我这边将返回的 img 保存到数组里面,**或许 /应该 /可能**浏览器不会清掉缓存。

回来看了一下,ctx.drawImage 好像不能接受 blob 作为参数。。。

随便找个预加载的库就是了

localStorage 只能放字符串,并且单个域名在多数浏览器里有 5M 的限制

URL.createObjectURL(blob)

我好像确实忘了去找库了,其实我一直纠结的是,浏览器会不会把我预加载的东西给清理掉

游戏引擎就是这么做的,没什么问题。

https://codepen.io/jsq2627/pen/ZEYLyEW?editors=1010
不做分片加载的话,那就有很大概率内存占用超出上限,页面崩溃。特别是低端安卓机。
如果你能手动控制好分片加载的话,那自然是 ok 的。
另外存 blob 和存 Image 有个区别是,blob 占用的是 JS heap 内存,最大上限比存 Image 小很多。

100 张肯定没问题,我试过存过千张几百 kb 的。

根据实现,图片不一定在内存。具体是 from disk cache 还是 from memory cahe 应该是分情况的

这段代码有意思。我试了一个 200kb 的图片( 1800*1200 )加载 200 次的内存占用(约 50M 流量)

任务管理器里面报的内存,不知道是 windows 的是实际的还是 chrome 的是实际的,不过应该 600M+是有的,performance 里面的值雷打不动
数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服