HIDL MemoryBlock adalah lapisan abstrak yang dibangun di atas hidl_memory
, HIDL @1.0::IAllocator
, dan HIDL @1.0::IMapper
. Ini dirancang untuk layanan HIDL yang memiliki banyak blok memori untuk berbagi satu tumpukan memori.
Peningkatan kinerja
Menggunakan MemoryBlock dalam aplikasi dapat secara signifikan mengurangi jumlah mmap
/ munmap
dan kesalahan segmentasi ruang pengguna, sehingga meningkatkan kinerja. Misalnya:
- Penggunaan per
hidl_memory
untuk setiap alokasi buffer rata-rata 238 alokasi us/1. - Menggunakan
MemoryBlock
dan berbagi satuhidl_memory
rata-rata alokasi 2,82 us/1.
Arsitektur
Arsitektur HIDL MemoryBlock mencakup layanan HIDL dengan beberapa blok memori yang berbagi satu tumpukan memori:
Gambar 1. Arsitektur HIDL MemoryBlock
Penggunaan normal
Bagian ini memberikan contoh penggunaan MemoryBlock dengan terlebih dahulu mendeklarasikan HAL kemudian mengimplementasikan HAL.
Mendeklarasikan HAL
Untuk contoh berikut IFoo HAL:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
Android.bp
adalah sebagai berikut:
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
Melaksanakan HAL
Untuk mengimplementasikan contoh HAL:
Dapatkan
hidl_memory
(untuk detailnya, lihat 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 }));
Buat
HidlMemoryDealer
denganhidl_memory
yang diperoleh:#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);
Alokasikan
MemoryBlock
, yang merupakan struct yang didefinisikan dengan HIDL.Contoh
MemoryBlock
:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };
Contoh penggunaan
MemoryDealer
untuk mengalokasikanMemoryBlock
:#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); ...
Batalkan alokasi
MemoryBlock
:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
Memanipulasi data:
#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()));
Konfigurasi
Android.bp
:shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
Tinjau alur untuk menentukan apakah Anda perlu
lockMemory
.Biasanya, MemoryBlock menggunakan jumlah referensi untuk mempertahankan
hidl_memory
bersama yangmmap()
-ed saat pertama kali salah satuMemoryBlock
-nya dipetakan danmunmap()
-ed ketika tidak ada yang merujuk ke sana. Agarhidl_memory
selalu dipetakan, Anda dapat menggunakanlockMemory
, objek gaya RAII yang menjagahidl_memory
terkait tetap dipetakan sepanjang siklus hidup kunci. Contoh:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Penggunaan yang diperluas
Bagian ini memberikan detail tentang perpanjangan penggunaan MemoryBlock
.
Menggunakan jumlah referensi untuk mengelola Memoryblock
Dalam kebanyakan situasi, cara paling efisien untuk menggunakan MemoryBlock adalah dengan mengalokasikan/membatalkan alokasi secara eksplisit. Namun, dalam aplikasi yang rumit, menggunakan jumlah referensi untuk pengumpulan sampah mungkin merupakan ide yang lebih baik. Untuk menghitung jumlah referensi di MemoryBlock, Anda dapat mengikat MemoryBlock dengan objek pengikat, yang membantu menghitung referensi dan membatalkan alokasi MemoryBlock ketika jumlah berkurang menjadi nol.
Mendeklarasikan HAL
Saat mendeklarasikan HAL, jelaskan struct HIDL yang berisi MemoryBlock dan IBase:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
Gunakan MemoryBlockAllocation
untuk menggantikan MemoryBlock
dan hapus metode untuk mengembalikan MemoryBlock
. Itu akan dibatalkan alokasinya dengan penghitungan referensi dengan MemoryBlockAllocation
. Contoh:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
Melaksanakan HAL
Contoh penerapan sisi layanan HAL:
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);
Contoh implementasi HAL di sisi klien:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
Melampirkan/mengambil metadata
Beberapa aplikasi memerlukan data tambahan untuk diikat dengan MemoryBlock
yang dialokasikan. Anda dapat menambahkan/mengambil metadata menggunakan dua metode:
Jika aplikasi mengakses metadata sesering blok itu sendiri, tambahkan metadata dan teruskan semuanya dalam sebuah struct. Contoh:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };
Jika aplikasi mengakses metadata lebih jarang dibandingkan blok, akan lebih efisien jika meneruskan metadata secara pasif dengan antarmuka. Contoh:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };
Selanjutnya, ikat metadata dengan MemoryBlock menggunakan Memory Dealer. Contoh:
MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);