/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "BenchmarkMsgQ.h" #include <iostream> #include <thread> #include <fmq/MessageQueue.h> namespace android { namespace hardware { namespace tests { namespace msgq { namespace V1_0 { namespace implementation { // Methods from ::android::hardware::tests::msgq::V1_0::IBenchmarkMsgQ follow. Return<void> BenchmarkMsgQ::configureClientInboxSyncReadWrite( configureClientInboxSyncReadWrite_cb _hidl_cb) { static constexpr size_t kNumElementsInQueue = 16 * 1024; mFmqOutbox = new (std::nothrow) android::hardware::MessageQueue<uint8_t, kSynchronizedReadWrite>(kNumElementsInQueue); if (mFmqOutbox == nullptr) { _hidl_cb(false /* ret */, android::hardware::MQDescriptorSync<uint8_t>( std::vector<android::hardware::GrantorDescriptor>(), nullptr /* nhandle */, 0 /* size */)); } else { _hidl_cb(true /* ret */, *mFmqOutbox->getDesc()); } return Void(); } Return<void> BenchmarkMsgQ::configureClientOutboxSyncReadWrite( configureClientOutboxSyncReadWrite_cb _hidl_cb) { static constexpr size_t kNumElementsInQueue = 16 * 1024; mFmqInbox = new (std::nothrow) android::hardware::MessageQueue<uint8_t, kSynchronizedReadWrite>(kNumElementsInQueue); if ((mFmqInbox == nullptr) || (mFmqInbox->isValid() == false)) { _hidl_cb(false /* ret */, android::hardware::MQDescriptorSync<uint8_t>( std::vector<android::hardware::GrantorDescriptor>(), nullptr /* nhandle */, 0 /* size */)); } else { _hidl_cb(true /* ret */, *mFmqInbox->getDesc()); } return Void(); } Return<bool> BenchmarkMsgQ::requestWrite(int32_t count) { uint8_t* data = new (std::nothrow) uint8_t[count]; for (int i = 0; i < count; i++) { data[i] = i; } bool result = mFmqOutbox->write(data, count); delete[] data; return result; } Return<bool> BenchmarkMsgQ::requestRead(int32_t count) { uint8_t* data = new (std::nothrow) uint8_t[count]; bool result = mFmqInbox->read(data, count); delete[] data; return result; } Return<void> BenchmarkMsgQ::benchmarkPingPong(uint32_t numIter) { std::thread(QueuePairReadWrite<kSynchronizedReadWrite>, mFmqInbox, mFmqOutbox, numIter) .detach(); return Void(); } Return<void> BenchmarkMsgQ::benchmarkServiceWriteClientRead(uint32_t numIter) { if (mTimeData) delete[] mTimeData; mTimeData = new (std::nothrow) int64_t[numIter]; std::thread(QueueWriter<kSynchronizedReadWrite>, mFmqOutbox, mTimeData, numIter).detach(); return Void(); } Return<void> BenchmarkMsgQ::sendTimeData(const hidl_vec<int64_t>& clientRcvTimeArray) { int64_t accumulatedTime = 0; for (uint32_t i = 0; i < clientRcvTimeArray.size(); i++) { std::chrono::time_point<std::chrono::high_resolution_clock> clientRcvTime((std::chrono::high_resolution_clock::duration( clientRcvTimeArray[i]))); std::chrono::time_point<std::chrono::high_resolution_clock>serverSendTime( (std::chrono::high_resolution_clock::duration(mTimeData[i]))); accumulatedTime += static_cast<int64_t>( std::chrono::duration_cast<std::chrono::nanoseconds>(clientRcvTime - serverSendTime).count()); } accumulatedTime /= clientRcvTimeArray.size(); std::cout << "Average service to client write to read delay::" << accumulatedTime << "ns" << std::endl; return Void(); } template <MQFlavor flavor> void BenchmarkMsgQ::QueueWriter(android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox, int64_t* mTimeData, uint32_t numIter) { uint8_t data[kPacketSize64]; uint32_t numWrites = 0; while (numWrites < numIter) { do { mTimeData[numWrites] = std::chrono::high_resolution_clock::now().time_since_epoch().count(); } while (mFmqOutbox->write(data, kPacketSize64) == false); numWrites++; } } template <MQFlavor flavor> void BenchmarkMsgQ::QueuePairReadWrite( android::hardware::MessageQueue<uint8_t, flavor>* mFmqInbox, android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox, uint32_t numIter) { uint8_t data[kPacketSize64]; uint32_t numRoundTrips = 0; while (numRoundTrips < numIter) { while (mFmqInbox->read(data, kPacketSize64) == false) ; while (mFmqOutbox->write(data, kPacketSize64) == false) ; numRoundTrips++; } } IBenchmarkMsgQ* HIDL_FETCH_IBenchmarkMsgQ(const char* /* name */) { return new BenchmarkMsgQ(); } } // namespace implementation } // namespace V1_0 } // namespace msgq } // namespace tests } // namespace hardware } // namespace android