hidl 性能设计

2020-08-10  本文已影响0人  xuefeng_apple

1-使用binder 架构存在的问题
如果设计的系统是对时间要求比较苛刻,那么采用HIDL 就要考虑性能
从framework 与hal 在同一个进程,演进到framework 与hal 在不同进程,那么肯定存在性能的损耗。

图片.png 图片.png

对[1][2][3]进行测试性能
类服务器端的底层写函数:

#define LOG_TAG     "Sample#Lib"
#include <log/log.h>
#include <string.h>
#include "sample.h"
int writeMessage(uint8_t *data, int32_t size)
{
    int i;
    uint8_t tmp = 0;
    for(i = 0; i < size; i++) {
        tmp += data[i];
        tmp &= 0xff;
    }
    return tmp;
}

直接调用:

void test_function_call(void)
{
    android::StopWatch stopWatch("test_function_call");
    writeMessage(buffer, BUFFER_SIZE);
}

HIDL接口:

void test_hidl_interface(void)
{
    SampleMessage message;
    message.size = BUFFER_SIZE;
    message.data.resize(BUFFER_SIZE);
    ::memcpy(&message.data[0], buffer, BUFFER_SIZE);
    android::StopWatch stopWatch("test_hidl_interface");
    benchmark->writeMessage(message);
}

Oneyway HIDL接口:

void test_oneway_hidl_interface(void)
{
    SampleMessage message;
    message.size = BUFFER_SIZE;
    message.data.resize(BUFFER_SIZE);
    ::memcpy(&message.data[0], buffer, BUFFER_SIZE);
    android::StopWatch stopWatch("test_oneway_hidl_interface");
    benchmark->writeMessageOneway(message);
}

StopWatch: StopWatch test_function_call (us): 1
StopWatch: StopWatch test_hidl_interface (us): 325
StopWatch: StopWatch test_oneway_hidl_interface (us): 98
可以看出passthrough 是性能最好的,google 采用了binder ,舍弃了性能最优,获得了与vendor 的隔离。

2-对binder HIDL 进行改进-共享内存
共享内存
研究hidl ,必须要研究共享内存的方式, 因为这个太重要,camera HIDL 涉及到的就是采用了这种方式
不同的进程进行大量数据传输的时候,共享内存,零拷贝,这样是最经济的
Memory:

HIDL memory 类型会映射到 libhidlbase 中的 hidl_memory 类,该类表示未映射的共享内存。这是要在 HIDL 中共享内存而必须在进程之间传递的对象。要使用共享内存,需满足以下条件:

#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hardware::hidl_memory;
....
  sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
  ashmemAllocator->allocate(2048, [&](bool success, const hidl_memory& mem) {
        if (!success) { /* error */ }
        // now you can use the hidl_memory object 'mem' or pass it around
  }));

对内存的实际更改必须通过 IMemory 对象完成(在创建 mem 的一端或在通过 HIDL RPC 接收更改的一端完成):

// Same includes as above
sp<IMemory> memory = mapMemory(mem);
void* data = memory->getPointer();
memory->update();
// update memory however you wish after calling update and before calling commit
data[0] = 42;
memory->commit();
// …
memory->update(); // the same memory can be updated multiple times
// …
memory->commit();

上面对memory 使用有了基本的了解,下面进行详细的介绍
HIDL memory 梳理:
HIDL 内存块是一个建立在HIDL @1.0::IAllocator, 和 HIDL @1.0::IMapper的抽象层。
它是为具有多个内存块共享单个内存堆的HIDL Severis而设计的。


图片.png

使用实例
声明HAL
IFoo HAL:

import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
    getSome() generates(MemoryBlock block);
    giveBack(MemoryBlock block);
};

Android.bp:

hidl_interface {
    ...
    srcs: [
        "IFoo.hal",
    ],
    interfaces: [
        "android.hidl.memory.block@1.0",
        ...
};

再HAL service 端的实现:
1.获取 hidl_memory

#include <android/hidl/allocator/1.0/IAllocator.h>
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hardware::hidl_memory;
...
  sp<IAllocator> allocator = IAllocator::getService("ashmem");
  allocator->allocate(2048, [&](bool success, const hidl_memory& mem)
  {
        if (!success) { /* error */ }
        // you can now use the hidl_memory object 'mem' or pass it
  }));

2.创建一个HidlMemoryDealer来获取hidl_memory:

#include <hidlmemory/HidlMemoryDealer.h>
using ::android::hardware::HidlMemoryDealer
/* The mem argument is acquired in the Step1, returned by the ashmemAllocator->allocate */
sp<HidlMemoryDealer> memory_dealer = HidlMemoryDealer::getInstance(mem);

3.使用MemoryBlock申请内存

struct MemoryBlock {
IMemoryToken token;
uint64_t size;
uint64_t offset;
};
//==========================================
#include <android/hidl/memory/block/1.0/types.h>
using ::android::hidl::memory::block::V1_0::MemoryBlock;
Return<void> Foo::getSome(getSome_cb _hidl_cb) {
    MemoryBlock block = memory_dealer->allocate(1024);
    if(HidlMemoryDealer::isOk(block)){
        _hidl_cb(block);
    ...

4 解除分配:

Return<void> Foo::giveBack(const MemoryBlock& block) {
    memory_dealer->deallocate(block.offset);

5.使用数据

#include <hidlmemory/mapping.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hidl::memory::V1_0::IMemory;
sp<IMemory> memory = mapMemory(block);
uint8_t* data =
static_cast<uint8_t*>(static_cast<void*>(memory->getPointer()));

6.配置 Android.bp

shared_libs: [
        "android.hidl.memory@1.0",
        "android.hidl.memory.block@1.0"
        "android.hidl.memory.token@1.0",
        "libhidlbase",
        "libhidlmemory",

3-对binder HIDL 进行改进-FMQ
FMQ 快速队列, FMQ 在实际的使用中并不多,主要的理念就是FMQ 在进程间传递,不经过kernel binder 节点,节省了开支,后面继续研究

REF:
https://www.jianshu.com/p/550040f8f7cb

上一篇 下一篇

猜你喜欢

热点阅读