新浦京娱乐场官网-301net-新浦京娱乐www.301net
做最好的网站

而容器的高效稳定不仅仅由容器提供方来保障

H5 Crash 研究

2016/05/31 · HTML5 · Crash

初稿出处: 小胡子哥(@Barret托塔天王)   

作者们通晓,支撑页面在 webview 上出彩运行的前提是有所二个便捷并且稳固的 webview 容器,而容器的飞速牢固不唯有由容器提供方来保险,也急需容器使用者固守一些基本法规,不然就有望现身页面 Crash 的情形,那些法则是何许?什么样的上层代码会引起容器极度退出?那是本文须求解说的内容。

H5 Crash 难题差不离

下图是 H5 Crash 的大概流程图:

图片 1

鉴于前端无法捕捉到页面 Crash 的状态和储藏室,可是 H5 页面上发生的错误会传送到 Java 和更底层的 Native 直到容器十分退出,在脱离的那一刻,容器会将仓库写入到日志中,当后一次张开容器时(也说不许是准时报告)就能够反馈那个酒店消息。

H5 Crash 原因初探

测验代码 货仓地址:

git clone ; cd demo;

1
2
git clone https://github.com/barretlee/h5crash.git;
cd demo;

注意: 代码要求在 Webview 容器中测量试验,PC 浏览器下不会现身相当。

H5 Crash 的案由不太刚毅,不过从经验上判断和搜索,大致归类为以下三种:

1. 内部存款和储蓄器难点

  • 测验方法:使用闭包,不断扩展内部存款和储蓄器量,看看增到哪些区间大小, webview 容器会现身相当
  • 测量检验地方:(Wechat、今日头条或许别的顾客端张开该页面的客商,能够点步向测验下,选用100M 内部存款和储蓄器,不出意外,你的客商端会闪退。)

XHTML

<script> var Closure = function() { var _cache = []; var cache = 0; var add = function(size) { cache = size; size = size * 1024 * 1024; _cache.push(new Array(size卡塔尔.join('x'卡塔尔(英语:State of Qatar)卡塔尔(英语:State of Qatar); refresh(卡塔尔; }; var refresh = function(卡塔尔(英语:State of Qatar) { r.innerHTML = '内部存款和储蓄器消耗: ' cache 'M'; }; return { cache: cache 'M', add: add, refresh: refresh } }; var closure = Closure(卡塔尔; </script> <button onclick="closure.add(1卡塔尔">扩大1M 内部存款和储蓄器消耗</button> <button onclick="closure.add(10卡塔尔国">扩大10M 内存消耗</button> <button onclick="closure.add(20卡塔尔国">扩充20M 内部存款和储蓄器消耗</button> <button onclick="closure.add(50卡塔尔">增加50M 内部存款和储蓄器消耗</button> <button onclick="closure.add(100卡塔尔(英语:State of Qatar)">增添 100M 内存消耗</button> <div id="r">内部存款和储蓄器消耗:0 M</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script>
var Closure = function() {
  var _cache = [];
  var cache = 0;
  var add = function(size) {
    cache = size;
    size = size * 1024 * 1024;
    _cache.push(new Array(size).join('x'));
    refresh();
  };
  var refresh = function() {
    r.innerHTML = '内存消耗: ' cache 'M';
  };
  return {
    cache: cache 'M',
    add: add,
    refresh: refresh
  }
};
var closure = Closure();
</script>
 
<button onclick="closure.add(1)">增加 1M 内存消耗</button>
<button onclick="closure.add(10)">增加 10M 内存消耗</button>
<button onclick="closure.add(20)">增加 20M 内存消耗</button>
<button onclick="closure.add(50)">增加 50M 内存消耗</button>
<button onclick="closure.add(100)">增加 100M 内存消耗</button>
 
<div id="r">内存消耗:0 M</div>

存在的扰攘:这种测验存在非常多的烦闷,比方设备档期的顺序、系统项目(iOS/Android卡塔尔国、和装置内部存款和储蓄器运市场价格况等。

2. Layers 数问题

Layers 数的得到比较辛勤,Chrome Driver 未有提供该数据的接口,前段时间也绝非比较好的不二等秘书诀得到那个数目。

  • 测量试验方法:通过差别的办法创制层,观看页面包车型客车 Crash 意况
  • 测验地方:

XHTML

<style>.transform { transform: translateZ(0); } .animation { width:100px; height:100px; background:red; position:relative; animation:move 5s infinite; } @keyframes move { from {left:0px;} to {left:200px;} } </style> <script> var Layer = function() { function getType() { return document.querySelector('input:checked').value; }; return { createOne: function(index) { var div = document.createElement('div'); div.appendChild(document.createTextNode(index)); switch(getType()) { case 'opacity': div.style.cssText = "opacity:" (index / 1000); break; case 'transform': div.className = 'transform'; break; case 'animation': div.className = 'animation'; break; case 'zindex': div.style.cssText = "position:relative; z-index:" index; break; } document.body.appendChild(div); }, create: function(num) { [].slice.call(document.querySelectorAll('div'卡塔尔(قطر‎卡塔尔.forEach(function(item卡塔尔{ item.parentNode && item.parentNode.removeChild(item卡塔尔国; }卡塔尔; while(num--卡塔尔{ this.createOne(num卡塔尔(英语:State of Qatar); } } } }; var layer = Layer(卡塔尔(قطر‎; </script> <strong>层类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 成立层</span></label></li> <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创设层</span></label></li> <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创造层</span></label></li> <li><label><input type="radio" name="type" value="zindex"> <span>通过相对定位分层</span></label></li> </ul> <button onclick="layer.create(1卡塔尔(قطر‎">创造 1 个层</button> <button onclick="layer.create(10卡塔尔">创立 12个层</button> <button onclick="layer.create(20卡塔尔(قطر‎">创造 二十一个层</button> <button onclick="layer.create(50卡塔尔">成立 四18个层</button> <button onclick="layer.create(100卡塔尔(英语:State of Qatar)">创制 100 个层</button> <button onclick="layer.create(200卡塔尔">成立 200 个层</button> <button onclick="layer.create(500卡塔尔国">创造 500 个层</button> <button onclick="layer.create(1000卡塔尔">创建 1000 个层</button> <button onclick="layer.create(二〇〇二卡塔尔(قطر‎">创设 二零零四个层</button> <button onclick="layer.create(5000卡塔尔(英语:State of Qatar)">创立 5000 个层</button> <button onclick="layer.create(10000卡塔尔">成立10000 个层</button>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<style>.transform {
  transform: translateZ(0);
}
.animation {
  width:100px;
  height:100px;
  background:red;
  position:relative;
  animation:move 5s infinite;
}
 
@keyframes move {
  from {left:0px;}
  to {left:200px;}
}
</style>
<script>
var Layer = function() {
  function getType() {
    return document.querySelector('input:checked').value;
  };
  return {
    createOne: function(index) {
      var div = document.createElement('div');
      div.appendChild(document.createTextNode(index));
      switch(getType()) {
        case 'opacity':
          div.style.cssText = "opacity:" (index / 1000);
          break;
        case  'transform':
          div.className = 'transform';
          break;
        case  'animation':
          div.className = 'animation';
          break;
        case  'zindex':
          div.style.cssText = "position:relative; z-index:" index;
          break;
      }
      document.body.appendChild(div);
    },
    create: function(num) {
      [].slice.call(document.querySelectorAll('div')).forEach(function(item) {
        item.parentNode && item.parentNode.removeChild(item);
      });
      while(num--) {
        this.createOne(num);
      }
    }
  }
};
var layer = Layer();
</script>
 
<strong>层类型: </strong>
<ul>
  <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li>
  <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li>
  <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li>
  <li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li>
</ul>
 
<button onclick="layer.create(1)">创建 1 个层</button>
<button onclick="layer.create(10)">创建 10 个层</button>
<button onclick="layer.create(20)">创建 20 个层</button>
<button onclick="layer.create(50)">创建 50 个层</button>
<button onclick="layer.create(100)">创建 100 个层</button>
<button onclick="layer.create(200)">创建 200 个层</button>
<button onclick="layer.create(500)">创建 500 个层</button>
<button onclick="layer.create(1000)">创建 1000 个层</button>
<button onclick="layer.create(2000)">创建 2000 个层</button>
<button onclick="layer.create(5000)">创建 5000 个层</button>
<button onclick="layer.create(10000)">创建 10000 个层</button>
  • 实在,创设五个层,也是对内存的伟大消耗,页面 Crash 只怕还是因为内部存款和储蓄器消耗过大

3. 并发过多难点

  • 测量试验方法:尝试并发发出多样不相同的乞请(Fetch诉求、XHRubicon必要、Script/CSS 能源伏乞),观望页面 Crash 境况
  • 测量检验地方:

XHTML

<script> var Request = function() { function getType() { return document.querySelector('input:checked').value; }; function getResource() { var type = getType(); var resource = { fetch: '/', xhr: '/', script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js', css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css' }; return resource[type]; }; return { emitOne: function() { var url = getResource() "?_t=" (new Date * 1 Math.random()); switch(getType()) { case 'fetch': return fetch('/'); case 'xhr': with(new XMLHttpRequest) { open('GET', url); send(); } return; case 'script': var s = document.createElement('script'); s.src = url; document.body.appendChild(s); return; case 'css': var s = document.createElement('link'); s.href = url; document.body.appendChild(s); } }, emit: function(num) { [].slice.call(document.querySelectorAll('script,link'卡塔尔(英语:State of Qatar)卡塔尔国.forEach(function(item){ item.parentNode && item.parentNode.removeChild(item卡塔尔(قطر‎; }卡塔尔国; while(num--卡塔尔国{ this.emitOne(卡塔尔国; } } } }; var request = Request(卡塔尔(قطر‎; </script> <strong>哀求类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送央求</span></label></li> <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHCR-V发送乞请</span></label></li> <li><label><input type="radio" name="type" value="script"> <span>并发需要脚本能源</span></label></li> <li><label><input type="radio" name="type" value="css"> <span>并发诉求样式能源</span></label></li> </ul> <button onclick="request.emit(1卡塔尔">并发 1 个诉求</button> <button onclick="request.emit(10卡塔尔国">并发 12个乞求</button> <button onclick="request.emit(20卡塔尔(قطر‎">并发 20个诉求</button> <button onclick="request.emit(50卡塔尔(英语:State of Qatar)">并发 50个央求</button> <button onclick="request.emit(100卡塔尔(英语:State of Qatar)">并发 100 个恳求</button> <button onclick="request.emit(500卡塔尔(英语:State of Qatar)">并发 500 个央浼</button> <button onclick="request.emit(1000卡塔尔(英语:State of Qatar)">并发 1000 个央浼</button>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<script>
var Request = function() {
  function getType() {
    return document.querySelector('input:checked').value;
  };
  function getResource() {
    var type = getType();
    var resource = {
      fetch: '/',
      xhr: '/',
      script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js',
      css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css'
    };
    return resource[type];
  };
  return {
    emitOne: function() {
      var url = getResource() "?_t=" (new Date * 1 Math.random());
      switch(getType()) {
        case 'fetch':
          return fetch('/');
        case 'xhr':
          with(new XMLHttpRequest) {
            open('GET', url);
            send();
          }
          return;
        case 'script':
          var s = document.createElement('script');
          s.src = url;
          document.body.appendChild(s);
          return;
        case 'css':
          var s = document.createElement('link');
          s.href = url;
          document.body.appendChild(s);
      }
    },
    emit: function(num) {
      [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) {
        item.parentNode && item.parentNode.removeChild(item);
      });
      while(num--) {
        this.emitOne();
      }
    }
  }
};
var request = Request();
</script>
 
<strong>请求类型: </strong>
<ul>
  <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li>
  <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li>
  <li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li>
  <li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li>
</ul>
 
<button onclick="request.emit(1)">并发 1 个请求</button>
<button onclick="request.emit(10)">并发 10 个请求</button>
<button onclick="request.emit(20)">并发 20 个请求</button>
<button onclick="request.emit(50)">并发 50 个请求</button>
<button onclick="request.emit(100)">并发 100 个请求</button>
<button onclick="request.emit(500)">并发 500 个请求</button>
<button onclick="request.emit(1000)">并发 1000 个请求</button>
  • 留存的忧愁:设备的等级次序、设备的 CPU 使用状态和网络景况等。

H5 Crash 测量试验结果

测量检验结果:

  • 通过 opacity、animation、positon 等措施创设层,即正是 1w 个,页面也一向不明显浮动;不过使用 transform 创设 2k~5k 个层,页面会卡顿几秒后旋即闪退;
  • 内部存款和储蓄器是条红线,测量检验开掘,叁回性消耗 20M 的内部存款和储蓄器,会促成顾客端即时闪退;
  • 现身央求也是存在响应难点的,Fetch API 和 CSS Resource 并发 1k 央求未有出现难题,不过 XHTucson 和 Script Resource 乞求,难点特地鲜明,即便尚无导致页面闪退,可是页面已经跻身了假死状态。

以上临界点还足以持续标准。

小结

本文首要是对 H5 Crash 做了一个预备性商讨,测量检验大概存在不菲引用误差,测量试验方法也须要改进,可是沿着这一个的思绪考究会比较便于找到结论。

一而再再而三会付出相比较有意义的边际数据甚至探测工具。

 

1 赞 3 收藏 评论

图片 2

本文由新浦京娱乐场官网-301net-新浦京娱乐www.301net发布于www.301net,转载请注明出处:而容器的高效稳定不仅仅由容器提供方来保障

您可能还会对下面的文章感兴趣: