web仿真或实际内存分析应用及自动化方案

news2025/1/13 15:50:15

js 自带 GC(垃圾回收)机制,因此绝大多数 web 开发人员不会在日常开发中考虑内存情况(包括本人),在多数业务场景中,这可能没有问题,但在一些核心web应用场景下(比如某个页面投放在一级tab下这种 WebView 基本不会销毁的场景,或者像小程序、PhoneGap / Electron 这种目前以 WebView 渲染为主的应用),会造成一些白屏崩溃这种意想不到的bug,影响用户体验。

(*注:文中大多三方链接需要翻墙访问)

内存泄漏的影响

对于用户来说,一般内存泄漏场景根本感知不到,但是一旦内存泄漏比较严重,用户的直观感觉就是页面/电脑开始操作卡顿、直到某一时刻彻底卡死或者页面/应用崩溃闪退,这种情况下会让用户对你的产品丧失信任感。

  • PC 浏览器:浏览器卡顿、甚至崩溃
  • iOS:早期 UIWebView 由于与 app 共享内存空间, 会容易导致app/浏览器卡顿、白屏、甚至崩溃,甚至 input 传个大图/文件如果处理不当就直接崩;之后 WKWebView 虽然优化了 WebView 内存及管理,但仍存在很多bug,加上 iPhone 本身内存空间较小,综合起来还是容易出现卡顿、白屏、甚至崩溃问题;
  • 安卓:相比 iPhone,安卓设备通常内存空间较大,且 WebView 的内存分配更足,这为 WebView 的稳定性提供了一些帮助,但是安卓由于生态混乱,加上引擎等对 js 支持的问题,会导致很多奇葩问题,更容易出现内存泄漏。容易出现卡顿、白屏、甚至崩溃问题;

相比于 PC 端,移动端硬件条件往往较为落后,并且 WebView 环境和内存限制也更为严格。并且移动端由于存在系统限制,不像PC端能方便进行浏览器更新/切换,因此更难以通过环境改善进行WebView管理优化,因此移动端的内存问题会更为严重,需要得到足够的重视。

通常 PC 端通过代码或引导浏览器更新/切换来减少内存问题,PC 应用也可以更新内核来优化环境,总体成本较小。移动端主流的优化手段就是优化内核/内存管理,有能力/有切实需求的往往会自研内核以减少内存问题,像很多安卓应用会基于 QQX5 进行改造,这些成本也往往较大并且还有宿主环境的限制要求。关于内存优化及管理本文就不做具体说明了。

SPA 页面需要更加关注

在 SPA 页面中,内存并不会在每次导航切换时自动清除,相比于 MPA 更容易引发内存泄漏。因此SPA中事件监听、DOM操作、网络请求、定时器等都需要更加关注。


真机内存检测

最通用的检测手段——Chrome DevTool

1.“任务管理器”——查看整体情况

入口为 Chrome 右上角设置 - 更多工具 - 任务管理器Setting - More Tools - Task Manager)。

p-chrome-1

并且我们可以通过右键菜单选择需要展示的字段:

p-chrome-2

其中字段说明:

  • 任务:Task
  • 个人资料:Profile
  • 内存占用空间:Memory Footprint
  • CPU
  • 网络:Network
  • 进程ID:Process ID
  • 图片缓存:Image Cache
  • 脚本缓存:Script Cache
  • CSS缓存:CSS Cache
  • GPU缓存:GPU Memory
  • SQLite使用的内存:SQLite Memory
  • NaCI调试端口:NaCI Debug Port
  • JavaScript 使用的内存:JavaScript Memory
  • 闲置状态唤醒:Idle Wake Ups
  • 文件描述符:File Descriptors
  • 进程优先级:Process Priority
  • 正在使用相应拓展程序的活动数:Keepalive Count

2.Performance——js Heap 查看时间轴上的内存变化情况

Performance 大家会用的相对多些,只要我们勾选了 Memory 便可以增加内存的变化统计。

p-chrome-3

*Recorder,结合用户事件进行记录

Chrome 97开始支持(大约是在2021.10),可以作为 Performance 的 plus 版,增加了用户操作等相关的事件记录,以更好得定位具体操作场景:

p-chrome-7

p-chrome-8

官网使用介绍:《Chrome Developers——Record, replay and measure user flows》

3.Memory ——查看某段/一时刻内存具体快照信息

真要定位内存问题,这是必不可少的工具,它的使用也比较简单。

p-chrome-4

选择模式:

  • Heap snapshot:堆快照,用以打印堆快照,堆快照文件显示页面的 js 对象和相关 DOM 节点之间的内存分配;
  • Allocation instrumentation on timeline: 在时间轴上记录内存信息,随着时间变化记录内存信息;
  • Allocation sampling: 内存信息采样,使用采样的方法记录内存分配。此配置文件类型具有最小的性能开销,可用于长时间运行的操作。它提供了由 js 执行堆栈细分的良好近似值分配。

筛选

选择模式进行快照后,可通过右上选择模块进行筛选:

  • 快照查看方式:默认Summary
    • Summary: 可以显示按构造函数名称分组的对象。使用此视图可以根据按构造函数名称分组的类型深入了解对象(及其内存使用),适用于跟踪 DOM 泄漏。
    • Comparison: 可以显示两个快照之间的不同。使用此视图可以比较两个(或多个)内存快照在某个操作前后的差异。检查已释放内存的变化和参考计数,可以确认是否存在内存泄漏及其原因。
    • Containment: 此视图提供了一种对象结构视图来分析内存使用,由顶级对象作为入口。
    • Statistic:内存使用饼状的统计图。
  • 对象归类的筛选:对Constructor的筛选
  • 对象选择:默认All objects

展示字段

表中展示字段的说明:

  • Contructor:表示使用此构造函数创建的所有对象
  • Distance:显示使用节点最短简单路径时距根节点的距离
  • Shallow Size: 显示通过特定构造函数创建的所有对象浅层大小的总和。浅层大小是指对象自身占用的内存大小(一般来说,数组和字符串的浅层大小比较大)
  • Retained Size: 显示同一组对象中最大的保留大小。某个对象删除后(其依赖项不再可到达)可以释放的内存大小称为保留大小。
  • New:(Comparison 特有)新增项
  • Deleted:(Comparison 特有)删除项
  • Delta:(Comparison 特有)增量
  • Alloc. Size:(Comparison 特有)内存分配大小
  • Freed Size:(Comparison 特有)释放大小
  • Size Delta:(Comparison 特有)内存增量

官网术语解释:《Chrome Developers——Memory terminology》

搜索

ctrl/command + F 唤醒搜索,根据关键字进行筛选

p-chrome-5

4.Performance monitor——简易查看

p-chrome-6

Performance monitor 是实时的,但是没办法看到细节信息。

Chrome排查内存的手段和场景还有很多,如

  • 检查ArrayBuffer《Chrome Developers——Inspect JavaScript ArrayBuffer with the Memory inspector》

移动端——Chrome/Safari

相比于PC,移动端真机调试一直是比较麻烦的,特别是内存分析难以像样式调试这种可以借助一些 socket 连接手段(Performance Memory兼容拉跨),所以要查看移动端页面的真实内存使用情况需要设备/环境帮助。

iOS——Safari

有线,需要有一台 iPhone 、Mac 和数据线。

步骤

  • 1.确认手机设置(设置 -> Safari -> 高级 -> Web检查器为打开状态);
  • 2.USB连接真机;
  • 3.确认设备信任;
  • 4.手机和电脑都打开Safari;
  • 5.Safari菜单中开发-XXX 的 iPhone,点击开始调试。

注意如果要看时间线的内存变化,菜单选择为时间线、左侧编程选中内存模块,如:

p-safari-1

特别提醒,要查看内存情况的话最好只选择内存一个指标模块,有多个指标选择的话容易 Safari 崩溃闪退。

*iOS 也能通过 ios-webkit-debug-proxy 然后使用 Chrome 进行调试,本身机制也是通过创建代理服务器与 Chrome 进行连接,可参考这篇文章:《How to debug remote iOS device using Chrome DevTools》

安卓/鸿蒙——Chrome/Android Studio

与iOS调试比较类似,有线,需要有一台 安卓手机 、Windows/Mac电脑 和数据线。

Chrome官方说明:《Chrome Developers——Remote debug Android devices》

步骤

  • 1.确认手机设置(开发者模式打开 -> USB调试打开状态);

  • 2.USB连接真机;

  • 3.确认设备信任;

  • 4.手机和电脑都打开 Chrome;

  • 5.PC Chrome访问chrome://inspect:确认连接状态
    p-dchrome-1

  • 6.选择对应页面的’inspect’进行访问
    p-dchrome-2

Android Studio 的调试模式与 Chrome 类似,也依赖 Chrome,操作可以参考《How to debug Android Chrome from Windows, Linux, or Mac——Install Android Debug Bridge (ADB)》

特别提醒:如果通过'inspect'进行访问时,发现调试控制台始终空白或者404,大概率为控制台涉及的js文件加载失败,大部分js文件需要翻墙访问,这时候需要翻一下。

有没有不用插线的远程方法

有,但是需要设备在一个网段。在开发电脑上建立个 Web 服务器并托管一个站点,然后从 Android 设备访问内容。具体可以查看文档说明:《Chrome Developers——Access local servers》

app内页面

一般通用的方案就是装 debug app,然后可以通过 IDE debug 或者再借助 Safari/Chrome。这种方式的主要问题就是有 debug 包及环境的要求;
要么就是用客户端开发的模拟器进行排查。这种方式的主要问题就是因为是模拟环境,与真实环境有一定区别;
要么就是客户端提供控制台,将内存信息放到控制台中展示,如滴滴的DoraemonKit,但要注意,iOS 现在 App 基本会用 WKWebView,这种情况下客户端是拿不到页面(WebView)的内存信息的(因为系统共享 WebView 虚拟内存),因此像 DoraemonKit 的内存模块也是无法观察页面内存情况,这时候的方案就是获取整个设备的内存信息,通过观察设备内存变化来进行判断,缺点就是难以保证其他应用及系统的影响;

iOS 开发获取内存的相关代码:

// 获取当前app消耗的内存,注意捕获不了WebView的内存消耗
+ (NSUInteger)useMemoryForApp {
  task_vm_info_data_t vmInfo;
  mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
  kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
  if (kernelReturn == KERN_SUCCESS) {
    int64_t memoryUsageInByte = (int64_t) vmInfo.phys_footprint;
	return memoryUsageInByte / 1024 / 1024;
  } else {
    return -1;
  }
}

// 获取整个设备的内存情况
+ (NSUInteger)totalMemoryForDevice {
  return [NSProcessInfo processInfo].physicalMemory / 1024 / 1024;
}

*js VM

最后还有一种方式就是利用Chrome和服务器搭建一套js VM 调试生态,如下小程序开发者工具也是这种模式,有兴趣可以看下Chrome DevTools Protocol: https://chromedevtools.github.io/devtools-protocol/

小程序——开发者工具

像微信/支付宝的小程序开发者工具,通常都较好得利用了Chrome 67起支持的js VM内存工具,因此可以非常方便得远程进行真机内存分析。

p-weapp-1


另外借助无头浏览器 Puppeteer,我们可以做到内存检测的自动化

快速手段——FuiteJs

github地址:https://github.com/nolanlawson/fuite

Fuite是一个 js 写的 cli 工具,它基于 Puppeteer 分析页面是否存在内存泄漏,对SPA友好

注意:Fuite需要 nodejs v14.14.0及以上的环境,(目前 nodejs 稳定版在16+)

原理机制

Fuite 比较简单,主要通过监控路由跳转来判断是否存在内存泄漏:

  • 1.使用 Puppeteer 打开对于参数的页面;
  • 2.找到页面中所有路由页面并打开;
  • 3.模拟后退(路由返回);
  • 4.重复(默认为7次)以确认是否存在内存泄漏。整个库的主要逻辑处理就是这块。判断依据:
    • Objects:对象(Chrome heap snapshots)
    • Event listeners:事件监听
    • DOM节点
    • Arrays, Maps, Sets、普通Object

如果 Fuite 发现存在泄漏情况,它将在控制台或者 output文件中展示信息。

使用

命令式

安装及测试

npx fuite https://blog.michealwayne.cn

使用:

fuite [options] <url>

参数:

  url                        URL to load in the browser and analyze

其中Options:

  -o, --output <file>        Write JSON output to a file
  -i, --iterations <number>  Number of iterations (default: 7)
  -s, --scenario <scenario>  Scenario file to run
  -S, --setup <setup>        Setup function to run
  -H, --heapsnapshot         Save heapsnapshot files
  -d, --debug                Run in debug mode
  -p, --progress             Show progress spinner (use --no-progress to disable)
  -b, --browser-arg <arg>    Arg(s) to pass when launching the browser
  -V, --version              output the version number
  -h, --help                 display help for command

引用式

import { findLeaks } from 'fuite';

const myScenario = {
  async setup(page) { /* ... */ },			// 默认无
  async createTests(page) { /* ... */ },	// 默认拿href
  async iteration(page, data) { /* ... */ }	// 默认为页面后退的往返
};

for await (const result of findLeaks('https://blog.michealwayne.cn', {
  scenario: myScenario,		// scenario参数可选,默认为defaultScenario
})) {
  console.log(result);
}

有意思的是,Fuite 的作者用 Fuite 对10个前端主流框架的主页进行了测试,发现都存在泄漏问题(作者在统计中隐藏了具体名称,有兴趣可以试一下):

p-auth-page1

延伸

我们可以扩展延伸 Fuite 的功能和使用场景,以更好地服务业务内存检测:

  • 1.服务化:我们可以将 Fuite 放在服务器,通过配置化进行定时检查,以及对应的异常报警等,将内存检测服务化、平台化;
  • 2.集群处理:使用 Fuite 通常耗时会比较久,如果有多个地址需要检测的话建议起多进程集群进行分开检测;
  • 3.改造:Fuite 逻辑是获取页面中所有路由进行检测,我们可以调整筛选控制,并且对 MPA 的处理进行业务优化,以提升检测效率和覆盖率。

最后

并非所有内存泄漏都是需要解决的问题,如 v8 的 JIT 也会导致内存增长,但作为 web 开发者,我们有义务通过工具方法找出业务中所有内存泄漏的场景。

*本人github:https://github.com/MichealWayne、博客地址:https://blog.michealwayne.cn/


相关链接

  • https://developer.chrome.com/docs/devtools/open/
  • https://nolanlawson.com/2021/12/17/introducing-fuite-a-tool-for-finding-memory-leaks-in-web-apps/
  • https://developer.chrome.com/docs/devtools/memory-problems/
  • https://github.com/nolanlawson/fuite
  • https://developer.chrome.com/blog/new-in-devtools-67/
  • https://gilfink.medium.com/help-my-memory-is-leaking-bf5dcaf83fc6
  • https://chromedevtools.github.io/
  • https://chromedevtools.github.io/devtools-protocol/
  • https://github.com/google/ios-webkit-debug-proxy
  • https://medium.com/@nikoloza/how-to-debug-remote-ios-device-using-chrome-devtools-f44d697003a7
  • https://raygun.com/blog/debug-android-chrome/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/117732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring(一)】初识Spring(史上最详细的Spring介绍!)

文章目录前言1.初识Spring2.Spring Framework系统架构3.核心概念前言 在学习 Spring 之前&#xff0c;我们需要先知道为什么要学习它?    IT业的任何一门技术,它只有抢占了很强的市场占有率&#xff0c;才会有更多的人使用和学习它&#xff0c;Spring技术在我们Java开发界拥…

APP怎么免费接入MobPush

1、获取AppKey 申请Appkey的流程&#xff0c;请点击 http://bbs.mob.com/thread-8212-1-1.html?fromuid70819 2、下载SDK 下载解压后&#xff0c;如下图&#xff1a; 目录结构 &#xff08;1&#xff09;Sample&#xff1a;演示Demo。&#xff08;2&#xff09;SDK&#…

【C操作符】详解操作符

操作符前言一、操作符分类二、算数操作符三、移位操作符&#xff08;一&#xff09;原码、补码、反码&#xff08;二&#xff09;操作符应用1.左移操作符&#xff08;1&#xff09;正数&#xff08;2&#xff09;负数&#xff08;3&#xff09;总结2.右移操作符&#xff08;1&a…

《码出高效:java开发手册》六-数据结构与集合(二)

前言 接上篇&#xff0c;第六章第二部分&#xff0c;上篇讲到了红黑树的FixAfterInsertion方法&#xff0c;这个方法原理与fixAfterDelete类似&#xff0c;只讲这个添加时的调整方法 代码可以看到&#xff0c;调整后的根节点一定是黑色的&#xff0c;叶子节点可红可黑&#x…

Spring 之 @Import 注解使用与源码浅析

1、Import 的作用&#xff1f; 再说 Import 之前先回忆下 Component 的作用&#xff0c;在类上标注该注解&#xff0c;该类就能够被 Spring 扫描封装成 BeanDefinition 并注册到容器中。但现在需要将第三方 jar 包、或者其他路径下面的包中的类也要被扫描注册呢&#xff1f;使…

Unity 制作一个简单的星系

使用素材&#xff1a; 1.Planets with Space Background in Flat Style 2.Planet Icons 创建场景 编写脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Cytaster : MonoBehaviour {[SerializeField]private float rotate_s…

【LeetCode】矩阵置零 [M](矩阵)

73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&a…

uni-app - 封装全局 API 调用弹框组件

uni-app - 在纯 JS 文件中调用自定义弹框组件 / 封装全局 API 调用弹框组件&#xff08;解决小程序、APP 无法使用 document.body.appendChild 插入组件节点&#xff09;适配全端 uni-app中实现一个全局弹层组件 引用超级全局组件方案 一、安装 npm install vue-inset-loade…

零入门容器云网络-9:命令行式操作tun设备介绍

已发表的技术专栏&#xff08;订阅即可观看所有专栏&#xff09; 0  grpc-go、protobuf、multus-cni 技术专栏 总入口 1  grpc-go 源码剖析与实战  文章目录 2  Protobuf介绍与实战 图文专栏  文章目录 3  multus-cni   文章目录(k8s多网络实现方案) 4  gr…

测开工具:spring boot 实现同步数据库表结构

源码&#xff1a; GitHub - 18713341733/mysqlsync 一、使用场景 一个项目&#xff0c;有多套开发环境。有一套标准的数据库&#xff0c;不同的开发环境&#xff0c;有各自的一套数据库。 标准数据库的表结构经常发生变化&#xff0c;不同的开发环境中的数据库&#xff0c;…

C#,图像二值化(04)——全局阈值 Kittler 算法及其源程序

1、Kittler算法&#xff08;最小误差法&#xff09;概述 最小误差法是 J. Kittler & J. Illingworth 1986年在《MINIMUM ERROR THRESHOLDING》文章中提出的一种基于直方图的阈值分割方法,简称 Kittler 算法。其思想:假设灰度图像由目标和背景组成,且目标和背景满足一混合高…

11个技巧让你成为更好的 Typescript 程序员

学习 Typescript 通常是一次重新发现之旅。您的最初印象可能非常具有欺骗性&#xff1a;这不就是一种注释 Javascript 的方式&#xff0c;所以编译器可以帮助我找到潜在的错误吗&#xff1f; 通过 r/mevlixreddit 虽然这句话通常是正确的&#xff0c;但随着您继续前进&#xff…

【聆思CSK6 视觉AI开发套件试用】AI识别试用以及闭坑方案

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;X Y Z 非常感谢能有这次机会体验聆思CSK6 视觉AI开发套件。上班的一大早收到了快递&#xff0c;迫不及待的打开快递。必须先来个图&#xff0…

4个技巧,节约网络工程师一半的时间

01 批量ping网段 对于一个网段ip地址众多&#xff0c;如果单个检测实在麻烦&#xff0c;那么你就可以直接批量ping网段检测&#xff0c;那个ip地址出了问题&#xff0c;一目了然。 先看代码&#xff0c;直接在命令行窗口输入&#xff1a; for /L %D in (1,1,255) do ping 10…

渗透测试神器--Burp Suite

一、介绍 Burp Suite 是用于攻击web 应用程序的集成平台。Burp Suite是一款信息安全从业人员必备的集成型的渗透测试工具&#xff0c;它采用自动测试和半自动测试的方式&#xff0c;包含了Proxy、Spider、Scanner、Intruder、Repeater、Sequencer、Decoder、Comparer等工具模块…

uniapp 窗口小工具、桌面小部件、微件 Ba-AppWidget

简介&#xff08;下载地址&#xff09; Ba-AppWidget 是一款窗口小工具&#xff08;桌面小部件、微件&#xff09;插件&#xff0c;默认为音乐播放器的样式&#xff0c;有其他界面需要&#xff0c;可联系作者定制。 支持点击事件监听支持动态更改页面内容支持设置小工具的预览…

区块链(一): 以太坊基础知识

目录什么是区块链&#xff1f;什么是以太坊&#xff1f;什么是加密货币&#xff1f;以太坊与比特币有什么不同&#xff1f;以太坊能做什么&#xff1f;什么是智能合约&#xff1f;以太坊社区以太坊白皮书什么是区块链&#xff1f; 区块链是一个交易数据库&#xff0c;在网络中…

容器,容器技术,云容器相关入门知识

前言 最近面试了一家国企&#xff0c;交谈愉快&#xff0c;对方的工程师问到容器时&#xff0c;突然愣了一下。脑子里有学习前端时候学习的docker&#xff0c;但印象里docker可不能代表容器技术&#xff0c;于是学习容器相关知识后整理相关知识以作巩固。 什么是容器 有点开…

SuperMap iDesktop/iDesktopX 端性能优化

作者&#xff1a;yd&hyy 一、背景 在使用iDesktop/iDesktopX的三维场景加载GIS数据的过程中&#xff0c;随着数据的种类、大小、数量的增多&#xff0c;往往会有很多的性能问题&#xff0c;加载速率缓慢&#xff0c;数据显示清晰度不足&#xff0c;多数据交叠显示错误&am…

『分分钟玩转VueRouter●上』VueRouter的一些基础配置

文章目录前言一、vue中如何使用VueRouter?二、路由使用的基本配置1.多级路由配置2.路由中的query参数3.命名路由4.路由的params参数5.路由的props配置6.router-link的replace属性7.通配符路由前言 计算机网络中有一个路由的概念&#xff1a;路由是指网络数据包发送到目的地址的…