Android 性能优化之黑科技开道(一)

news2024/11/20 23:16:06

1. 缘起

在开发电视版智家 App9.0 项目的时候,发现了一个性能问题。电视系统原本剩余的可用资源就少,而随着 9.0 功能的进一步增多,特别是门铃、门锁、多路视频同屏监控后等功能的增加,开始出现了卡顿情况。

经过调研分析发现有一部分是日志输出导致的,profiler 工具显示有一个日志输出的线程会有频繁占用 CPU 时间片的现象。

2. 性能优化引起的 Android 日志开关控制问题及解决

2.1 查看日志线程的 CPU 占用率 

使用 Profiler 查看 CPU 占用率,在打开日志及关闭日志的情况下分别如下:

 (图 1 日志开关打开的情况)

 (图 2 日志开关关闭的情况下)

 由上可以看出,存在两个问题:

  1. 日志开关打开的情况下,占用 CPU 时间比较多

  2. 日志开关关闭的情况下,比打开的情况好一些,但还是会有一些 CPU 占用,通过打日志发现,是有一些日志没有关闭,还在频繁的继续打印

2.2 需要日志开关方案?

  1. 发现关不掉的 TAG 大部分第三方库中的,它们没有对外提供使能接口,导致日志关不掉,为了性能考虑,需要对第三方库中的日志进行控制,在必要时可以关闭它们;

  2. 如果线上的版本不关闭日志,会存在用户隐私或产品信息泄漏的风险,为了 APP 和用户安全考虑,需要关闭线上版本的日志输出;

  3. 另外,为了更加方便的发现错误,我们应该对日志级别进行控制,例如我们可以采用如下方案:无论任何时候都输出 E 级别日志,其它级别日志可以根据情况进行关闭;

 结论:我们需要一个统一关闭和控制所有日志的开关方案。

2.3 方案调研 

方案

方案介绍

优点

缺点

混淆

采用混淆 proguard 配置方式关闭 APP 日志输出,包括:

android.util.Log 类

java.io.PrintStream 类(java.lang.System.out.println( )和 java.lang.System.out.print()系列

实现简单,想关哪个关哪个

  1. 不能动态控制,版本一经编译就不能再更改了

  2. 在没有开启混淆的 App 上,需要先开启混淆,需要仔细调试保证没有问题

  3. 能控制 Java 层的日志输出,不能控制 Native 层

插桩+ASM

通过 AOP 编程,在日志输出的某个类中进行字节码插桩,实现控制日志输出的目的

灵活,稳定性高

  1. 实现复杂度较混淆要高

  2. 需要找到合适的适合插桩的点

Hook

通过反射或其它技术,针对日志输出的某一个实现点,进行 Hook,进而实现控制的目的

灵活,稳定性高

  1. 实现复杂度较混淆要高

  2. 需要找到合适的需要 Hook 的点和 Hook 技术

混淆

  1. 混淆方案有个缺点,就是不能通过开关动态的调节日志开关,先做为备选吧

 插桩

  1. 经过技术预研,发现插桩的方案如果选用 Transform, 只能修改自己写的类或者是第三方库中的类,而影响不到 Android SDK 中的类 android.util.Log

  2. 在暂时未找到其它插桩点的情况下,此方案行不通

 Hook

  1. Hook 方案有很多种,需要根据具体的情况进行分析,选择合适的方案

Hook 技术

适用范围

主要原理

优点

缺点

反射+动态代理

Java 层部分场景

虚拟机提供的能力

稳定性高

技术门槛低

适用范围小

ClassLoader 修改

Java 层全部

修改 ClassLoader 加载类的顺序

稳定性高,Java 层都可以替换

需要提前准备好替换的 Dex

JNI Hook

Java 层与 native 间的函数

native 函数指针存储在表中,重定向表中的函数指针

稳定性高

只能 Hook native 方法

Xposed 类

Java 层全部

虚拟机中的目标函数为 Native,然后利用 JNI hook 重定向

java 层全 hook,hook 接口友好,有大量 Hook 插件可以使用和参考

ART/Dalvik 虚拟机每个版本都有不少改动,需适配。稳定性较差

GOT

native 层动态链接库入口函数

Linux 进程会链接 so 到内存中,并给 so 的入口函数们分配地址。原理是重定向入口地址

稳定性高

只能 Hook so 的入口函数,不能 Hook so 的内部

Inline hook

native 层全部

目标函数执行指令代码中插入 Jump 指令实现重定向

hook native everything

和 cpu 指令集相关,需要针对性汇编实现,稳定性较一般,技术门槛相对高

  1. 经过分析,发现

    1. Java 层的两种方案(反射+动态代理、ClassLoader 修改)不能满足我们的需求

    2. Native 的两种方案(GOT 和 inline hook)确实很强大,但在这里我们还用不到修改这么底层的内容

    3. 而 Xposed 框架类型的方案又太重

    4. 对比后发现,JniHook 正好能够满足我们的需求。Hook 并重定向 android.util.Log 类中的 native 方法(print_native)即可满足要求。

2.4 实现原理(对 Log 类进行 JniHook)

原理图:

2.5 最终效果

1. 通过我们的开关控制逻辑关闭了所有的 Java 日志,并保留 Error 级别的日志输出,如下图

2. 收益

  1. 提升了性能,CPU 占用率减少约 17%

  2. 有效防止了敏感信息泄漏,保护了用户隐私

  3. 使用自己的策略灵活管控了日志的输出

其它可以黑科技优化的方向是什么?下期敬请期待~

3. 团队介绍

「三翼鸟数字化技术平台-场景设计交互平台」主要负责设计工具的研发,包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力,研发并沉淀素材库,构建家居家装素材库,集成户型库、全品类产品库、设计方案库、生产工艺模型,打造基于户型和风格的AI设计能力,快速生成算量和报价;同时研发了门店设计师中心和项目中心,包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理,同时为水,空气,厨房等产业提供商机管理工具,从而实现了以场景贯穿的B端C端全流程系统。

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

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

相关文章

OpenHarmony实战:Makefile方式组织编译的库移植

以yxml库为例,其移植过程如下文所示。 源码获取 从仓库获取yxml源码,其目录结构如下表: 表1 源码目录结构 名称描述yxml/bench/benchmark相关代码yxml/test/测试输入输出文件,及测试脚本yxml/Makefile编译组织文件yxml/.gitat…

C语言:文件操作(一)

目录 前言 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 结(一) 前言 本篇文章将介绍C语言的文件操作,在后面的内容讲到:为什么使用文…

2024-04-03 NO.4 Quest3 手势追踪抓取物体

文章目录 1 手势抓取方式1.1 Hand Grab1.2 Touch Hand Grab1.3 Distance Hand Grab 2 HandGrabExamples 示例场景2.1 Interactor 对象2.2 Interactable 对象2.2.1 父子结构2.2.2 “Hand Grab lnteractable” 脚本2.2.3 “Move Towards Target Provider” 脚本2.2.4 其他 Moveme…

OpenHarmony实战:CMake方式组织编译的库移植

以double-conversion库为例,其移植过程如下文所示。 源码获取 从仓库获取double-conversion源码,其目录结构如下表: 表1 源码目录结构 名称描述double-conversion/cmake/CMake组织编译使用到的模板double-conversion/double-conversion/源…

浅谈分布式光伏电站的运维管理

摘要:随着近些年我国对节能降耗关注力度的持续加大,为满足人们不断增长的电能需求,光伏发电产业得到迅猛发展,其中分布式光伏发电的比重持续增长。在打赢脱贫攻坚战的大背景下,国家电网公司探索出一条“阳光扶贫”的扶…

第十三届蓝桥杯JavaA组省赛真题 - 青蛙过河

解题思路: 定义一个累和数组arr,我们可以比较arr[ i ]和arr[ l ]之间的差值看是否大于等于2倍的x,满足则证明这两点之间可以跳满所有实际过河次数,此时记录最大距离,并移动左边界 l import java.util.Scanner;public…

大数据时代下,如何利用信息化、数字化、数智化成为行业领先者

在大数据时代背景下,企业的竞争力提升离不开信息化、数字化和数智化的联动作用。首先,企业需通过信息化手段,将业务流程、管理方式等进行标准化和系统化,提高效率和减少错误。同时,借助数字化技术如云计算、物联网等&a…

抖店体验分是什么?怎么快速提升体验分?今天一篇带你搞懂!

大家好,我是电商小布。 经营小店的小伙伴应该都有发现,当自己的店铺成功出够30单之后,小店就会出现体验分这个东西。 简单来说,这个就相当于是对我们店铺的一个综合评价,包括有商品、物流、服务三个方面。 这个分数…

前端作业之完成学校官方网页的制作

&#xff08;未使用框架&#xff0c;纯html和css制作&#xff09; 注&#xff1a;由本人技术限制&#xff0c;代码复用性极差 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>xxx大学</tit…

java框架学习——注解/元注解概述及使用案例

前言&#xff1a; 整理下学习笔记&#xff0c;打好基础&#xff0c;daydayup!!! 注解 注解&#xff08;Annotation&#xff09;是java代码里的特殊标记。作用为&#xff1a;让其他程序根据注解信息来决定怎么执行该程序&#xff0c;如&#xff1a;Override,Test等。同时可以根…

换到idf 5.0版本后报错 jsmn could not be found

原因&#xff1a; idf5.0去掉了部分组件&#xff0c;包括jsmn&#xff0c;工程中adf又用到了这个组件&#xff0c;所以会报错。 解决办法&#xff1a; 升级adf到新版本即可。

从C到C++过渡知识 中(为什么C++支持函数重载,而C不支持函数重载)

感谢大家的阅读&#xff0c;这篇文章我们接着了解C对于C的一些优化。 函数重载 了解C这个特殊用法之前&#xff0c;我们先考虑一个问题&#xff0c;如何交换两个整数。相信大家一定信手捏来&#xff0c;实参传地址而非变量&#xff0c;于是可以写出如下函数。 void Swap(int*…

无极低码:免费版部署操作指南

无极低码 :https://wheart.cn 无极低码:免费试用版部署过程参照: 无极低码部署版操作指南 https://wheart.cn/so/home?m=index&id=ad614930-d936-11ee-8489-525400be6368 ” 。 下载完解压成后进行部署

Codeforces Round 837 (Div. 2) C. Hossam and Trainees

题目 #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e9, maxm 4e4 5; const int N sqrt(1…

硬件RAID横评(上)

正文共&#xff1a;3857字 50图&#xff0c;预估阅读时间&#xff1a;12 分钟 之前误打误撞测试了软件RAID&#xff08;Windows下软RAID测试&#xff09;&#xff0c;发现性能基本上是线性的&#xff0c;而据说硬件RAID性能比这个高的很。那本文将就硬件RAID展开测试&#xff0…

【leetcode】 c++ 数字全排列, test ok

1. 问题 2. 思路 3. 代码实现 #if 0 class Solution { private:vector<int> path; // 满足条件的一个结果 vector<vector<int>> res; // 结果集 void backtracking(vector<int> nums, vector<bool> used){// 若path的个数和nums个数相等,说明…

C++中的vector与C语言中的数组的区别

C中的vector和C语言中的数组在很多方面都有所不同&#xff0c;以下是它们之间的一些主要区别&#xff1a; 大小可变性&#xff1a; vector是C标准模板库&#xff08;STL&#xff09;提供的动态数组容器&#xff0c;它的大小可以动态增长或减少。这意味着你可以在运行时添加或删…

JavaScript高级 —— 学习(三)

目录 一、深入面向对象 &#xff08;一&#xff09;面向对象介绍 &#xff08;二&#xff09;面向对象编程 &#xff08;oop&#xff09; 1.面向对象编程介绍 2.面向对象编程优点 3.面向对象的特征 4.和面向过程编程对比 二、构造函数 &#xff08;一&#xff09;介绍…

STM32 移植 LVGL -- 教程图解

&#xff08; 编辑状态中&#xff0c;已完成80%&#xff0c;估计清明假期后完成更新 ) 移植效果&#xff0c;先睹为快&#xff1a; 目录 一、LVGL 简述 二、准备一个STM32的工程 三、LVGL 官方下载 四、裁剪 源文件 五、添加 源文件 六、注册 显示 七、注册 触摸输入 八…

014——超声波模块驱动开发Plus(基于I.MX6uLL、SR04和poll机制)

目录 一、基础知识 二、分析为什么打印会影响中断 三、驱动程序 四、应用程序 五、验证及其它 一、基础知识 013——超声波模块驱动开发&#xff08;基于I.MX6uLL与SR04&#xff09;-CSDN博客 二、分析为什么打印会影响中断 asmlinkage __visible int printk(const ch…