AOSP CameraLatencyHistogram的原理与使用

168 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

AOSP代码引用参考:www.aospxref.com/

可以搜索到android各个版本的代码,比较方便,不必下载AOSP代码。

image.png

CameraLatencyHistogram是什么

CameraLatencyHistogram是AOSP Camera模块的一个工具类,主要作用是进行直方图统计,针对一些有时延的操作,比如request执行的时间,dequeue buffer的时间等,做直方图统计,最后用于性能相关问题的debug。 核心源代码位置: /frameworks/av/services/camera/libcameraservice/utils/LatencyHistogram.cpp

源码解析

头文件定义

image.png

其中,

  • mBinSizeMs 记录的是当前记录表的标准时间,比如预设一次request的标准时长为40ms
  • mBinCount 记录的是直方图的等级划分数量,通常默认是10个等级
  • mBins 记录的是直方图各个等级的数量
  • mTotalCount 记录的是直方图的统计数量总数

类初始化

image.png

初始化上述的变量,注意,这里对vector进行的初始化,实际上是设定vector的size大小,不是将第一个元素设定为binCount。

增加一个数据/清空所有数据

image.png

add一个数据时: 先计算时间差,注意,这里是ns,然后转换为ms,再与标准时间做除法(计算机的整数除法只取整数部分,比如标准时间是40ms,本次耗时30ms,则除法得到0,耗时70ms,则除法得到1),这样就能保证0<=t<mBinSizeMs的时长index为0,然后依次类推到9mbinSizeMs<=t<10mBinSizeMs的index为9;

然后针对小于0和大于等于10的做归一化操作;

然后对应存储位置加一,总数加一。

dump/log以及内部处理函数formatHistogramText

image.png

dump的逻辑:

  • 先dump数据的行头,标识dump时的记录数据量;
  • 然后将直方图数据构造成字符串;
  • 将直方图数据写入到对应的fd文件中。

log函数的操作与dump基本一致,只是这时是调用Android log 打印出来。

image.png

这个函数的作用就是将统计结果表示成字符串:

  • 先打印耗时的时间段,如33ms/66ms/99ms,最大值打印为inf (max ms)
  • 然后打印每一个段数据占总数据量的百分比100.0*mBins[i]/mTotalCount
  • 最后打印一个%号。

使用该工具的位置

mDequeueBufferLatency:dequeue buffer的时延,5ms

///frameworks/av/services/camera/libcameraservice/device3/Camera3OutputStream.h
//dequebuffer默认耗时5ms,进行记录 
static const int32_t kDequeueLatencyBinSize = 5; // in ms C
ameraLatencyHistogram mDequeueBufferLatency; 

status_t Camera3OutputStream::getBuffersLocked(std::vector<OutstandingBuffer>* outBuffers) { 
    ... 
    nsecs_t dequeueStart = systemTime(SYSTEM_TIME_MONOTONIC); 
    res = consumer->dequeueBuffers(&buffers); 
    nsecs_t dequeueEnd = systemTime(SYSTEM_TIME_MONOTONIC);
    mDequeueBufferLatency.add(dequeueStart, dequeueEnd); 
    ... 
}

mBufferLimitLatency:buffer signal时延,33ms

///frameworks/av/services/camera/libcameraservice/device3/Camera3Stream.h
// Latency histogram of the wait time for handout buffer count to drop below 
// max_buffers. 
static const int32_t kBufferLimitLatencyBinSize = 33; //in ms 
CameraLatencyHistogram mBufferLimitLatency; 
status_t Camera3Stream::getBuffer(camera_stream_buffer *buffer, nsecs_t waitBufferTimeout, const std::vector<size_t>& surface_ids) { 
    ... 
    nsecs_t waitStart = systemTime(SYSTEM_TIME_MONOTONIC); 
    if (waitBufferTimeout < kWaitForBufferDuration) { 
        waitBufferTimeout = kWaitForBufferDuration; 
    } 
    res = mOutputBufferReturnedSignal.waitRelative(mLock, waitBufferTimeout); 
    nsecs_t waitEnd = systemTime(SYSTEM_TIME_MONOTONIC);
    mBufferLimitLatency.add(waitStart, waitEnd); 
    ... 
}

mRequestLatency:request执行的时延,40ms

///frameworks/av/services/camera/libcameraservice/device3/Camera3Device.h
//记录request的时延,默认一帧request时长40ms 
static const int32_t kRequestLatencyBinSize = 40; // in ms 
CameraLatencyHistogram mRequestLatency; 
bool Camera3Device::RequestThread::threadLoop() { 
    ... 
    bool submitRequestSuccess = false; 
    nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC); 
    submitRequestSuccess = sendRequestsBatch(); 
    nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
    mRequestLatency.add(tRequestStart, tRequestEnd); 
    ... 
}

具体使用

ADBlog搜索关键字:CameraLatencyHistogram 由此可见,采样41个request,40ms内执行成功的有95.12%;采样36个dequeue buffer,全部都在5ms内执行成功。

该模块主要用于查看framework的一些耗时流程的时延直方图分布,check性能时可以进行参考