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