• 记录自己解决的第一个H5页的性能问题, 关于内存溢出
  • 拼字游戏

问题表现

  • 初始化后, 第一次拼字并不卡.

  • 随着拼的次数越来越多, 越来越卡

  • 浏览器任务管理器中可以看出, 内存持续升高

  • 确定内存问题, 即是卡顿第一问题

代码层面问题

  • 首先希望从代码层面排查内存问题
  • 思考代码后, 发现以下两点

第二舞台直接删除Canvas的Dom

  • 问题:

    • 每次都会重新建立第二个分享舞台.
    • 上一次的canvas直接删除了Dom.
  • 推断:
    • 推断直接删除DOM, 并不能释放舞台上一系列的Bitmap图像等
    • 上几次图像继续占用内存
  • 排查与解决:
    • 游戏舞台与分享舞台只保留一个
    • 每次游戏, 通过指针清空bitmap
  • 结果:
    • 内存无明显变化

loader进来的临时图片未删除

  • 问题:

    • 每次完成一次拼字都会请求后台这次结果需要加载的资源
    • 资源中包含大量的图片等, 都是通过new Image()的src加载过来的
  • 推断:
    • 每次浏览器加载大量图片, 展示后, 并未释放图片空间
  • 排查与解决:
    • 找出不能重复利用的图片, 使用新的加载器
    • 一次性使用图片后, 让加载器为null
  • 结果:
    • 内存少量减少
    • 游戏已经卡顿

每次游戏会重新new一些对象

  • 问题: 因每次进行游戏都会new一些对象出来
  • 推断: 怀疑是游戏过程中js内存溢
  • 排查:
  • 结论: js中的内存变化不能引起内存卡顿问题.

GPU层面问题

  • 直接贴链接了: Chromium Graphics // Chrome GPU
  • 这次通过任务管理器可以直接看出是GPU缓存的溢出
  • 哭了, 为什么上次我测得时候不显示... 仅仅是一个内存的表示, 给我好找啊..
  • 最后还是在安卓中进行排查, 才知道是GPU / chromium grapics的问题

观察GPU表现体征

  • 我们在游戏中发现内存的溢出主要是GPU的变化
  • 在游戏中去除所有的序列帧后, 只保留最基本的游戏, 任何手机都不卡.
  • 那就一定是这些图片搞得鬼.
  • 已经把加载的图片缓存清除掉了.
  • 我们排除了canvas, 排除了图片加载, 剩下的就是最基本的图片展示了.
  • 现在唯一剩下的就是浏览器自己做的事情了.
  • 展示图片, 然后清理DOM
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style> #stage {
width: 100%;
height: 100%;
}
</style>
<title>测试内存</title>
</head> <body>
<button id="add">增加图片</button>
<button id="clear">清除内存</button>
<button id="addTen">增加十倍图片</button>
<div id="stage"></div>
<script>
var count = 0
var stage = document.getElementById('stage')
document.getElementById('add').onclick = function () {
for (var i = 0; i < 23; i++) {
stage.innerHTML += `<img src='./img${count}/${i}.jpg' />`
}
++count
}
document.getElementById('clear').onclick = function () {
stage.innerHTML = ''
count = 0
}
document.getElementById('addTen').onclick = function () {
for (var j = 0; j < 10; j++) {
for (var i = 0; i < 23; i++) {
stage.innerHTML += `<img src='./img${count}/${i}.jpg' />`
}
}
}
</script>
</body> </html>

chrome中测试

  • 在添加三组十倍图片后, 清除DOM
  • GPU和Image cache, 在浏览器中并不能总结出规律

webview表现特征

  • 我们写了一个最简单的demo, 在安卓上的webview进行了测试
  • 测试结果如下:
    • 初始状态下的内存:
    • 添加图片并浏览器后的内存:
    • 清理页面dom后的内存:

总结

个人理解原理

浏览器中的GPU会自动缓存一段时间展示过的 "图像". 我们称为: "GPU Program Cache"

  • 浏览器在读取图片之后会生成GPU可以使用的着色器代码
  • 在GPU使用的时候, 会自动缓存这些着色器代码.

最后解决办法

  • 去掉大量序列帧, 序列帧尽量用小图
  • 动画尽量用代码实现

附带一个测试着色器的代码, 也是当时测试webgl的代码

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head> <body>
<canvas id="glcanvas" width="700" height="500"></canvas>
<script>
// 获取WebGL
var canvas = document.getElementById('glcanvas')
gl = canvas.getContext("webgl") // 创建顶点着色器
var VSHADER_SOURCE =
'void main() {\n' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
// 创建片元着色器
// var FSHADER_SOURCE =
// 'void main() {\n' +
// ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
// '}\n'; // 绘制圆
var FSHADER_SOURCE = `
#ifdef GL_ES
precision mediump float;
#endif
void main() {
float d = distance(gl_PointCoord, vec2(0.5,0.5));
if(d < 0.5){
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}else{ discard;}
}`; // 着色器代码需要放到一个程序中
var program = gl.createProgram()
// 创建顶点着色器
var vShader = gl.createShader(gl.VERTEX_SHADER)
// 创建片元着色器
var fShader = gl.createShader(gl.FRAGMENT_SHADER) // shader容器与着色器绑定
gl.shaderSource(vShader, VSHADER_SOURCE)
gl.shaderSource(fShader, FSHADER_SOURCE) // 将GLSE语言编写成浏览器可用的代码
gl.compileShader(vShader)
gl.compileShader(fShader) // 将着色器添加到程序上
gl.attachShader(program, vShader)
gl.attachShader(program, fShader) // 链接程序
// 在链接操作以后, 可以任意修改shader代码.
// 对shader重新编译不会影响整个程序, 除非重新链接程序
gl.linkProgram(program) // 加载并使用链接好的程序
gl.useProgram(program) // 绘制一个点
gl.clearColor(0.0, 0.0, 0.0, 1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.POINTS, 0, 1)
</script>
</body> </html>

H5页游戏内存溢出问题的更多相关文章

  1. 游戏服java程序启动,显示内存溢出

    1.OutOfMemoryError:Java heap space 过程:服务器上面的mysql突然异常重启,导致了程序启动的时候报错 问题1:OutOfMemoryError:Java heap ...

  2. jvm内存溢出分析

    概述 jvm中除了程序计数器,其他的区域都有可能会发生内存溢出 内存溢出是什么? 当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出 内存溢出和 ...

  3. Egret白鹭H5小游戏开发入门(二)

    前言: 昨天的文章中简单的介绍了Egret白鹭引擎从安装到基本的使用配置等问题,今天着重介绍H5小游戏开发的起步阶段,如Wing面板的使用,素材的处理,类的说明,开始布局等等. 整体概况: 根据上一篇 ...

  4. 使用(POI)SAX处理Excel文件,防止内存溢出

    POISAXReader h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-chi ...

  5. Egret白鹭H5小游戏开发入门(三)

    前言: 在上一篇文章中着重介绍了H5小游戏开发的起步阶段,如Wing面板的使用,素材的处理,类的说明等等,那么今天主要是涉及到场景的创建,loading的修改等等的代码编写. 对于这一节,我在讲解的过 ...

  6. Tomcat内存溢出解决办法

    使用Java程序从数据库中查询大量的数据时出现异常:java.lang.OutOfMemoryError: Java heap space在JVM中如果98%的时间是用于GC且可用的 Heap siz ...

  7. Android内存溢出解决方案(OOM)

    众所周知,每个Android应用程序在运行时都有一定的内存限制,限制大小一般为16MB或24MB(视平台而定).因此在开发应用时需要特别关注自身的内存使用量,而一般最耗内存量的资源,一般是图片.音频文 ...

  8. Android 内存溢出解决方案(OOM) 整理总结

    在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手机上做了测试,因为有效果也有结果,今天小马就做个详细的总 ...

  9. 图片_ _Android有效解决加载大图片时内存溢出的问题 2

    Android有效解决加载大图片时内存溢出的问题 博客分类: Android Android游戏虚拟机算法JNI 尽量不要使用setImageBitmap或 setImageResource或 Bit ...

随机推荐

  1. JAVA学习篇--静态代理VS动态代理

    本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者 ...

  2. java lesson09总结

    package Super; public class SuperTest {  String color;  // public SuperTest(String color) {this.colo ...

  3. sonarqube执行命令遇上的小问题

    在安装好sonarqube,本地或是服务器上都是可疑正常运行的情况下. 这一次我重新上传,修改配置SonarQube.Analysis.xml,sonar.host.url的值已经改为服务器上的,执行 ...

  4. HDR10 中的名词解释

    1. EOTF ( Electro-Optical Transfer Function ),电->光 转换函数.由电信号,转换成光信号时的规则.确定显示终端(电视机.投影仪等),如何合理地响应输 ...

  5. echarts 内存泄漏

    最近使用vue + Echarts 实现vue项目的数据可视化功能的时候,在ios环境下,点击列表页进入详情页几次就白屏了. 感觉白屏的原因是:echarts频繁初始化画图时候有内存泄漏,吃掉了所有内 ...

  6. JavaScript基本使用

    基本使用 1.JavaScript组成 ECMAScript+BOM+DOM BOM的思想(重点) DOM的思想(重点) 2.使用<script></script>标签 doc ...

  7. 使用Vue CLI脚手架搭建vue项目

    本次是使用@vue/cli 3.11.0版本搭建的vue项目 1. 首先确保自己的电脑上的Node.js的版本是8.9版本或者以上 2. 全局安装vue/cli npm install @vue/cl ...

  8. 在vue中引用echarts导致Cannot read property getAttribute of null ?

    报错信息如下: 之前一直用echarts没有出现过这个问题,所以当这个问题出现时我就开始了各种查,试了几种方法依旧报错,比如: 1.在mounted() {},写成如下形式:(依旧报错) this.$ ...

  9. 【Mac】 开启原生的 NTFS 硬盘格式支持

    一.MacOS 10.13 之前 二.MacOS 10.13 及之后 一.MacOS 10.13 之前 直接跳到引用地址查看,下面的草记只是为了防止链接丢失 引用地址 打开终端 切换至root身份,输 ...

  10. 如何准备Java的高级技术面试

    一. 换位思考下,如果你面试官,你会怎么做 只能通过简历和面试来衡量,别无他法.如果某位大牛确认能力很行,但面试时无法充分地自证能力,那对不起了,过不了,现实就这样. 如果面试官由于能力不行,招进来一 ...