Home | History | Annotate | Download | only in default
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "BenchmarkMsgQ.h"
     18 #include <iostream>
     19 #include <thread>
     20 #include <fmq/MessageQueue.h>
     21 
     22 namespace android {
     23 namespace hardware {
     24 namespace tests {
     25 namespace msgq {
     26 namespace V1_0 {
     27 namespace implementation {
     28 
     29 // Methods from ::android::hardware::tests::msgq::V1_0::IBenchmarkMsgQ follow.
     30 Return<void> BenchmarkMsgQ::configureClientInboxSyncReadWrite(
     31         configureClientInboxSyncReadWrite_cb _hidl_cb) {
     32     static constexpr size_t kNumElementsInQueue = 16 * 1024;
     33     mFmqOutbox = new (std::nothrow) android::hardware::MessageQueue<uint8_t,
     34                kSynchronizedReadWrite>(kNumElementsInQueue);
     35     if (mFmqOutbox == nullptr) {
     36         _hidl_cb(false /* ret */, android::hardware::MQDescriptorSync<uint8_t>(
     37                 std::vector<android::hardware::GrantorDescriptor>(),
     38                 nullptr /* nhandle */, 0 /* size */));
     39     } else {
     40         _hidl_cb(true /* ret */, *mFmqOutbox->getDesc());
     41     }
     42 
     43     return Void();
     44 }
     45 
     46 Return<void> BenchmarkMsgQ::configureClientOutboxSyncReadWrite(
     47         configureClientOutboxSyncReadWrite_cb _hidl_cb) {
     48     static constexpr size_t kNumElementsInQueue = 16 * 1024;
     49     mFmqInbox = new (std::nothrow) android::hardware::MessageQueue<uint8_t,
     50               kSynchronizedReadWrite>(kNumElementsInQueue);
     51     if ((mFmqInbox == nullptr) || (mFmqInbox->isValid() == false)) {
     52         _hidl_cb(false /* ret */, android::hardware::MQDescriptorSync<uint8_t>(
     53                 std::vector<android::hardware::GrantorDescriptor>(),
     54                 nullptr /* nhandle */, 0 /* size */));
     55     } else {
     56         _hidl_cb(true /* ret */, *mFmqInbox->getDesc());
     57     }
     58 
     59     return Void();
     60 }
     61 
     62 Return<bool> BenchmarkMsgQ::requestWrite(int32_t count) {
     63     uint8_t* data = new (std::nothrow) uint8_t[count];
     64     for (int i = 0; i < count; i++) {
     65         data[i] = i;
     66     }
     67     bool result = mFmqOutbox->write(data, count);
     68     delete[] data;
     69     return result;
     70 }
     71 
     72 Return<bool> BenchmarkMsgQ::requestRead(int32_t count) {
     73     uint8_t* data = new (std::nothrow) uint8_t[count];
     74     bool result = mFmqInbox->read(data, count);
     75     delete[] data;
     76     return result;
     77 }
     78 
     79 Return<void> BenchmarkMsgQ::benchmarkPingPong(uint32_t numIter) {
     80     std::thread(QueuePairReadWrite<kSynchronizedReadWrite>, mFmqInbox,
     81                 mFmqOutbox, numIter)
     82             .detach();
     83     return Void();
     84 }
     85 
     86 Return<void> BenchmarkMsgQ::benchmarkServiceWriteClientRead(uint32_t numIter) {
     87     if (mTimeData) delete[] mTimeData;
     88     mTimeData = new (std::nothrow) int64_t[numIter];
     89     std::thread(QueueWriter<kSynchronizedReadWrite>, mFmqOutbox,
     90                 mTimeData, numIter).detach();
     91     return Void();
     92 }
     93 
     94 Return<void> BenchmarkMsgQ::sendTimeData(const hidl_vec<int64_t>& clientRcvTimeArray) {
     95     int64_t accumulatedTime = 0;
     96 
     97     for (uint32_t i = 0; i < clientRcvTimeArray.size(); i++) {
     98         std::chrono::time_point<std::chrono::high_resolution_clock>
     99                 clientRcvTime((std::chrono::high_resolution_clock::duration(
    100                         clientRcvTimeArray[i])));
    101         std::chrono::time_point<std::chrono::high_resolution_clock>serverSendTime(
    102                 (std::chrono::high_resolution_clock::duration(mTimeData[i])));
    103         accumulatedTime += static_cast<int64_t>(
    104                 std::chrono::duration_cast<std::chrono::nanoseconds>(clientRcvTime -
    105                                                                      serverSendTime).count());
    106     }
    107 
    108     accumulatedTime /= clientRcvTimeArray.size();
    109     std::cout << "Average service to client write to read delay::"
    110          << accumulatedTime << "ns" << std::endl;
    111     return Void();
    112 }
    113 
    114 template <MQFlavor flavor>
    115 void BenchmarkMsgQ::QueueWriter(android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox,
    116                                 int64_t* mTimeData,
    117                                 uint32_t numIter) {
    118     uint8_t data[kPacketSize64];
    119     uint32_t numWrites = 0;
    120 
    121     while (numWrites < numIter) {
    122         do {
    123             mTimeData[numWrites] =
    124                     std::chrono::high_resolution_clock::now().time_since_epoch().count();
    125         } while (mFmqOutbox->write(data, kPacketSize64) == false);
    126         numWrites++;
    127     }
    128 }
    129 
    130 template <MQFlavor flavor>
    131 void BenchmarkMsgQ::QueuePairReadWrite(
    132         android::hardware::MessageQueue<uint8_t, flavor>* mFmqInbox,
    133         android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox,
    134         uint32_t numIter) {
    135     uint8_t data[kPacketSize64];
    136     uint32_t numRoundTrips = 0;
    137 
    138     while (numRoundTrips < numIter) {
    139         while (mFmqInbox->read(data, kPacketSize64) == false)
    140             ;
    141         while (mFmqOutbox->write(data, kPacketSize64) == false)
    142             ;
    143         numRoundTrips++;
    144     }
    145 }
    146 
    147 IBenchmarkMsgQ* HIDL_FETCH_IBenchmarkMsgQ(const char* /* name */) {
    148     return new BenchmarkMsgQ();
    149 }
    150 
    151 }  // namespace implementation
    152 }  // namespace V1_0
    153 }  // namespace msgq
    154 }  // namespace tests
    155 }  // namespace hardware
    156 }  // namespace android
    157