| #pragma once |
| |
| #ifndef GEODE_INTEGRATION_TEST_FW_PERF_H_ |
| #define GEODE_INTEGRATION_TEST_FW_PERF_H_ |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /** |
| |
| fw_perf.hpp provides framework macros for measuring performance, |
| archiving the results, and comparing against previous archives. |
| |
| Steps for a performance suite: |
| |
| perf::PerfSuite suite( "SuiteName" ); |
| |
| const char* name = "my operation type/test description"; |
| perf::TimeStamp starttime; |
| ... perform n operations. |
| perf::TimeStamp stoptime; |
| suite.addRecord( name, opcount, starttime, stoptime ); |
| |
| suite.save( ); // will save current results to <suite>_results.<hostname> |
| suite.compare( ); // will compare against the file named |
| <suite>_baseline.<hostname> |
| |
| If no baseline file for the host is available, then an error will occur, |
| recommending |
| that the results be analyzed for acceptability, and checked in as the hosts |
| baseline. |
| |
| If a baseline is found, a comparison report is generated, if the deviation is |
| beyond |
| established limits, a TestException will be thrown. |
| |
| */ |
| |
| #include <string> |
| #include <map> |
| |
| #include <geode/DataOutput.hpp> |
| #include <geode/DataInput.hpp> |
| |
| #include <ace/Task.h> |
| #include <ace/Condition_T.h> |
| #include <ace/Thread_Mutex.h> |
| //#include "Name_Handler.h" |
| |
| namespace perf { |
| |
| class Semaphore { |
| private: |
| ACE_Thread_Mutex m_mutex; |
| ACE_Condition<ACE_Thread_Mutex> m_cond; |
| volatile int m_count; |
| |
| public: |
| explicit Semaphore(int count); |
| ~Semaphore(); |
| void acquire(int t = 1); |
| void release(int t = 1); |
| |
| private: |
| Semaphore(); |
| Semaphore(const Semaphore& other); |
| Semaphore& operator=(const Semaphore& other); |
| }; |
| |
| class TimeStamp { |
| private: |
| int64_t m_msec; |
| |
| public: |
| TimeStamp(); |
| TimeStamp(const TimeStamp& other); |
| explicit TimeStamp(int64_t msec); |
| TimeStamp& operator=(const TimeStamp& other); |
| |
| ~TimeStamp(); |
| |
| int64_t msec() const; |
| void msec(int64_t t); |
| }; |
| |
| class Record { |
| private: |
| std::string m_testName; |
| int64_t m_operations; |
| TimeStamp m_startTime; |
| TimeStamp m_stopTime; |
| |
| public: |
| Record(std::string testName, int64_t ops, const TimeStamp& start, |
| const TimeStamp& stop); |
| |
| Record(); |
| |
| Record(const Record& other); |
| |
| Record& operator=(const Record& other); |
| |
| void write(apache::geode::client::DataOutput& output); |
| |
| void read(apache::geode::client::DataInput& input); |
| |
| int elapsed(); |
| int perSec(); |
| std::string asString(); |
| |
| ~Record(); |
| }; |
| |
| typedef std::map<std::string, Record> RecordMap; |
| |
| class PerfSuite { |
| private: |
| std::string m_suiteName; |
| RecordMap m_records; |
| |
| public: |
| explicit PerfSuite(const char* suiteName); |
| |
| void addRecord(std::string testName, int64_t ops, const TimeStamp& start, |
| const TimeStamp& stop); |
| |
| /** create a file in cwd, named "<suite>_results.<host>" */ |
| void save(); |
| |
| /** load data saved in $ENV{'baselines'} named "<suite>_baseline.<host>" |
| * A non-favorable comparison will throw an TestException. |
| */ |
| void compare(); |
| }; |
| |
| class Thread; |
| |
| class ThreadLauncher { |
| private: |
| int m_thrCount; |
| Semaphore m_initSemaphore; |
| Semaphore m_startSemaphore; |
| Semaphore m_stopSemaphore; |
| Semaphore m_cleanSemaphore; |
| Semaphore m_termSemaphore; |
| TimeStamp* m_startTime; |
| TimeStamp* m_stopTime; |
| Thread& m_threadDef; |
| |
| public: |
| ThreadLauncher(int thrCount, Thread& thr); |
| |
| void go(); |
| |
| ~ThreadLauncher(); |
| |
| Semaphore& initSemaphore() { return m_initSemaphore; } |
| |
| Semaphore& startSemaphore() { return m_startSemaphore; } |
| |
| Semaphore& stopSemaphore() { return m_stopSemaphore; } |
| |
| Semaphore& cleanSemaphore() { return m_cleanSemaphore; } |
| |
| Semaphore& termSemaphore() { return m_termSemaphore; } |
| |
| TimeStamp startTime() { return *m_startTime; } |
| |
| TimeStamp stopTime() { return *m_stopTime; } |
| |
| private: |
| ThreadLauncher& operator=(const ThreadLauncher& other); |
| ThreadLauncher(const ThreadLauncher& other); |
| }; |
| |
| class Thread : public ACE_Task_Base { |
| private: |
| ThreadLauncher* m_launcher; |
| bool m_used; |
| |
| public: |
| Thread(); |
| // Unhide function to prevent SunPro Warnings |
| using ACE_Shared_Object::init; |
| void init(ThreadLauncher* l) { |
| ASSERT(!m_used, "Cannot reliably reuse Thread."); |
| m_launcher = l; |
| } |
| |
| ~Thread(); |
| |
| /** called before measurement begins. override to do per thread setup. */ |
| virtual void setup() {} |
| |
| /** run during measurement */ |
| virtual void perftask() = 0; |
| |
| /** called after measurement to clean up what might have been setup in setup.. |
| */ |
| virtual void cleanup() {} |
| |
| virtual int svc(); |
| }; |
| |
| // class NamingServiceThread |
| //: public ACE_Task_Base |
| //{ |
| // private: |
| // uint32_t m_port; |
| // |
| // void namingService() |
| // { |
| // char * argsv[2]; |
| // char pbuf[32]; |
| // sprintf( pbuf, "-p %d", 12321 ); |
| // |
| // argsv[0] = strdup( pbuf ); |
| // argsv[1] = 0; |
| // auto svcObj = ACE_SVC_INVOKE( ACE_Name_Acceptor ); |
| // |
| // if ( svcObj->init( 1, argsv ) == -1 ) { |
| // fprintf( stdout, "Failed to construct the Naming Service." ); |
| // fflush( stdout ); |
| // } |
| // ACE_Reactor::run_event_loop(); |
| // } |
| // |
| // public: |
| // NamingServiceThread( uint32_t port ) : m_port( port ) {} |
| // virtual int svc() { };//namingService(); } |
| //}; |
| } // namespace perf |
| |
| #endif // GEODE_INTEGRATION_TEST_FW_PERF_H_ |