区块链技术博客
www.b2bchain.cn

Systrace 基础知识(十) – Binder 和锁竞争解读求职学习资料

本文介绍了Systrace 基础知识(十) – Binder 和锁竞争解读求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

本文是 Systrace 系列文章的第十篇,主要是对 Systrace 中的 Binder 和锁信息进行简单介绍,简单介绍了 Binder 的情况,介绍了 Systrace 中 Binder 通信的表现形式,以及 Binder 信息查看,SystemServer 锁竞争分析等

本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。

Binder 概述

Android 的大部分进程间通信都使用 Binder,这里对 Binder 不做过多的解释,想对 Binder 的实现有一个比较深入的了解的话,推荐你阅读下面三篇文章

  1. 理解Android Binder机制1/3:驱动篇
  2. 理解Android Binder机制2/3:C++层
  3. 理解Android Binder机制3/3:Java层

之所以要单独讲 Systrace 中的 Binder 和锁,是因为很多卡顿问题和响应速度的问题,是因为跨进程 binder 通信的时候,锁竞争导致 binder 通信事件变长,影响了调用端。最常见的就是应用渲染线程 dequeueBuffer 的时候 SurfaceFlinger 主线程阻塞导致 dequeueBuffer 耗时,从而导致应用渲染出现卡顿; 或者 SystemServer 中的 AMS 或者 WMS 持锁方法等待太多, 导致应用调用的时候等待时间比较长导致主线程卡顿

这里放一张文章里面的 Binder 架构图 , 本文主要是以 Systrace 为主,所以会讲 Systrace 中的 Binder 表现,不涉及 Binder 的实现
Systrace 基础知识(十) - Binder 和锁竞争解读

Binder 调用图例

Binder 主要是用来跨进程进行通信,可以看下面这张图,简单显示了在 Systrace 中 ,Binder 通信是如何显示的
Systrace 基础知识(十) - Binder 和锁竞争解读

图中主要是 SystemServer 进程和 高通的 perf 进程通信,Systrace 中右上角 ViewOption 里面勾选 Flow Events 就可以看到 Binder 的信息
Systrace 基础知识(十) - Binder 和锁竞争解读

点击 Binder 可以查看其详细信息,其中有的信息在分析问题的时候可以用到,这里不做过多的描述
Systrace 基础知识(十) - Binder 和锁竞争解读

对于 Binder,这里主要介绍如何在 Systrace 中查看 Binder 锁信息锁等待这两个部分,很多卡顿和响应问题的分析,都离不开这两部分信息的解读,不过最后还是要回归代码,找到问题后,要读源码来理顺其代码逻辑,以方便做相应的优化工作

Systrace 显示的锁的信息

Systrace 基础知识(十) - Binder 和锁竞争解读

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

上面的话分两段来看,以 blocking 为分界线 

第一段信息解读

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2

Monitor 指的是当前锁对象的池,在 Java 中,每个对象都有两个池,锁(monitor)池和等待池:

锁池(同步队列 SynchronizedQueue ):假设线程 A 已经拥有了某个对象(注意:不是类 )的锁,而其它的线程想要调用这个对象的某个 synchronized 方法(或者 synchronized 块),由于这些线程在进入对象的 synchronized 方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程 A 拥有,所以这些线程就进入了该对象的锁池中。

这里用了争夺(contention)这个词,意思是这里由于在和目前对象的锁正被其他对象(Owner)所持有,所以没法得到该对象的锁的拥有权,所以进入该对象的锁池

Owner : 指的是当前拥有这个对象的锁的对象。这里是 Binder:1605_B,4667 是其线程 ID。

at 后面跟的是拥有这个对象的锁的对象正在做什么。这里是在执行 void com.android.server.wm.ActivityTaskManagerService.activityPaused 这个方法,其代码位置是 :ActivityTaskManagerService.java:1733 其对应的代码如下:

com/android/server/wm/ActivityTaskManagerService.java

@Override public final void activityPaused(IBinder token) {     final long origId = Binder.clearCallingIdentity();     synchronized (mGlobalLock) { // 1733 是这一行         ActivityStack stack = ActivityRecord.getStackLocked(token);         if (stack != null) {             stack.activityPausedLocked(token, false);         }     }     Binder.restoreCallingIdentity(origId); }

可以看到这里 synchronized (mGlobalLock) ,获取了 mGlobalLock 锁的拥有权,在他释放这个对象的锁之前,任何其他的调用 synchronized (mGlobalLock) 的地方都得在锁池中等待

waiters 值得是锁池里面正在等待锁的操作的个数;这里 waiters=2 表示目前锁池里面已经有一个操作在等待这个对象的锁释放了,加上这个的话就是 3 个了

第二段信息解读

blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

第二段信息相对来说简单一些,就是标识了当前被阻塞等锁的方法 , 这里是 ActivityManager 的 getFocusedStackInfo 被阻塞,其对应的代码

com/android/server/wm/ActivityTaskManagerService.java

@Override public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {     enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");     long ident = Binder.clearCallingIdentity();     try {         synchronized (mGlobalLock) { // 2064 是这一行              ActivityStack focusedStack = getTopDisplayFocusedStack();             if (focusedStack != null) {                 return mRootActivityContainer.getStackInfo(focusedStack.mStackId);             }             return null;         }     } finally {         Binder.restoreCallingIdentity(ident);     } }

可以看到这里也是调用了 synchronized (ActivityManagerService.this) ,从而需要等待获取 ams 对象的锁拥有权

总结

上面这段话翻译过来就是

ActivityTaskManagerService 的 getFocusedStackInfo 方法在执行过程中被阻塞,原因是因为执行同步方法块的时候,没有拿到同步对象的锁的拥有权;需要等待拥有同步对象的锁拥有权的另外一个方法 ActivityTaskManagerService.activityPaused 执行完成后,才能拿到同步对象的锁的拥有权,然后继续执行

可以对照原文看上面的翻译

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

本文是 Systrace 系列文章的第十篇,主要是对 Systrace 中的 Binder 和锁信息进行简单介绍,简单介绍了 Binder 的情况,介绍了 Systrace 中 Binder 通信的表现形式,以及 Binder 信息查看,SystemServer 锁竞争分析等

本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。

Binder 概述

Android 的大部分进程间通信都使用 Binder,这里对 Binder 不做过多的解释,想对 Binder 的实现有一个比较深入的了解的话,推荐你阅读下面三篇文章

  1. 理解Android Binder机制1/3:驱动篇
  2. 理解Android Binder机制2/3:C++层
  3. 理解Android Binder机制3/3:Java层

之所以要单独讲 Systrace 中的 Binder 和锁,是因为很多卡顿问题和响应速度的问题,是因为跨进程 binder 通信的时候,锁竞争导致 binder 通信事件变长,影响了调用端。最常见的就是应用渲染线程 dequeueBuffer 的时候 SurfaceFlinger 主线程阻塞导致 dequeueBuffer 耗时,从而导致应用渲染出现卡顿; 或者 SystemServer 中的 AMS 或者 WMS 持锁方法等待太多, 导致应用调用的时候等待时间比较长导致主线程卡顿

这里放一张文章里面的 Binder 架构图 , 本文主要是以 Systrace 为主,所以会讲 Systrace 中的 Binder 表现,不涉及 Binder 的实现
Systrace 基础知识(十) - Binder 和锁竞争解读

Binder 调用图例

Binder 主要是用来跨进程进行通信,可以看下面这张图,简单显示了在 Systrace 中 ,Binder 通信是如何显示的
Systrace 基础知识(十) - Binder 和锁竞争解读

图中主要是 SystemServer 进程和 高通的 perf 进程通信,Systrace 中右上角 ViewOption 里面勾选 Flow Events 就可以看到 Binder 的信息
Systrace 基础知识(十) - Binder 和锁竞争解读

点击 Binder 可以查看其详细信息,其中有的信息在分析问题的时候可以用到,这里不做过多的描述
Systrace 基础知识(十) - Binder 和锁竞争解读

对于 Binder,这里主要介绍如何在 Systrace 中查看 Binder 锁信息锁等待这两个部分,很多卡顿和响应问题的分析,都离不开这两部分信息的解读,不过最后还是要回归代码,找到问题后,要读源码来理顺其代码逻辑,以方便做相应的优化工作

Systrace 显示的锁的信息

Systrace 基础知识(十) - Binder 和锁竞争解读

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

上面的话分两段来看,以 blocking 为分界线 

第一段信息解读

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2

Monitor 指的是当前锁对象的池,在 Java 中,每个对象都有两个池,锁(monitor)池和等待池:

锁池(同步队列 SynchronizedQueue ):假设线程 A 已经拥有了某个对象(注意:不是类 )的锁,而其它的线程想要调用这个对象的某个 synchronized 方法(或者 synchronized 块),由于这些线程在进入对象的 synchronized 方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程 A 拥有,所以这些线程就进入了该对象的锁池中。

这里用了争夺(contention)这个词,意思是这里由于在和目前对象的锁正被其他对象(Owner)所持有,所以没法得到该对象的锁的拥有权,所以进入该对象的锁池

Owner : 指的是当前拥有这个对象的锁的对象。这里是 Binder:1605_B,4667 是其线程 ID。

at 后面跟的是拥有这个对象的锁的对象正在做什么。这里是在执行 void com.android.server.wm.ActivityTaskManagerService.activityPaused 这个方法,其代码位置是 :ActivityTaskManagerService.java:1733 其对应的代码如下:

com/android/server/wm/ActivityTaskManagerService.java

@Override public final void activityPaused(IBinder token) {     final long origId = Binder.clearCallingIdentity();     synchronized (mGlobalLock) { // 1733 是这一行         ActivityStack stack = ActivityRecord.getStackLocked(token);         if (stack != null) {             stack.activityPausedLocked(token, false);         }     }     Binder.restoreCallingIdentity(origId); }

可以看到这里 synchronized (mGlobalLock) ,获取了 mGlobalLock 锁的拥有权,在他释放这个对象的锁之前,任何其他的调用 synchronized (mGlobalLock) 的地方都得在锁池中等待

waiters 值得是锁池里面正在等待锁的操作的个数;这里 waiters=2 表示目前锁池里面已经有一个操作在等待这个对象的锁释放了,加上这个的话就是 3 个了

第二段信息解读

blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

第二段信息相对来说简单一些,就是标识了当前被阻塞等锁的方法 , 这里是 ActivityManager 的 getFocusedStackInfo 被阻塞,其对应的代码

com/android/server/wm/ActivityTaskManagerService.java

@Override public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {     enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");     long ident = Binder.clearCallingIdentity();     try {         synchronized (mGlobalLock) { // 2064 是这一行              ActivityStack focusedStack = getTopDisplayFocusedStack();             if (focusedStack != null) {                 return mRootActivityContainer.getStackInfo(focusedStack.mStackId);             }             return null;         }     } finally {         Binder.restoreCallingIdentity(ident);     } }

可以看到这里也是调用了 synchronized (ActivityManagerService.this) ,从而需要等待获取 ams 对象的锁拥有权

总结

上面这段话翻译过来就是

ActivityTaskManagerService 的 getFocusedStackInfo 方法在执行过程中被阻塞,原因是因为执行同步方法块的时候,没有拿到同步对象的锁的拥有权;需要等待拥有同步对象的锁拥有权的另外一个方法 ActivityTaskManagerService.activityPaused 执行完成后,才能拿到同步对象的锁的拥有权,然后继续执行

可以对照原文看上面的翻译

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

本文是 Systrace 系列文章的第十篇,主要是对 Systrace 中的 Binder 和锁信息进行简单介绍,简单介绍了 Binder 的情况,介绍了 Systrace 中 Binder 通信的表现形式,以及 Binder 信息查看,SystemServer 锁竞争分析等

本系列的目的是通过 Systrace 这个工具,从另外一个角度来看待 Android 系统整体的运行,同时也从另外一个角度来对 Framework 进行学习。也许你看了很多讲 Framework 的文章,但是总是记不住代码,或者不清楚其运行的流程,也许从 Systrace 这个图形化的角度,你可以理解的更深入一些。

Binder 概述

Android 的大部分进程间通信都使用 Binder,这里对 Binder 不做过多的解释,想对 Binder 的实现有一个比较深入的了解的话,推荐你阅读下面三篇文章

  1. 理解Android Binder机制1/3:驱动篇
  2. 理解Android Binder机制2/3:C++层
  3. 理解Android Binder机制3/3:Java层

之所以要单独讲 Systrace 中的 Binder 和锁,是因为很多卡顿问题和响应速度的问题,是因为跨进程 binder 通信的时候,锁竞争导致 binder 通信事件变长,影响了调用端。最常见的就是应用渲染线程 dequeueBuffer 的时候 SurfaceFlinger 主线程阻塞导致 dequeueBuffer 耗时,从而导致应用渲染出现卡顿; 或者 SystemServer 中的 AMS 或者 WMS 持锁方法等待太多, 导致应用调用的时候等待时间比较长导致主线程卡顿

这里放一张文章里面的 Binder 架构图 , 本文主要是以 Systrace 为主,所以会讲 Systrace 中的 Binder 表现,不涉及 Binder 的实现
Systrace 基础知识(十) - Binder 和锁竞争解读

Binder 调用图例

Binder 主要是用来跨进程进行通信,可以看下面这张图,简单显示了在 Systrace 中 ,Binder 通信是如何显示的
Systrace 基础知识(十) - Binder 和锁竞争解读

图中主要是 SystemServer 进程和 高通的 perf 进程通信,Systrace 中右上角 ViewOption 里面勾选 Flow Events 就可以看到 Binder 的信息
Systrace 基础知识(十) - Binder 和锁竞争解读

点击 Binder 可以查看其详细信息,其中有的信息在分析问题的时候可以用到,这里不做过多的描述
Systrace 基础知识(十) - Binder 和锁竞争解读

对于 Binder,这里主要介绍如何在 Systrace 中查看 Binder 锁信息锁等待这两个部分,很多卡顿和响应问题的分析,都离不开这两部分信息的解读,不过最后还是要回归代码,找到问题后,要读源码来理顺其代码逻辑,以方便做相应的优化工作

Systrace 显示的锁的信息

Systrace 基础知识(十) - Binder 和锁竞争解读

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

上面的话分两段来看,以 blocking 为分界线 

第一段信息解读

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2

Monitor 指的是当前锁对象的池,在 Java 中,每个对象都有两个池,锁(monitor)池和等待池:

锁池(同步队列 SynchronizedQueue ):假设线程 A 已经拥有了某个对象(注意:不是类 )的锁,而其它的线程想要调用这个对象的某个 synchronized 方法(或者 synchronized 块),由于这些线程在进入对象的 synchronized 方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程 A 拥有,所以这些线程就进入了该对象的锁池中。

这里用了争夺(contention)这个词,意思是这里由于在和目前对象的锁正被其他对象(Owner)所持有,所以没法得到该对象的锁的拥有权,所以进入该对象的锁池

Owner : 指的是当前拥有这个对象的锁的对象。这里是 Binder:1605_B,4667 是其线程 ID。

at 后面跟的是拥有这个对象的锁的对象正在做什么。这里是在执行 void com.android.server.wm.ActivityTaskManagerService.activityPaused 这个方法,其代码位置是 :ActivityTaskManagerService.java:1733 其对应的代码如下:

com/android/server/wm/ActivityTaskManagerService.java

@Override public final void activityPaused(IBinder token) {     final long origId = Binder.clearCallingIdentity();     synchronized (mGlobalLock) { // 1733 是这一行         ActivityStack stack = ActivityRecord.getStackLocked(token);         if (stack != null) {             stack.activityPausedLocked(token, false);         }     }     Binder.restoreCallingIdentity(origId); }

可以看到这里 synchronized (mGlobalLock) ,获取了 mGlobalLock 锁的拥有权,在他释放这个对象的锁之前,任何其他的调用 synchronized (mGlobalLock) 的地方都得在锁池中等待

waiters 值得是锁池里面正在等待锁的操作的个数;这里 waiters=2 表示目前锁池里面已经有一个操作在等待这个对象的锁释放了,加上这个的话就是 3 个了

第二段信息解读

blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

第二段信息相对来说简单一些,就是标识了当前被阻塞等锁的方法 , 这里是 ActivityManager 的 getFocusedStackInfo 被阻塞,其对应的代码

com/android/server/wm/ActivityTaskManagerService.java

@Override public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {     enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");     long ident = Binder.clearCallingIdentity();     try {         synchronized (mGlobalLock) { // 2064 是这一行              ActivityStack focusedStack = getTopDisplayFocusedStack();             if (focusedStack != null) {                 return mRootActivityContainer.getStackInfo(focusedStack.mStackId);             }             return null;         }     } finally {         Binder.restoreCallingIdentity(ident);     } }

可以看到这里也是调用了 synchronized (ActivityManagerService.this) ,从而需要等待获取 ams 对象的锁拥有权

总结

上面这段话翻译过来就是

ActivityTaskManagerService 的 getFocusedStackInfo 方法在执行过程中被阻塞,原因是因为执行同步方法块的时候,没有拿到同步对象的锁的拥有权;需要等待拥有同步对象的锁拥有权的另外一个方法 ActivityTaskManagerService.activityPaused 执行完成后,才能拿到同步对象的锁的拥有权,然后继续执行

可以对照原文看上面的翻译

monitor contention with owner Binder:1605_B (4667) at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Systrace 基础知识(十) – Binder 和锁竞争解读求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们