HIDL MemoryBlock
, hidl_memory
, HIDL
@1.0::IAllocator
ve HIDL @1.0::IMapper
üzerine inşa edilmiş soyut bir katmandır. Tek bir bellek yığınını paylaşmak üzere birden fazla bellek bloğuna sahip HIDL hizmetleri için tasarlanmıştır.
Performans iyileştirmeleri
Uygulamalarda MemoryBlock
kullanmak, mmap
/munmap
ve kullanıcı alanı segmentasyon hatalarının sayısını önemli ölçüde azaltarak performansı artırabilir.
Örnek:
- Her arabelleği ayırma için
hidl_memory
başına kullanım, 1 ayırma başına ortalama 238 us'dir. MemoryBlock
kullanarak ve tek birhidl_memory
paylaşarak 1 tahsisat için ortalama 2,82 ABD doları ödersiniz.
Mimari
HIDL MemoryBlock
mimarisi, tek bir bellek yığınını paylaşan birden fazla bellek bloğu içeren HIDL hizmetlerini içerir:
Şekil 1. HIDL MemoryBlock mimarisi
Normal kullanım
Bu bölümde, önce HAL'i açıklayarak, ardından HAL'i uygulayarak MemoryBlock
kullanma örneği verilmiştir.
HAL'i beyan etme
Aşağıdaki örnekte IFoo HAL:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
Android.bp
aşağıdaki gibidir:
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
HAL'i uygulama
Örnek HAL'i uygulamak için:
hidl_memory
değerini alın (ayrıntılar için HIDL C++ bölümüne bakın).#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 }));
Satın alınan
hidl_memory
ile birHidlMemoryDealer
örneği oluşturun:#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);
HIDL ile tanımlanan bir yapı olan
MemoryBlock
'ü ayırın.Örnek
MemoryBlock
:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };
MemoryBlock
ayırmak içinMemoryDealer
öğesinin kullanıldığı örnek:#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
için bayilik yap:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
Verileri işleme:
#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()));
Android.bp
yapılandırması:shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
lockMemory
yapmanız gerekip gerekmediğini belirlemek için akışı inceleyin.Normalde
MemoryBlock
, kilit yaşam döngüsü boyunca eşlenenMemoryBlock instances is mapped and is
munmap()-ed when nothing refers to it. To keep
hidl_memoryalways mapped, you can use
lockMemory, a RAII style object that keeps the corresponding
hidl_memory` öğelerinden biri ilk kezmmap()
edildiğinde paylaşılanhidl_memory
'ı korumak için referans sayısını kullanır. Örnek:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Genişletilmiş kullanım
Bu bölümde, MemoryBlock
ürününün genişletilmiş kullanımıyla ilgili ayrıntılar yer almaktadır.
MemoryBlock'u yönetmek için referans sayısını kullanma
Çoğu durumda, MemoryBlock
'ü kullanmanın en verimli yolu açıkça ayırmaktır/ayrılmamış duruma getirmektir. Ancak karmaşık uygulamalarda, referans sayısını kullanarak çöp toplama işlemini gerçekleştirmek daha iyi bir fikir olabilir. MemoryBlock
'te referans sayısının olması için MemoryBlock
'yi bir bağlayıcı nesneyle bağlayabilirsiniz. Bu, referansları saymanıza ve sayı sıfıra düştüğünde MemoryBlock
'nin ayrılmasına yardımcı olur.
HAL'i beyan etme
HAL'i tanımlarken bir MemoryBlock
örneği ve IBase içeren bir HIDL yapısı tanımlayın:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
MemoryBlock
yerine MemoryBlockAllocation
kullanın ve MemoryBlock
tutarını geri vermek için yöntemi kaldırın. MemoryBlockAllocation
ile referans sayımı yapılarak ayrılır. Örnek:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
HAL'i uygulama
HAL'in hizmet tarafı uygulaması örneği:
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);
HAL'in istemci tarafı uygulama örneği:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
Meta veri ekleme ve alma
Bazı uygulamaların, ayrılan MemoryBlock
ile bağlanmak için ek verilere ihtiyacı vardır.
Meta verileri iki yöntemle ekleyebilir ve alabilirsiniz:
Uygulama, meta verilere blokun kendisi kadar sık erişiyorsa meta verileri ekleyin ve tümünü bir yapı içinde iletin. Örnek:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };
Uygulama, meta verilere bloktan çok daha az sıklıkta erişiyorsa meta verileri bir arayüzle pasif olarak iletmek daha verimlidir. Örnek:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };
Ardından,
MemoryDealer
kullanarak meta verileriMemoryBlock
ile bağlayın. Örnek:MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);