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 beberapa blok memori untuk berbagi tumpukan memori tunggal.
Peningkatan kinerja
Menggunakan MemoryBlock dalam aplikasi dapat secara signifikan mengurangi jumlah kesalahan segmentasi mmap
/ munmap
dan ruang pengguna, sehingga meningkatkan kinerja. Sebagai contoh:
- Menggunakan per
hidl_memory
untuk setiap alokasi buffer rata-rata 238 us/1 alokasi. - 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 tumpukan memori tunggal:
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",
...
};
Menerapkan 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 menggunakan
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); ...
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
yang dibagikan yaitummap()
-ed pertama kali salah satuMemoryBlock
s dipetakan danmunmap()
-ed ketika tidak ada yang merujuk padanya. Agarhidl_memory
selalu dipetakan, Anda dapat menggunakanlockMemory
, objek gaya RAII yang membuathidl_memory
yang sesuai dipetakan sepanjang siklus hidup kunci. Contoh:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Penggunaan yang diperpanjang
Bagian ini memberikan detail tentang penggunaan MemoryBlock
yang diperpanjang.
Menggunakan jumlah referensi untuk mengelola Memoryblock
Dalam kebanyakan situasi, cara paling efisien untuk menggunakan MemoryBlock adalah dengan mengalokasikan/mengalokasikan secara eksplisit. Namun, dalam aplikasi yang rumit menggunakan jumlah referensi untuk pengumpulan sampah mungkin merupakan ide yang lebih baik. Untuk memiliki jumlah referensi di MemoryBlock, Anda dapat mengikat MemoryBlock dengan objek pengikat, yang membantu menghitung referensi dan membatalkan alokasi MemoryBlock saat hitungan menurun ke 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 mengganti MemoryBlock
dan hapus metode untuk mengembalikan MemoryBlock
. Itu akan dibatalkan alokasinya dengan penghitungan referensi dengan MemoryBlockAllocation
. Contoh:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
Menerapkan HAL
Contoh penerapan HAL sisi pelayanan:
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 sisi klien dari HAL:
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 jauh lebih jarang daripada blok, lebih efisien untuk melewatkan metadata secara pasif dengan sebuah 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(...);