美文网首页
hidl 性能设计

hidl 性能设计

作者: xuefeng_apple | 来源:发表于2020-08-10 20:05 被阅读0次

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

图片.png
  • 左边黄色的,是使用以前的HAL层架构,直接app进程直接function call调用hall层的函数,通过ioctl的system call把数据传送到kernel层。
  • 右边蓝色的,是使用HIDL来实现app调用底层I2C操作,分为两部分,app作为HIDL的client端通过binder进程间通信来调用server端的接口。
  • proxy client端进程间调用到server端的时间延迟,毕竟是进程间通信,肯定没有直接调用来的快。而且两个不同进程,就涉及到数据的拷贝,当i2c需要写入的数据很大而且调用次数很多的时候这个拷贝和传输的延迟就会显得比较突出了。
图片.png
  • [1]直接调用 passthrough
  • [2]binder HIDL接口传输 就是上图中的3
  • [3]Oneway HIDL interface, 这个可以理解不阻塞形式,也是对应上图中3其中的一种形式

对[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 中共享内存而必须在进程之间传递的对象。要使用共享内存,需满足以下条件:

  • 获取 IAllocator 的实例(当前只有“ashmem”实例可用)并使用该实例分配共享内存。
  • IAllocator::allocate() 返回 hidl_memory 对象,该对象可通过 HIDL RPC 传递,并能使用 libhidlmemory 的 mapMemory 函数映射到某个进程。
  • mapMemory 返回对可用于访问内存的 sp<IMemory> 对象的引用(IMemory 和 IAllocator 在 android.hidl.memory@1.0 中定义)。
    IAllocator 分配内存:
#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

相关文章

  • hidl 性能设计

    1-使用binder 架构存在的问题如果设计的系统是对时间要求比较苛刻,那么采用HIDL 就要考虑性能从frame...

  • Android HIDL学习(5) ---- 设计要素

    前面我们学习了如何使用HIDL来设计或者重构之前在HAL层的代码,而且也对比了一些高性能的编程方式,这里我们在来一...

  • HIDL实战笔记

    目录 第一篇:HIDL学习笔记之HIDL C++(第一天)第二篇:HIDL学习笔记之HIDL C++(第二天)第三...

  • CameraProvider启动流程分析

    CameraProvider进程中hidl文件 HIDL文件服务端客户端BinderNameICameraProv...

  • HIDL模型分析

    一 HIDL的结构体关系 以 Light的HIDL为例,class之间的关系如下 二 client端 sm 通过...

  • C++ struct和class区别

    一 struct继承 最近分析HIDL,在HIDL的生成中google使用了大量的struct继承,比如 首先看一...

  • 为iOS设计:图形和性能

    为iOS设计:图形和性能 为iOS设计:图形和性能

  • Android HIDL学习(1) ---- 简介

    HIDL HAL接口定义语言(简称HIDL)适用于指定HAL和其用户之间的接口的一种接口描述语言(IDL)。HID...

  • HIDL In Telephony

    前置文章 《HIDL》 前言 在 Android 8.0(不含,下同)之前,Telephony 和 modem 之...

  • hidl 编译

网友评论

      本文标题:hidl 性能设计

      本文链接:https://www.haomeiwen.com/subject/cgfsdktx.html