Android客户端性能工具3:GpuMemoryTracker分析

类的定义很简单,爆漏的接口也不是很多,只有7个并且都是static类型的,看来要打的不是一场硬仗

enum class GpuObjectType {
    Texture = 0,
    OffscreenBuffer,
    Layer,

    TypeCount,
};
class GpuMemoryTracker {
public:
    GpuObjectType objectType() { return mType; }
    int objectSize() { return mSize; }

    static void onGLContextCreated();
    static void onGLContextDestroyed();
    static void dump();
    static void dump(std::ostream& stream);
    static int getInstanceCount(GpuObjectType type);
    static int getTotalSize(GpuObjectType type);
    static void onFrameCompleted();

protected:
    GpuMemoryTracker(GpuObjectType type) : mType(type) {
        ASSERT_GPU_THREAD();
        startTrackingObject();
    }

    ~GpuMemoryTracker() {
        notifySizeChanged(0);
        stopTrackingObject();
    }

    void notifySizeChanged(int newSize);

private:
    void startTrackingObject();
    void stopTrackingObject();

    int mSize = 0;
    GpuObjectType mType;
};

hwui中有三个类派生自GpuMemoryTracker类.
1 Layer类用于TextureView进行opengl渲染
2 Texture 纹理
3 OffscreenBuffer 是用来替代前边layer
关于hwui可以参考http://blog.csdn.net/jinzhuojun/article/details/54234354这篇文章

初始化之后都调用startTrackingObject会开启内存追踪

void GpuMemoryTracker::startTrackingObject() {
    auto result = gObjectSet.insert(this);
    LOG_ALWAYS_FATAL_IF(!result.second,
            "startTrackingObject() on %p failed, already being tracked!", this);
    gObjectStats[static_cast<int>(mType)].count++;
}

startTrackingObject是私有函数,进来之后直接添加this指针到gObjectSet维护的集合中,之后有给对应的统计信息计数加1

void GpuMemoryTracker::onGLContextCreated() {
    LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a GL thread? "
            "current = %lu, gl thread = %lu", pthread_self(), gGpuThread);
    gGpuThread = pthread_self();
}

void GpuMemoryTracker::onGLContextDestroyed() {
    gGpuThread = 0;
    if (CC_UNLIKELY(gObjectSet.size() > 0)) {
        std::stringstream os;
        dump(os);
        ALOGE("%s", os.str().c_str());
        LOG_ALWAYS_FATAL("Leaked %zd GPU objects!", gObjectSet.size());
    }
}

onGLContextCreated()函数在render thread创建时候记录下render线程id,销毁的时候如果还有没释放的内存,可能是出现内存泄漏了,打印一下调用栈. 记录线程id是为了检验创建GpuMemoryTracker子类在render thread中.

struct TypeStats {
    int totalSize = 0;
    int count = 0;
};

void GpuMemoryTracker::notifySizeChanged(int newSize) {
    int delta = newSize - mSize;
    mSize = newSize;
    gObjectStats[static_cast<int>(mType)].totalSize += delta;
}

notifySizeChanged是统计gpu使用内存的关键函数,目前只有Texture实现了该函数,也就是目前只支持统计纹理数据的大小.将每一个类型的数据大小之和用gObjectStats保存.(gObjectStats中保存的元素都是TypeStats,所以既可以统计数量有可以统计内存占用)

还有个比较重要的函数就是在每帧绘制完成计算统计信息

void GpuMemoryTracker::onFrameCompleted() {
    if (ATRACE_ENABLED()) {
        char buf[128];
        for (int type = 0; type < NUM_TYPES; type++) {
            snprintf(buf, 128, "hwui_%s", TYPE_NAMES[type]);
            const TypeStats& stats = gObjectStats[type];
            ATRACE_INT(buf, stats.totalSize);
            snprintf(buf, 128, "hwui_%s_count", TYPE_NAMES[type]);
            ATRACE_INT(buf, stats.count);
        }
    }

    std::vector<const Texture*> freeList;
    for (const auto& obj : gObjectSet) {
        if (obj->objectType() == GpuObjectType::Texture) {
            const Texture* texture = static_cast<Texture*>(obj);
            if (texture->cleanup) {
                ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u",
                        texture->id(), texture->width(), texture->height());
                freeList.push_back(texture);
            }
        }
    }
    for (auto& texture : freeList) {
        const_cast<Texture*>(texture)->deleteTexture();
        delete texture;
    }
}

第一个for循环是给atrace的输出,输出每种类型的总大小和数量
第二个for循环就是清理那些无用的texture

最后最重要的函数就是给用户抓取信息的dump函数

void GpuMemoryTracker::dump(std::ostream& stream) {
    for (int type = 0; type < NUM_TYPES; type++) {
        const TypeStats& stats = gObjectStats[type];
        stream << TYPE_NAMES[type];
        stream << " is using " << SizePrinter{stats.totalSize};
        stream << ", count = " << stats.count;
        stream << std::endl;
    } }

也是打印类型和总大小
是不是很简单,GpuMemoryTracker只是用于调试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值