एचआईडीएल मेमोरीब्लॉक

HIDL MemoryBlock, hidl_memory, HIDL @1.0::IAllocator, और HIDL @1.0::IMapper पर बनी एक ऐब्स्ट्रैक्ट लेयर है. इसे उन HIDL सेवाओं के लिए डिज़ाइन किया गया है जिनमें एक ही मेमोरी हीप शेयर करने के लिए कई मेमोरी ब्लॉक होते हैं.

परफ़ॉर्मेंस में सुधार किए गए

ऐप्लिकेशन में MemoryBlock का इस्तेमाल करने से, mmap/munmap की संख्या और उपयोगकर्ता के स्पेस को अलग-अलग सेगमेंट में बांटने की गड़बड़ियों को काफ़ी कम किया जा सकता है. इससे परफ़ॉर्मेंस बेहतर होती है. उदाहरण के लिए:

  • हर बफ़र ऐलोकेशन के लिए, हर hidl_memory का इस्तेमाल करने पर औसतन 238 us/1 ऐलोकेशन होती है.
  • MemoryBlock का इस्तेमाल करके और एक hidl_memory शेयर करने पर, औसतन 2.82 डॉलर/1 ऐलोकेशन मिलता है.

भवन निर्माण

HIDL MemoryBlock आर्किटेक्चर में ऐसी HIDL सेवाएं शामिल हैं जिनमें एक से ज़्यादा मेमोरी ब्लॉक को एक ही मेमोरी हीप शेयर किया जाता है:

HIDL MemoryBlock

पहली इमेज. HIDL MemoryBlock आर्किटेक्चर

सामान्य इस्तेमाल

इस सेक्शन में, पहले एचएएल का एलान करके और फिर एचएएल को लागू करके, MemoryBlock का इस्तेमाल करने का उदाहरण दिया गया है.

एचएएल का एलान करना

नीचे दिए गए उदाहरण के लिए 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 लागू करना

एचएएल के उदाहरण को लागू करने के लिए:

  1. hidl_memory पाएं (ज़्यादा जानकारी के लिए, 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
      }));
    
  2. हासिल किए गए hidl_memory के साथ HidlMemoryDealer इंस्टेंस बनाएं:

    #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 को असाइन करें, जो HIDL के साथ तय किया गया स्ट्रक्चर है.

    उदाहरण के लिए, MemoryBlock:

    struct MemoryBlock {
    IMemoryToken token;
    uint64_t size;
    uint64_t offset;
    };
    

    MemoryBlock देने के लिए, MemoryDealer का इस्तेमाल करने का उदाहरण:

    #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. MemoryBlock को अनलिंक करें:

    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. Config Android.bp:

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. फ़्लो की समीक्षा करके, यह तय करें कि आपको lockMemory करने की ज़रूरत है या नहीं.

    आम तौर पर, MemoryBlock शेयर किए गए hidl_memory को मैनेज करने के लिए, रेफ़रंस की गिनती का इस्तेमाल करता है. hidl_memory को पहली बार mmap() तब MemoryBlock instances is mapped and ismunmap()-ed when nothing refers to it. To keephidl_memoryalways mapped, you can uselockMemory, a RAII style object that keeps the correspondinghidl_memory` के ज़रिए मैप किया जाता है, जब वह लॉक के पूरे लाइफ़साइकल के दौरान मैप किया जाता है. उदाहरण:

    #include <hidlmemory/mapping.h>
    
    sp<RefBase> lockMemory(const sp<IMemoryToken> key);
    

ज़्यादा समय तक इस्तेमाल करना

इस सेक्शन में, MemoryBlock के ज़्यादा इस्तेमाल के बारे में जानकारी दी गई है.

MemoryBlock को मैनेज करने के लिए, रेफ़रंस की संख्या का इस्तेमाल करना

ज़्यादातर मामलों में, MemoryBlock का इस्तेमाल करने का सबसे असरदार तरीका यह है कि उसे साफ़ तौर पर ऐलोकेट/डिऐलोकेट किया जाए. हालांकि, जटिल ऐप्लिकेशन में, ग़ैर-ज़रूरी डेटा हटाने के लिए रेफ़रंस की संख्या का इस्तेमाल करना बेहतर हो सकता है. MemoryBlock पर रेफ़रंस की गिनती करने के लिए, MemoryBlock को बाइंडर ऑब्जेक्ट से बंधा जा सकता है. इससे रेफ़रंस की गिनती करने में मदद मिलती है. साथ ही, गिनती शून्य होने पर MemoryBlock को डिएलोकेट किया जा सकता है.

एचएएल का एलान करना

एचएएल का एलान करते समय, उस HIDL निर्देश के बारे में बताएं जिसमें एक MemoryBlock इंस्टेंस और एक IBase हो:

import android.hidl.memory.block@1.0::MemoryBlock;

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

MemoryBlock को बदलने के लिए MemoryBlockAllocation का इस्तेमाल करें और MemoryBlock वापस देने का तरीका हटाएं. इसे MemoryBlockAllocation की मदद से, रेफ़रंस काउंटिंग की मदद से डिएलोकेट किया जाता है. उदाहरण:

interface IFoo {
    allocateSome() generates(MemoryBlockAllocation allocation);
};

HAL लागू करना

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);

एचएएल को क्लाइंट-साइड पर लागू करने का उदाहरण:

ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
    ...
);

मेटाडेटा अटैच करना और उसे वापस लाना

कुछ ऐप्लिकेशन को, ऐलोकेट किए गए MemoryBlock से बाइंड करने के लिए ज़्यादा डेटा की ज़रूरत होती है. मेटाडेटा जोड़ने और वापस पाने के लिए, इन दो तरीकों का इस्तेमाल किया जा सकता है:

  • अगर ऐप्लिकेशन, ब्लॉक के जितनी बार ऐक्सेस करता है उतनी ही बार मेटाडेटा को ऐक्सेस करता है, तो मेटाडेटा को जोड़ें और सभी को स्ट्रक्चर में पास करें. उदाहरण:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • अगर ऐप्लिकेशन, ब्लॉक की तुलना में मेटाडेटा को बहुत कम बार ऐक्सेस करता है, तो इंटरफ़ेस की मदद से मेटाडेटा को पैसिव तरीके से पास करना ज़्यादा असरदार होता है. उदाहरण:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        IMetaData metaData;
    };
    

    इसके बाद, MemoryDealer का इस्तेमाल करके मेटाडेटा को MemoryBlock से बांधें. उदाहरण:

    MemoryBlockWithMetaData memory_block;
    memory_block.block = dealer->allocate(size);
    if(HidlMemoryDealer::isOk(block)){
        memory_block.metaData = new MetaData(...);