HIDL MemoryBlock là một lớp trừu tượng được xây dựng trên hidl_memory
, HIDL @1.0::IAllocator
và HIDL @1.0::IMapper
. Nó được thiết kế cho các dịch vụ HIDL có nhiều khối bộ nhớ để chia sẻ một đống bộ nhớ.
Cải tiến hiệu suất
Sử dụng MemoryBlock trong các ứng dụng có thể giảm đáng kể số lượng lỗi mmap
/ munmap
và phân đoạn không gian người dùng, do đó cải thiện hiệu suất. Ví dụ:
- Sử dụng mỗi
hidl_memory
cho mỗi lần phân bổ bộ đệm trung bình là 238 us/1 lần phân bổ. - Sử dụng
MemoryBlock
và chia sẻ mộthidl_memory
trung bình phân bổ 2,82 us/1.
Ngành kiến trúc
Kiến trúc HIDL MemoryBlock bao gồm các dịch vụ HIDL với nhiều khối bộ nhớ chia sẻ một đống bộ nhớ duy nhất:
Hình 1. Kiến trúc HIDL MemoryBlock
Sử dụng bình thường
Phần này cung cấp ví dụ về cách sử dụng MemoryBlock bằng cách khai báo HAL trước tiên sau đó triển khai HAL.
Khai báo HAL
Đối với ví dụ sau IFoo HAL:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
Android.bp
như sau:
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
Thực hiện HAL
Để triển khai ví dụ HAL:
Lấy
hidl_memory
(để biết chi tiết, hãy tham khảo HIDL C++ ).#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 }));
Tạo
HidlMemoryDealer
vớihidl_memory
có được:#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);
Phân bổ
MemoryBlock
, là một cấu trúc được xác định bằng HIDL.Ví dụ
MemoryBlock
:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };
Ví dụ sử dụng
MemoryDealer
để phân bổMemoryBlock
:#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); ...
Phân bổ
MemoryBlock
:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
Thao tác dữ liệu:
#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()));
Cấu hình
Android.bp
:shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
Xem lại quy trình để xác định xem bạn có cần
lockMemory
hay không.Thông thường, MemoryBlock sử dụng số tham chiếu để duy trì
hidl_memory
được chia sẻ, đó làmmap()
-ed trong lần đầu tiên một trongMemoryBlock
s của nó được ánh xạ và làmunmap()
-ed khi không có gì đề cập đến nó. Để giữ chohidl_memory
luôn được ánh xạ, bạn có thể sử dụnglockMemory
, một đối tượng kiểu RAII giữ chohidl_memory
tương ứng được ánh xạ trong suốt vòng đời khóa. Ví dụ:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Sử dụng mở rộng
Phần này cung cấp thông tin chi tiết về việc sử dụng mở rộng MemoryBlock
.
Sử dụng số tham chiếu để quản lý Memoryblock
Trong hầu hết các trường hợp, cách hiệu quả nhất để sử dụng MemoryBlock là phân bổ/giải phóng rõ ràng. Tuy nhiên, trong các ứng dụng phức tạp sử dụng số tham chiếu để thu gom rác có thể là một ý tưởng tốt hơn. Để có số lượng tham chiếu trên MemoryBlock, bạn có thể liên kết MemoryBlock với một đối tượng liên kết, giúp đếm các tham chiếu và phân bổ MemoryBlock khi số lượng giảm xuống 0.
Khai báo HAL
Khi khai báo HAL, hãy mô tả cấu trúc HIDL chứa MemoryBlock và IBase:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
Sử dụng MemoryBlockAllocation
để thay thế MemoryBlock
và xóa phương thức trả lại MemoryBlock
. Nó sẽ được giải phóng bằng cách đếm tham chiếu với MemoryBlockAllocation
. Ví dụ:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
Thực hiện HAL
Ví dụ về việc triển khai HAL phía dịch vụ:
class MemoryBlockRefCnt: public virtual IBase {
MemoryBlockRefCnt(uint64_t offset, sp<MemoryDealer> dealer)
: mOffset(offset), mDealer(dealer) {}
~MemoryBlockRefCnt() {
mDealer->deallocate(mOffset);
}
private:
uint64_t mOffset;
sp<MemoryDealer> mDealer;
};
Return<void> Foo::allocateSome(allocateSome_cb _hidl_cb) {
MemoryBlockAllocation allocation;
allocation.block = memory_dealer->allocate(1024);
if(HidlMemoryDealer::isOk(block)){
allocation.refcnt= new MemoryBlockRefCnt(...);
_hidl_cb(allocation);
Ví dụ về việc triển khai HAL phía khách hàng:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
Đính kèm/truy xuất siêu dữ liệu
Một số ứng dụng cần dữ liệu bổ sung để liên kết với MemoryBlock
được phân bổ. Bạn có thể thêm/truy xuất siêu dữ liệu bằng hai phương pháp:
Nếu ứng dụng truy cập siêu dữ liệu thường xuyên như chính khối đó, hãy nối thêm siêu dữ liệu và chuyển tất cả chúng vào một cấu trúc. Ví dụ:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };
Nếu ứng dụng truy cập siêu dữ liệu ít thường xuyên hơn khối thì việc truyền siêu dữ liệu một cách thụ động bằng giao diện sẽ hiệu quả hơn. Ví dụ:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };
Tiếp theo, liên kết siêu dữ liệu với MemoryBlock bằng Memory Dealer. Ví dụ:
MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);