/* arrayPerformance.cpp */ /** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvData is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ /** * @author mrk * @date 2013.08.08 */ #include #define epicsExportSharedSymbols #include namespace epics { namespace pvDatabase { using namespace epics::pvData; using std::tr1::static_pointer_cast; using std::tr1::dynamic_pointer_cast; using std::cout; using std::endl; using std::ostringstream; ArrayPerformancePtr ArrayPerformance::create( std::string const & recordName, size_t size, double delay) { epics::pvData::PVStructurePtr pvStructure = epics::pvData::getStandardPVField()->scalarArray(epics::pvData::pvLong,"timeStamp,alarm"); ArrayPerformancePtr pvRecord( new ArrayPerformance(recordName,pvStructure,size,delay)); if(!pvRecord->init()) pvRecord.reset(); return pvRecord; } ArrayPerformance::ArrayPerformance( std::string const & recordName, epics::pvData::PVStructurePtr const & pvStructure, size_t size, double delay) : PVRecord(recordName,pvStructure), size(size), delay(delay), isDestroyed(false) { pvTimeStamp.attach(pvStructure->getSubField("timeStamp")); } ArrayPerformance::~ArrayPerformance() { } bool ArrayPerformance::init() { initPVRecord(); PVScalarArrayPtr pvScalarArray = getPVStructure()->getScalarArrayField("value",pvLong); if(pvScalarArray==NULL) return false; pvValue = static_pointer_cast(pvScalarArray); ArrayPerformancePtr xxx = dynamic_pointer_cast(getPtrSelf()); arrayPerformanceThread = ArrayPerformanceThreadPtr(new ArrayPerformanceThread(xxx)); arrayPerformanceThread->init(); return true; } void ArrayPerformance::start() { arrayPerformanceThread->start(); } void ArrayPerformance::process() { timeStamp.getCurrent(); pvTimeStamp.set(timeStamp); } void ArrayPerformance::destroy() { if(isDestroyed) return; isDestroyed = true; arrayPerformanceThread->destroy(); arrayPerformanceThread.reset(); PVRecord::destroy(); } ArrayPerformanceThread::ArrayPerformanceThread(ArrayPerformancePtr const & arrayPerformance) : arrayPerformance(arrayPerformance), isDestroyed(false), runReturned(false), threadName("arrayPerformance"), value(0) {} void ArrayPerformanceThread::init() { thread = std::auto_ptr(new epicsThread( *this, threadName.c_str(), epicsThreadGetStackSize(epicsThreadStackSmall), epicsThreadPriorityHigh)); } void ArrayPerformanceThread::start() { thread->start(); } void ArrayPerformanceThread::destroy() { Lock lock(mutex); if(isDestroyed) return; isDestroyed = true; while(true) { if(runReturned) break; lock.unlock(); epicsThreadSleep(.01); lock.lock(); } thread->exitWait(); thread.reset(); arrayPerformance.reset(); } void ArrayPerformanceThread::run() { TimeStamp timeStamp; TimeStamp timeStampLast; timeStampLast.getCurrent(); int nSinceLastReport = 0; while(true) { if(arrayPerformance->delay>0.0) epicsThreadSleep(arrayPerformance->delay); { Lock lock(mutex); if(isDestroyed) { runReturned = true; return; } } timeStamp.getCurrent(); double diff = TimeStamp::diff(timeStamp,timeStampLast); if(diff>=1.0) { ostringstream out; out << "arrayPerformance value " << value; out << " time " << diff ; double iterations = nSinceLastReport; iterations /= diff; if(iterations>10.0e9) { iterations /= 1e9; out << " gigaIterations/sec " << iterations; } else if(iterations>10.0e6) { iterations /= 1e6; out << " megaIterations/sec " << iterations; } else if(iterations>10.0e3) { iterations /= 1e3; out << " kiloIterations/sec " << iterations; } else { out << " Iterations/sec " << iterations; } double elementSize = arrayPerformance->size; double elementsPerSecond = elementSize*nSinceLastReport; elementsPerSecond /= diff; if(elementsPerSecond>10.0e9) { elementsPerSecond /= 1e9; out << " gigaElements/sec " << elementsPerSecond; } else if(elementsPerSecond>10.0e6) { elementsPerSecond /= 1e6; out << " megaElements/sec " << elementsPerSecond; } else if(elementsPerSecond>10.0e3) { elementsPerSecond /= 1e3; out << " kiloElements/sec " << elementsPerSecond; } else { out << " Elements/sec " << elementsPerSecond; } cout << out.str() << endl; timeStampLast = timeStamp; nSinceLastReport = 0; } ++nSinceLastReport; shared_vector xxx(arrayPerformance->size,value++); shared_vector data(freeze(xxx)); arrayPerformance->lock(); try { arrayPerformance->beginGroupPut(); arrayPerformance->pvValue->replace(data); arrayPerformance->process(); arrayPerformance->endGroupPut(); } catch(...) { arrayPerformance->unlock(); throw; } arrayPerformance->unlock(); } } }}