Android性能分析工具:Perfetto介绍及用法

news2024/11/29 22:36:13

   68a6b753b1217225171a2d7acf805f83.gif

本文字数:8409

预计阅读时间:22分钟

概念

什么是Perfetto?PerfettoAndroid 10中引入的全新平台级跟踪工具。这是适用于AndroidLinuxChrome的更加通用和复杂的开源跟踪项目。与Systrace不同,它提供数据源超集,可让您以protobuf编码的二进制流形式记录任意长度的跟踪记录。您可以在Perfetto界面中打开这些跟踪记录。Perfetto是一款比较强大的安卓性能分析工具(它还可以用于分析其他系统),其功能涵盖了对CPU的追踪、电池耗电追踪、系统调用的追踪,内存分配与释放的追踪。除了性能数据记录还,它还有自带的分析工具,分析工具包括:通过自定义追踪功能来拼接命令行,用SQL方式筛选数据,将数据转换成其他格式方便自定义数据处理,Web形式的火焰图(Web可离线),以及Web上的ADB功能(有bug)。

  • Perfetto的优缺点是什么?

优点:

1.功能强大;

2.效率高;

3.可靠性强。

缺点:

1.只针对Android 9及以上机型;

2.学习门槛略高,至少需要知道些许ADBPythonLLMpprofPerfetto命令行的知识点,才能熟练运用该工具;

3.功能复杂且已嵌入安卓系统中修改难度大;

4.无法过滤so,只能全部分析完了再筛选;

5.  暂时只能在Mac上操作,否则无法解析函数堆栈信息(需要自己编译一个windowstrace-to-text程序);

6.  无对比功能。

  • Perfetto的内存分析原理是什么?

Perfetto:

源码:git clone 

https://android.googlesource.com/platform/external/perfetto/

Perfetto也是使用注入(hook)的方式,将内存分配和释放的几个函数修改为自己的代码指令后,当内存分配和释放时进行统计。与LoliPerfiler不同的是,它有得天独厚的优势,就是它本身就是安卓系统自带的程序,不需要用JDWP方式启动某个程序,直接启动执行程序就可以了。

8af809e078eaa6c177656541821fc90f.png

系统分析(适用于Liux和Android系统范围分析)

Perfetto-系统分析,应用程序跟踪和跟踪分析。Perfetto是用于性能检测和跟踪分析的生产级开源堆栈。它提供用于记录系统级和应用程序级跟踪的服务和库,本机+Java堆分析,使用SQL分析跟踪的库以及基于WebUI以可视化和探索多GB跟踪。

bed2e8fdac7ad6cefbb15b2966ee2f6b.png

Linux内核跟踪:捕获高频ftrace数据:调度活动,任务切换延迟,CPU频率等等。

用户空间分析器和额外的探针:本机堆分析,Java堆分析,/ proc状态文件的轮询器。

内置于Android:自Android 9 Pie以来该平台的一部分,也可在Linux上运行。

应用追踪

raceconv工具将Perfetto跟踪转换为其他跟踪格式。

高效的跟踪点仪器:以高吞吐量,低开销的跟踪点记录C++应用程序的活动。

结构化和可配置的事件:定义自定义protobuf消息以表示强类型的应用程序特定信息,仅跟踪您需要的信息。

与系统范围的跟踪集成:在同一时间线上将应用程序的状态与系统范围内的分析数据相关联。

追踪查看器

heapprofdAndroid堆分析器。

92ba7c3580a55387f48979861db4db1f.png

CI用于AOSPTreeHugger的顶部(而不是替代)。它提供早期测试信号,并涵盖TreeHugger不支持的其他操作系统和较旧的Android设备。

有四个主要部分:

前端:AppEngine

控制器:AppEngine BG服务

工作者:Compute Engine + Docker

数据库:Firebase实时数据库

它们通过Firebase数据库耦合。DB是整个CI的真理之源。

交互式痕迹探索:使用Perfetto UI记录,查看和处理跟踪数据。

支持流行的跟踪格式文件:TraceEvent JSONAndroid systraceftrace文本输出。

完全在您的浏览器中运行:不涉及服务器交互,即使您离线也可以工作。

痕量分析

痕量分析-跟踪处理器是一个C++库(/ src / trace_processor),它吸收以多种格式编码的跟踪,并公开一个SQL接口,用于查询一致的表集中所包含的跟踪事件。它还具有其他功能,包括计算摘要度量,使用用户友好的描述注释跟踪以及从跟踪的内容派生新事件。

450b190ae0bb55907e7d3cd280267e02.png

867427eaddab9321c31bd4dec10ae413.png

基于SQL的跟踪模型:跟踪处理器提取跟踪并公开基于SQLite的接口以通过外壳和UI访问跟踪的内容。

大痕量分析:支持高达数十GB的跟踪。

可互操作的:可以导入和导出流行的跟踪格式:Chromium JSON跟踪格式,Android SystraceftraceCSV

Perfetto的使用方法

官方说明,CPU分析:

https://perfetto.dev/docs/quickstart/android-tracing#perfetto-cmdline

官方说明,c++内存分析:

https://perfetto.dev/docs/data-sources/native-heap-profiler

使用web界面:

https://ui.perfetto.dev

分析命令行说明:

https://perfetto.dev/docs/reference/perfetto-cli

堆内存分析说明:

https://perfetto.dev/docs/reference/heap_profile-cli

  • 使用系统工具获取跟踪记录

1)在Android 10的手机上,开发者模式新增加了一个“系统跟踪”的功能,我们首先将开发者模式下的“系统跟踪”打开:

fea90950953e35335ed907ff04f6dfce.png

79c70b6468eeabe184eb52979e9d3f05.png

2)从“类别”选项中选择我们关注的信息类别:

996cb0b989721d723c384c33963e522c.png

3)设置完之后,下拉快捷选项多了个棒棒糖形状的图标:

b01b082ea1a8f9c9782860a66f035174.png

这个时候杀掉我们需要调试的应用,然后点击开启棒棒糖,接着打开应用,等待应用完全打开之后,再点击一次棒棒糖,结束录制。

4)我们保存录制后生成的跟踪文件存储在设备的“/data/local/traces”目录下,文件的后缀名为“.perfetto-trace”,我们就可以在网站界面(https://ui.perfetto.dev)中打开这些跟踪记录,进行性能分析了。

bace9f9e09d5981b94031e6ca4f4aceb.png

  • 使用Perfetto网站获取perfetto-trace文件

1)打开https://ui.perfetto.dev;

2)点击record new trace

19fb6e7a6a27ffa24158b646eb133d57.png

3)在web站点上选指令,可选择更详细的指令,包括cpu综合数据、gpu综合数据、函数调用堆栈、内存memory分配情况;

4)开始录入,点击start recording,网站自动生成脚本代码,默认是10秒dump一次(或一次性导出);

9e9588707379f0573ec537e50e0d3233.png

5)点击stop结束录制,在/data/misc目录下,即可看到生成的.perfetto-trace文件。

  • 使用脚本语言

Android QP先设置:

adb shell setprop persist.traced.enable 1

Android Q以上perfetto默认运行,无需上述步骤。

常规选项:

下表列出了在perfetto的两种模式下都可使用的选项:

d4a2e24c9df06f8afe60765832c3a9c6.png

两种方式,两种方式不能混用:

简单模式:

6409ef5f1129960fac545f01f925c7a2.png

使用类似与systrace。如果需要设定时间加-t,默认跟踪10s。-o输出文件的位置,使用/data/misc/perfetto-traces/,否则perfetto没有权限访问, 然后pull出文件,在Perfetto UI中打开使用。如下命令可直接使用,通常这种信息对大多数情况都够用了。

生成.perfetto-trace文件:

adb shell perfetto gfx input view wm am ss sched freq idle binder_driver res rs  -o /data/misc/perfetto-traces/trace -t 10s

导出.perfetto-trace文件:

adb pull /data/misc/perfetto-traces/trace ~/trace

普通模式

6402439c9d0382704deca854f3ec466a.png

借助config文件配置要调试的内容,命令行如下,其中config.pbtx为config file,可以借助Perfetto UIrecording settingPerfetto UI)生成,或者在Perfetto UI中的redording settings中设置后好,在recording commandcopy所有内容,在terminal中直接copy执行即可。

cat config.pbtx | adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace.perfetto-trace

解析perfetto-trace文件

导入文件

官方网址:

https://ui.perfetto.dev/#!/

打开上述网址,点击Open trace file,选择本地录制好的perfetto traceftrace等文件,即可以Timeline方式展现各进程、线程的详细跟踪信息。

trace文件大于1G时,Open trace file会出现内存溢出无法访问。

787f4ab042581cdae6723ce30286f07e.png

此时需要使用trace_processor来辅助,该程序建议在Linux环境下运行,Win10系统可安装WSL (Ubuntu20.04),参考附录安装WSL

# 下载官方trace_processor

curl -LO https://get.perfetto.dev/trace_processor

chmod +x ./trace_processor

运行如下命令来加载perfetto trace文件:

./trace_processor --full-sort -D xxx.pftrace

Windows下也可以运行如下命令(不稳定,内存耗用大):

python3 trace_processor --full-sort -D xxx.pftrace

Chrome浏览器打开https://ui.perfetto.dev/#!/,会自动检测本地是否已经有trace_processor生成的HTTP SERVER(9001端口),如下图提示,请选择:

YES, use loaded trace”,将自动解析trace_processor已经加载的pftrace文件。

394e7afd39b8775ad101486130dbe5bc.png

常规分析

a. 图例指标

slice (片段,选中片段后会显示黑色边框),对应代码中Trace.beginSection/ATRACE_BEGIN记录的事件。

848666fff069bfb281569c46a921c4b9.png

counter (计数器,离散的数值点) 代码中Trace.traceCounter/ATRACE_INT记录的事件。

3a8c69e5495634f0e529ca1fdfa3d8df.png

sched/freq (CPU调度、频率)

4997551ba2c8b966605af70a0b346b2a.png

thread_state (线程状态)

点击片段上方线程调度信息片段(Running),可以看到线程当前运行在哪个CPU上。

35da7b6c69324472f822c50a19df7cd5.png

点击向右箭头图标,可以在CPU调度中看到该运行片段,可以看到调度时延信息。被P(Process):system_server的 T(Thread):Binder_1754_18线程唤醒,从就绪到运行延迟了363us,再次点击,可以回到原片段,这个跳转比systrace更加灵活方便。同样的,Binder调用也可以如此在目标和原调用线程跳转来分析查看。

4d426dd605b0c9bb7d29a43a9cee778b.png

b. 添加标记

点击最上方的时间轨道即可添加时间点标记;通过按住鼠标左键选中一块区域或者点击某一片段,然后按下“shift+m”即可添加常驻区域标记。选中已经添加的标记,底部出现的Current Selection TAB里可以为其添加标记名,更改其颜色,以及执行移除操作。

fa282f09e8909424a6741cd36caa0668.png

按下“m”添加的是临时区域标记,再次选中另外一块区域添加临时区域时,上一个临时区域会自动移除。

c. 锁竞争(lock contention)

看到lock contention片段,可以点击上边的monitor contention来查看当前对象锁竞争发生的调用栈,如下详情中显示当前对象锁被Owner (Binder:1754_16)持有,其持锁当前运行在serviceDoneExecuting(AMS.java 16426行),且当前等待该对象锁的线程已经有2个了;当前线程执行被阻塞在getUidState方法中(AMS.java 6614行)。

464e48b61c19d74a42afe6ee6b299597.png

SQL查询与展现

在已经加载traceperfetto UI界面,Search框中输入 : 即可开启SQL输入,我们就可以使用SQL来查询并定位具体的trace片段(slice)。

0fe3f041ae55f923c2f1428c1db54e8b.png

输入SQL语句,Enter,得到查询结果,显示在底部表格中,点击表格中的每一行,可以跳转到具体的slice中,根据trace上下文可以进一步分析问题。

1ac85bc2bc29b79c8af05db95b16686a.png

列举几个常用的SQL查询:

1

列出所有doFrame片段,按耗时倒序排列,取前100条

select  slice_id,track_id,ts,dur,dur/1e6,name from slice WHERE name like '%doFrame%'  order by dur desc limit 100

2

1查询的基础上,指定process name为systemui,即systemui自身的绘帧信息

select  slice_id,track_id,ts,dur,dur/1e6,slice.name from slice JOIN thread_track ON  slice.track_id = thread_track.id JOIN thread USING(utid) JOIN process  USING(upid) WHERE process.name = 'com.android.systemui' and slice.name like  '%doFrame%' order by dur desc limit 100

3

system_server中各OPF:关键字片段的耗时信息,包含各片段的真实running_time(每个slice可能有一段时间running,一段时间sleep,一段时间runnable,需要借助thread_state表来查询slice中各调度时间片的状态)

select  slice_id,track_id,thread.utid,slice.ts,slice.dur,(slice.dur/1e6) as dur_ms,  (select total(case when thread_state.ts < slice.ts then  MIN(slice.ts+slice.dur,thread_state.ts+thread_state.dur)-slice.ts when  (thread_state.ts+thread_state.dur) > (slice.ts+slice.dur) then  (slice.ts+slice.dur-MAX(thread_state.ts,slice.ts)) else thread_state.dur end)  from thread_state where thread_state.utid=thread.utid and  thread_state.state='Running' and thread_state.ts < (slice.ts+slice.dur)  and (thread_state.ts+thread_state.dur) > slice.ts)/1e6 as  total_running,slice.name from slice JOIN thread_track ON slice.track_id =  thread_track.id JOIN thread USING(utid) JOIN process USING(upid) WHERE  process.name='system_server' and slice.name like 'OPF:%' order by slice.dur  desc limit 400

4

system_server中的锁竞争情况(lockcontention),lock_depth表示当时参与此对象锁竞争的线程个数

select  count(1) as lock_depth, s.slice_id,s.track_id,s.ts,s.dur,s.dur/1e6 as  dur_ms,ctn.otid,s.name

from  slice s, (select slice_id,track_id,ts,dur,name,substr(name, 46,  instr(name,')')-46) as otid

from  slice t

WHERE  name like 'Lock contention on a monitor lock %'

order  by dur) ctn

JOIN  thread_track ON s.track_id=thread_track.id JOIN thread USING(utid) JOIN  process USING(upid)

WHERE

    process.name = 'system_server'

and  s.name like 'Lock contention on a monitor lock %'

    and substr(s.name, 46,  instr(s.name,')')-46) = ctn.otid

    and ctn.slice_id <> s.slice_id

    and ctn.ts >= s.ts and  (ctn.ts+ctn.dur) <= (s.ts+s.dur)

group  by s.slice_id

order  by s.dur desc

应用实战

来一个简单例子,模拟卡顿现象,代码如下:

f896a7f0e048a97b086121bab223c797.png

log立可以看出损耗的相关代码:

b7f00b2124c0ef3969cbcaf258a057e9.png

进入perfetto,导入trace文件,界面如下,找到对应的包名线程:

10b9203545afa5108515f2fd0ef12856.png

能看到onResume方法阻塞了4s的样子,这样能在具体的类里尽快定位产生耗时的方法,其余的功能可以具体分析。

项目实际应用

由于android手机日益更新换代,现在折叠屏手机已经面市,搜狐视频要根据折叠屏幕尺寸不同变化适配不同的UI展示,这次的需求。

是手机界面展示成这样:

39ec43b56c642c3ad9aa92f2a2ca24b9.png

折叠屏展开后展示成不同样子:

6bec84b562538cda2f01ecfbdec15576.png

结果发现只要手机展开就会无响应,然后就crash崩溃,log里也没啥有用信息,实在不好定位问题,百思不得其解,最后想到用Perfetto看看有没有什么有用信息,按照上述步骤得到trace文件,导入界面如下,找到搜狐视频的包名线程,可以看到:

124813cbced9f9d5ef4a8eea16d71ab8.png上千次执行RV onBindView方法,在代码里找到对应位置,发现是2个xmlUI都在刷新,所以导致图片View加载混乱,所以一直重复刷新,修改后切换界面就正常了,长叹一口气,问题圆满解决,鼓掌撒花~

参考

  • https://blog.csdn.net/imqingyue/article/details/124194680?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-124194680-blog-110933087.pc_relevant_multi_platform_featuressortv2dupreplace&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-124194680-blog-110933087.pc_relevant_multi_platform_featuressortv2dupreplace&utm_relevant_index=2

  • https://blog.csdn.net/u011578734/article/details/110933087

  • https://developer.android.google.cn/studio/command-line/perfetto

  • https://blog.csdn.net/vviccc/article/details/124567746?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6-124567746-blog-124194680.pc_relevant_layerdownloadsortv1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6-124567746-blog-124194680.pc_relevant_layerdownloadsortv1&utm_relevant_index=9

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

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

相关文章

【6.09 代随_52day】 最长递增子序列、最长连续递增序列、最长重复子数组

最长递增子序列、最长连续递增序列、最长重复子数组 最长递增子序列1.方法图解步骤递归代码 最长连续递增序列1.动态规划的方法图解步骤代码 最长重复子数组图解步骤代码 最长递增子序列 力扣连接&#xff1a;300. 最长递增子序列&#xff08;中等&#xff09; 1.方法 dp[i]…

开源 Golang 微服务入门三:ORM 框架 GORM

前言 前两篇笔记分别介绍了 Golang 微服务 HTTP 框架 Hertz 和 Golang 微服务 RPC 框架 Kitex&#xff0c;本文将要介绍面向ORM(持久层)框架 GORM。 官方文档 GORM 是面向 Golang 语言的一种 ORM(持久层)框架&#xff0c;支持多种数据库的接入&#xff0c;例如 MySQL&#x…

【TCP/IP】多进程服务器的实现(进阶) - 僵尸进程及wait、waitpid函数

目录 僵尸(Zombie)进程 僵尸进程的产生机制 僵尸进程的危害 僵尸进程的销毁 wait函数 waitpid函数 进程管理在网络编程中十分重要&#xff0c;如果未处理好&#xff0c;将会导致出现“僵尸进程”&#xff0c;进而影响服务器端对进程的管控。 僵尸(Zombie)进程 第一次听到…

继万物分割SAM之后,万物识别模型RAM来了!

Recognize Anything: A Strong Image Tagging Model 提出“识别万物模型”&#xff08;Recognize Anything Model&#xff0c;RAM&#xff09;&#xff0c;用于图像打标签。RAM 可以高精度地识别任何常见类别。RAM 引入了图像打标签的一个新范式&#xff0c;利用大规模的图像-文…

如何在RPC和RESTful之间做选择?

不同软件系统之间的通信可以通过RPC&#xff08;远程过程调用&#xff09;或RESTful&#xff08;表现层状态转移&#xff09;协议来建立&#xff0c;这些协议允许多个系统在分布式计算中协同工作。 这两种协议在设计哲学上有所区别。RPC使得可以像调用本地过程一样调用服务器上…

AI时代已经到来,不想被抛弃,特别是传统产业的你,怎么办?

由于ChatGTP的惊人表现&#xff0c;本来已经趋于平淡的AI&#xff0c;又火爆起来。毫无疑问&#xff0c;人类已经进入了AI时代&#xff0c;AI将渗入到各行各业&#xff0c;渗入到生活与工作的每个方面。这是一场新的工业革命&#xff0c;很多工作都将消失&#xff0c;但也会产生…

【Python】Python进阶系列教程-- Python3 MySQL - mysql-connector 驱动(三)

文章目录 前言创建数据库连接创建数据库创建数据表主键设置 插入数据批量插入查询数据where 条件语句排序Limit删除记录更新表数据删除表 前言 往期回顾&#xff1a; Python进阶系列教程-- Python3 正则表达式&#xff08;一&#xff09;Python进阶系列教程-- Python3 CGI编程…

记录--7 个沙雕又带有陷阱的 JS 面试题

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 为了保证的可读性&#xff0c;本文采用意译而非直译。 在 JS 面试中&#xff0c;经常会看到一些简单而又沙雕的题目&#xff0c;这些题目包含一些陷阱&#xff0c;但这些在我们规范的编码下或者业务中…

基于BP神经网络的轨迹跟踪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

NLP(1):Introduction

文章目录 Why process textChallengesText processingword, sentence, document, corpus, tokenProcessing stepsSentence segmentationWord TokenizationMaxMatch AlgorithmSubword Tokenization &#xff08;BPE&#xff09;BPE 算法 Word NormalizationStop Words Remove Wh…

数据分析第17课seaborn绘图

关系型绘图 seaborn.relplot() 这个函数功能非常强大,可以用来表示多个变量之间的关联关系。默认情况下是绘制散点图(散点图是看到变量与变量之间相关性最优的一个图形),也可以绘制线性图,具体绘制什么图形是通过kind参数来决定的。实际上以下两个函数就是relplot的特例…

Vue2 事件的默认和传播行为、事件修饰符

前言 在学习vue2时&#xff0c;学到了 事件修饰符&#xff0c;但是对事件的默认行为和传播行为不太理解&#xff0c;所以也就是不知道为啥要使用事件修饰符&#xff0c;所以找了一些资料&#xff0c;在此记录一下。 Vue2官方文档 事件处理 — Vue.js (vuejs.org)https://v2.…

【 Python 全栈开发 - WEB开发篇 - 29 】MySQL初步

文章目录 一、MySQL介绍二、SQL语言三、MySQL安装与配置第一步&#xff1a;下载压缩文件第二步&#xff1a;解压第三步&#xff1a;配置第四步&#xff1a;登录 一、MySQL介绍 MySQL 是一个开源的关系型数据库管理系统&#xff0c;它使用 Structured Query Language&#xff0…

JDBC的增删改查

文章目录 前言创建数据库基础版JDBC实例添加JDBC实例删除JDBC实例修改JDBC实例查询 高级版JDBC实例添加JDBC实例删除JDBC实例修改JDBC实例查询 前言 JDBC编程步骤&#xff1a; 加载数据库驱动程序创建数据库连接对象创建Statement语句对象&#xff08;createStatement、prepa…

谈谈聚簇索引与非聚簇索引

技术主题 聚簇索引是一种数据的存储方式,它的数据行只存放在索引(B+树)的叶子上,内部节点不存放数据。 聚簇索引 聚簇索引默认是主键,如果没有定义主键,innodb会选择一个唯一的非空索引代替。如果没有这种索引,innodb会隐式定义一个主键作为聚簇索引。 非聚簇索引 非…

百度出品,Nature重磅 -- 优化的mRNA设计算法可改善mRNA的稳定性和免疫原性

摘要 尽管mRNA疫苗已用于COVID-19的预防&#xff0c;但仍然面临不稳定和易降解的风险&#xff0c;这是mRNA疫苗存储、配送、效价等面临的重要障碍。先前的研究已表明&#xff0c;增加二级结构可延长mRNA的半衰期&#xff0c;再加上选择优化的密码子&#xff0c;可改善蛋白表达。…

Django实现接口自动化平台(五)httprunner(2.x)基本使用【持续更新中】

上一章&#xff1a; Django实现接口自动化平台&#xff08;四&#xff09;解决跨域问题【持续更新中】_做测试的喵酱的博客-CSDN博客 下一章&#xff1a; 一、参考地址&#xff1a; 使用说明_httprunner2.0 概述及使用说明 二、介绍 HttpRunner是一款面向 HTTP(S) 协议的通…

一文带你了解MySQL之锁

目录 一、解决并发事务带来问题的两种基本方式1.1 一致性读&#xff08;Consistent Reads&#xff09;1.2 锁定读&#xff08;Locking Reads&#xff09;1.2.1 共享锁和独占锁1.2.2 锁定读的语句 1.3 写操作 二、多粒度锁三、MySQL中的行锁和表锁3.1 其他存储引擎中的锁3.2 Inn…

高通KMD框架详解

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、概览二、核心模块解析三、模块初始化四、处理UMD CSL请求 一、概览 利用了V4L2可扩展这一特性&#xff0c;高通在相机驱动部分实现了自有的一套KMD…

未来3年,请善待你的工作

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) “如果不是现在环境差&#xff0c;下家不好找&#xff0c;我早TM跟那个傻X老板翻桌子走人了&#xff0c;这破公司我真是一天都不想待…”这是一位粉丝朋友给K哥私信中的一段话。类似同款的话&#xff…