Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dev] AndroidPerformanceMonitor源码笔记 #99

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions blockcanary-analyzer/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '25.0.3'
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract class AbstractSampler {
protected AtomicBoolean mShouldSample = new AtomicBoolean(false);
protected long mSampleInterval;

private Runnable mRunnable = new Runnable() {
private Runnable mRunnable = new Runnable() {/*在子线程中定时取样*/
@Override
public void run() {
doSample();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,24 @@ public final class BlockCanaryInternals {

private List<BlockInterceptor> mInterceptorChain = new LinkedList<>();

public BlockCanaryInternals() {
// TODO: 2017/3/3 BlockCanaryInternals构造函数 (4)
public BlockCanaryInternals() {/*初始化*/

stackSampler = new StackSampler(
stackSampler = new StackSampler(/*堆栈数据Sampler*/
Looper.getMainLooper().getThread(),
sContext.provideDumpInterval());

cpuSampler = new CpuSampler(sContext.provideDumpInterval());
cpuSampler = new CpuSampler(sContext.provideDumpInterval());/*Cpu数据Sampler*/

/*设置自定义Printer,打印Looper dispatchMessage(msg)前后的时间*/
setMonitor(new LooperMonitor(new LooperMonitor.BlockListener() {

// TODO: 2017/3/3 卡顿时间超过设置:触发线程卡顿回调 (9)
@Override
public void onBlockEvent(long realTimeStart, long realTimeEnd,
long threadTimeStart, long threadTimeEnd) {
long threadTimeStart, long threadTimeEnd) {/*当页面卡顿时回调*/
// Get recent thread-stack entries and cpu usage
/*获取最新显存堆栈信息及Cpu使用情况*/
ArrayList<String> threadStackEntries = stackSampler
.getThreadStackEntries(realTimeStart, realTimeEnd);
if (!threadStackEntries.isEmpty()) {
Expand All @@ -60,25 +64,27 @@ public void onBlockEvent(long realTimeStart, long realTimeEnd,
.setRecentCpuRate(cpuSampler.getCpuRateInfo())
.setThreadStackEntries(threadStackEntries)
.flushString();
LogWriter.save(blockInfo.toString());
LogWriter.save(blockInfo.toString());/*保存卡顿信息*/

if (mInterceptorChain.size() != 0) {
if (mInterceptorChain.size() != 0) {/*检查拦截器*/
for (BlockInterceptor interceptor : mInterceptorChain) {
// TODO: 2017/3/3 通知DisplayService等监听,弹出Notification提示出现线程卡顿 (12)
interceptor.onBlock(getContext().provideContext(), blockInfo);
}
}
}
}
}, getContext().provideBlockThreshold()));

LogWriter.cleanObsolete();
LogWriter.cleanObsolete();/*重置过期数据*/
}

/**
* Get BlockCanaryInternals singleton
*
* @return BlockCanaryInternals instance
*/
// TODO: 2017/3/3 初始化BlockCanaryInternals (3)
static BlockCanaryInternals getInstance() {
if (sInstance == null) {
synchronized (BlockCanaryInternals.class) {
Expand All @@ -102,19 +108,19 @@ public static void setContext(BlockCanaryContext context) {
public static BlockCanaryContext getContext() {
return sContext;
}

/*添加拦截器*/
void addBlockInterceptor(BlockInterceptor blockInterceptor) {
mInterceptorChain.add(blockInterceptor);
}

/*设置自定义Printer*/
private void setMonitor(LooperMonitor looperPrinter) {
monitor = looperPrinter;
}

/*取样间隔*/
long getSampleDelay() {
return (long) (BlockCanaryInternals.getContext().provideBlockThreshold() * 0.8f);
}

/*数据保存路径*/
static String getPath() {
String state = Environment.getExternalStorageState();
String logPath = BlockCanaryInternals.getContext()
Expand All @@ -126,15 +132,15 @@ static String getPath() {
}
return Environment.getDataDirectory().getAbsolutePath() + BlockCanaryInternals.getContext().providePath();
}

/*创建文件夹*/
static File detectedBlockDirectory() {
File directory = new File(getPath());
if (!directory.exists()) {
directory.mkdirs();
}
return directory;
}

/*获取所有Log文件*/
public static File[] getLogFiles() {
File f = detectedBlockDirectory();
if (f.exists() && f.isDirectory()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void start() {

/**
* Get cpu rate information
*
* 获取cpu数据
* @return string show cpu rate information
*/
public String getCpuRateInfo() {
Expand All @@ -78,7 +78,7 @@ public String getCpuRateInfo() {
}
return sb.toString();
}

/*检测Cpu使用是否繁忙*/
public boolean isCpuBusy(long start, long end) {
if (end - start > mSampleInterval) {
long s = start - mSampleInterval;
Expand All @@ -104,7 +104,7 @@ protected void doSample() {
BufferedReader cpuReader = null;
BufferedReader pidReader = null;

try {
try {/*获取Cpu使用信息*/
cpuReader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/stat")), BUFFER_SIZE);
String cpuRate = cpuReader.readLine();
Expand All @@ -115,6 +115,7 @@ protected void doSample() {
if (mPid == 0) {
mPid = android.os.Process.myPid();
}
/*获取当前进程的Cpu使用信息*/
pidReader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/" + mPid + "/stat")), BUFFER_SIZE);
String pidCpuRate = pidReader.readLine();
Expand Down Expand Up @@ -147,7 +148,7 @@ private void reset() {
mTotalLast = 0;
mAppCpuTimeLast = 0;
}

/*解析系统cpu及进程cpu使用信息*/
private void parse(String cpuRate, String pidCpuRate) {
String[] cpuInfoArray = cpuRate.split(" ");
if (cpuInfoArray.length < 9) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import android.os.Handler;
import android.os.HandlerThread;

/*Handler工厂*/
final class HandlerThreadFactory {

private static HandlerThreadWrapper sLoopThread = new HandlerThreadWrapper("loop");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ private LogWriter() {
* @param str block info string
* @return log file path
*/
// TODO: 2017/3/3 保存卡顿数据 (11)
public static String save(String str) {
String path;
synchronized (SAVE_DELETE_LOCK) {
Expand All @@ -60,6 +61,7 @@ public static String save(String str) {

/**
* Delete obsolete log files, which is by default 2 days.
* 删除过期数据
*/
public static void cleanObsolete() {
HandlerThreadFactory.getWriteLogThreadHandler().post(new Runnable() {
Expand Down Expand Up @@ -94,7 +96,7 @@ public static void deleteAll() {
}
}
}

/*保存卡顿log数据*/
private static String save(String logFileName, String str) {
String path = "";
BufferedWriter writer = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import android.os.SystemClock;
import android.util.Printer;

/*自定义Printer*/
class LooperMonitor implements Printer {

private static final int DEFAULT_BLOCK_THRESHOLD_MILLIS = 3000;
Expand All @@ -43,17 +43,18 @@ public LooperMonitor(BlockListener blockListener, long blockThresholdMillis) {
mBlockThresholdMillis = blockThresholdMillis;
}

// TODO: 2017/3/3 重新Printer的println方法,监听Message Loop,同时记录该时间间隔的调用栈及CPU占用数据(6)
@Override
public void println(String x) {
if (!mPrintingStarted) {
if (!mPrintingStarted) {/*记录println message 时当前时间,同时开始dump 堆栈及cpu数据*/
mStartTimestamp = System.currentTimeMillis();
mStartThreadTimestamp = SystemClock.currentThreadTimeMillis();
mPrintingStarted = true;
startDump();
} else {
} else {/*记录end time ,停止dump 堆栈及cpu数据*/
final long endTime = System.currentTimeMillis();
mPrintingStarted = false;
if (isBlock(endTime)) {
if (isBlock(endTime)) {/*isBlock 回调监听*/// TODO: 2017/3/3 触发线程卡顿 (7)
notifyBlockEvent(endTime);
}
stopDump();
Expand All @@ -64,6 +65,7 @@ private boolean isBlock(long endTime) {
return endTime - mStartTimestamp > mBlockThresholdMillis;
}

// TODO: 2017/3/3 卡顿时间超过设置:触发线程卡顿 (8)
private void notifyBlockEvent(final long endTime) {
final long startTime = mStartTimestamp;
final long startThreadTime = mStartThreadTimestamp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public StackSampler(Thread thread, int maxEntryCount, long sampleIntervalMillis)
mMaxEntryCount = maxEntryCount;
}

// TODO: 2017/3/3 获取某个时间间隔内的线程调用栈数据 (10)
public ArrayList<String> getThreadStackEntries(long startTime, long endTime) {
ArrayList<String> result = new ArrayList<>();
synchronized (sStackMap) {
Expand All @@ -58,6 +59,7 @@ public ArrayList<String> getThreadStackEntries(long startTime, long endTime) {

@Override
protected void doSample() {
/*定时取样,获取当前主线程的堆栈信息*/
StringBuilder stringBuilder = new StringBuilder();

for (StackTraceElement stackTraceElement : mCurrentThread.getStackTrace()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

/**
* Information to trace a block.
* 实体类
*/
public class BlockInfo {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Pattern;

/*性能工具类*/
class PerformanceUtils {
private static final String TAG = "PerformanceUtils";

Expand All @@ -40,7 +40,7 @@ private PerformanceUtils() {

/**
* Get cpu core number
*
* 获取cpu内核数
* @return int cpu core number
*/
public static int getNumCores() {
Expand All @@ -66,14 +66,14 @@ public boolean accept(File pathname) {
}
return sCoreNum;
}

/*获取空闲存储空间*/
public static long getFreeMemory() {
ActivityManager am = (ActivityManager) BlockCanaryInternals.getContext().provideContext().getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
return mi.availMem / 1024;
}

/*获取总存储空间*/
public static long getTotalMemory() {
if (sTotalMemo == 0) {
String str1 = "/proc/meminfo";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import com.github.moduth.blockcanary.BlockCanaryInternals;

import java.util.List;

/*进程工具类*/
public class ProcessUtils {

private static volatile String sProcessName;
Expand Down
1 change: 1 addition & 0 deletions blockcanary-android-no-op/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '25.0.3'
}

dependencies {
Expand Down
5 changes: 3 additions & 2 deletions blockcanary-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '25.0.3'
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
// compile project(':blockcanary-analyzer')
compile 'com.github.markzhai:blockcanary-analyzer:1.4.1'
compile project(':blockcanary-analyzer')
// compile 'com.github.markzhai:blockcanary-analyzer:1.4.1'
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public final class BlockCanary {
private BlockCanaryInternals mBlockCanaryCore;
private boolean mMonitorStarted = false;

private BlockCanary() {
// TODO: 2017/3/3 BlockCanary 构造函数 (2)
private BlockCanary() {/*初始化*/
BlockCanaryInternals.setContext(BlockCanaryContext.get());
mBlockCanaryCore = BlockCanaryInternals.getInstance();
mBlockCanaryCore.addBlockInterceptor(BlockCanaryContext.get());
Expand All @@ -56,8 +57,10 @@ private BlockCanary() {
* @param blockCanaryContext BlockCanary context
* @return {@link BlockCanary}
*/
// TODO: 2017/3/3 BlockCanary (1)
public static BlockCanary install(Context context, BlockCanaryContext blockCanaryContext) {
BlockCanaryContext.init(context, blockCanaryContext);
/*设置以组件的形式DisplayActivity 是否有效*/
setEnabled(context, DisplayActivity.class, BlockCanaryContext.get().displayNotification());
return get();
}
Expand All @@ -81,6 +84,7 @@ public static BlockCanary get() {
/**
* Start monitoring.
*/
// TODO: 2017/3/3 设置自定义Printer,监听Message Loop(5)
public void start() {
if (!mMonitorStarted) {
mMonitorStarted = true;
Expand Down Expand Up @@ -134,6 +138,7 @@ public boolean isMonitorDurationEnd() {
// these lines are originally copied from LeakCanary: Copyright (C) 2015 Square, Inc.
private static final Executor fileIoExecutor = newSingleThreadExecutor("File-IO");

/*在子线程中开启/禁用四大组件*/
private static void setEnabledBlocking(Context appContext,
Class<?> componentClass,
boolean enabled) {
Expand All @@ -157,7 +162,7 @@ private static void setEnabled(Context context,
final Class<?> componentClass,
final boolean enabled) {
final Context appContext = context.getApplicationContext();
executeOnFileIoThread(new Runnable() {
executeOnFileIoThread(new Runnable() {/*在子线程中开启/禁用DisplayActivity 组件*/
@Override
public void run() {
setEnabledBlocking(appContext, componentClass, enabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class DisplayService implements BlockInterceptor {

private static final String TAG = "DisplayService";

// TODO: 2017/3/3 弹出Notification提示出现线程卡顿 (13)
@Override
public void onBlock(Context context, BlockInfo blockInfo) {
Intent intent = new Intent(context, DisplayActivity.class);
Expand All @@ -55,7 +56,7 @@ private void show(Context context, String contentTitle, String contentText, Pend
context.getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification;
if (SDK_INT < HONEYCOMB) {
if (SDK_INT < HONEYCOMB) {/*低于11的版本,通过反射setLatestEventInfo创建Notification*/
notification = new Notification();
notification.icon = R.drawable.block_canary_notification;
notification.when = System.currentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.util.Date;
import java.util.Locale;


/*文件上传类*/
final class Uploader {

private static final String TAG = "Uploader";
Expand Down
Loading