3c9d481f | 2014-05-07 01:17:19 | Francois Andriot |
Greatly improve tdehwlib polling performance This relates to Bug 1992 |
||
M tdecore/tdehw/tdehardwaredevices.cpp M tdecore/tdehw/tdehardwaredevices.h |
||
diff --git a/tdecore/tdehw/tdehardwaredevices.cpp b/tdecore/tdehw/tdehardwaredevices.cpp index 30d06a7..092fba2 100644 --- a/tdecore/tdehw/tdehardwaredevices.cpp +++ b/tdecore/tdehw/tdehardwaredevices.cpp @@ -70,6 +70,24 @@ // Compile-time configuration #include "config.h" +// Profiling stuff +//#define CPUPROFILING +//#define STATELESSPROFILING + +#include <time.h> +timespec diff(timespec start, timespec end) +{ + timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; +} + // BEGIN BLOCK // Copied from include/linux/genhd.h #define GENHD_FL_REMOVABLE 1 @@ -199,6 +217,10 @@ m_deviceWatchTimer = new TQTimer(this); connect( m_deviceWatchTimer, SIGNAL(timeout()), this, SLOT(processStatelessDevices()) ); + // Special case for battery polling (longer delay, 5 seconds) + m_batteryWatchTimer = new TQTimer(this); + connect( m_batteryWatchTimer, SIGNAL(timeout()), this, SLOT(processBatteryDevices()) ); + // Update internal device information queryHardwareInformation(); } @@ -207,6 +229,7 @@ TDEHardwareDevices::~TDEHardwareDevices() { // Stop device scanning m_deviceWatchTimer->stop(); + m_batteryWatchTimer->stop(); // [FIXME 0.01] #if 0 @@ -243,11 +266,26 @@ if (nodezerocpufreq.exists()) { m_cpuWatchTimer->start( 500, FALSE ); // 0.5 second repeating timer } + m_batteryWatchTimer->stop(); // Battery devices are included in stateless devices m_deviceWatchTimer->start( 1000, FALSE ); // 1 second repeating timer } else { m_cpuWatchTimer->stop(); m_deviceWatchTimer->stop(); + } +} + +void TDEHardwareDevices::setBatteryUpdatesEnabled(bool enable) { + if (enable) { + TQDir nodezerocpufreq("/sys/devices/system/cpu/cpu0/cpufreq"); + if (nodezerocpufreq.exists()) { + m_cpuWatchTimer->start( 500, FALSE ); // 0.5 second repeating timer + } + m_batteryWatchTimer->start( 5000, FALSE ); // 5 second repeating timer + } + else { + m_cpuWatchTimer->stop(); + m_batteryWatchTimer->stop(); } } @@ -270,6 +308,7 @@ syspath += "/"; } TDEGenericDevice *hwdevice; + // We can't use m_deviceList directly as m_deviceList can only have one iterator active against it at any given time TDEGenericHardwareList devList = listAllPhysicalDevices(); for ( hwdevice = devList.first(); hwdevice; hwdevice = devList.next() ) { @@ -280,6 +319,30 @@ return 0; } + +TDECPUDevice* TDEHardwareDevices::findCPUBySystemPath(TQString syspath, bool inCache=true) { + TDECPUDevice* cdevice; + + // Look for the device in the cache first + if(inCache && !m_cpuByPathCache.isEmpty()) { + cdevice = m_cpuByPathCache.find(syspath); + if(cdevice) { + return cdevice; + } + } + + // If the CPU was not found in cache, we need to parse the entire device list to get it. + cdevice = dynamic_cast<TDECPUDevice*>(findBySystemPath(syspath)); + if(cdevice) { + if(inCache) { + m_cpuByPathCache.insert(syspath, cdevice); // Add the device to the cache + } + return cdevice; + } + + return 0; +} + TDEGenericDevice* TDEHardwareDevices::findByUniqueID(TQString uid) { TDEGenericDevice *hwdevice; @@ -410,16 +473,28 @@ // Detect what changed between the old cpu information and the new information, // and emit appropriate events +#ifdef CPUPROFILING + timespec time1, time2, time3; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); + time3 = time1; + printf("TDEHardwareDevices::processModifiedCPUs() : begin at '%u'\n", time1.tv_nsec); +#endif + // Read new CPU information table m_cpuInfo.clear(); TQFile cpufile( "/proc/cpuinfo" ); if ( cpufile.open( IO_ReadOnly ) ) { TQTextStream stream( &cpufile ); - while ( !stream.atEnd() ) { - m_cpuInfo.append(stream.readLine()); - } + // Using read() instead of readLine() inside a loop is 4 times faster ! + m_cpuInfo = TQStringList::split('\n', stream.read(), true); cpufile.close(); } + +#ifdef CPUPROFILING + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); + printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint1 at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec); + time1 = time2; +#endif // Ensure "processor" is the first entry in each block and determine which cpuinfo type is in use bool cpuinfo_format_x86 = true; @@ -431,38 +506,42 @@ TQStringList::Iterator blockBegin = m_cpuInfo.begin(); for (TQStringList::Iterator cpuit1 = m_cpuInfo.begin(); cpuit1 != m_cpuInfo.end(); ++cpuit1) { curline1 = *cpuit1; - curline1 = curline1.stripWhiteSpace(); if (!(*blockBegin).startsWith("processor")) { bool found = false; TQStringList::Iterator cpuit2; for (cpuit2 = blockBegin; cpuit2 != m_cpuInfo.end(); ++cpuit2) { curline2 = *cpuit2; - curline2 = curline2.stripWhiteSpace(); if (curline2.startsWith("processor")) { found = true; break; } - else if (curline2 == "") { + else if (curline2 == NULL || curline2 == "") { break; } } if (found) { m_cpuInfo.insert(blockBegin, (*cpuit2)); } - else { + else if(blockNumber == 0) { m_cpuInfo.insert(blockBegin, "processor : 0"); } } - if (curline1 == "") { + if (curline1 == NULL || curline1 == "") { blockNumber++; blockBegin = cpuit1; blockBegin++; } - if (curline1.startsWith("Processor")) { + else if (curline1.startsWith("Processor")) { cpuinfo_format_x86 = false; cpuinfo_format_arm = true; } } + +#ifdef CPUPROFILING + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); + printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint2 at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec); + time1 = time2; +#endif // Parse CPU information table TDECPUDevice *cdevice; @@ -482,44 +561,45 @@ for (cpuit = m_cpuInfo.begin(); cpuit != m_cpuInfo.end(); ++cpuit) { curline = *cpuit; if (curline.startsWith("processor")) { - curline.remove(0, curline.find(":")+1); - curline = curline.stripWhiteSpace(); + curline.remove(0, curline.find(":")+2); processorNumber = curline.toInt(); - if (!cdevice) cdevice = dynamic_cast<TDECPUDevice*>(findBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber))); + if (!cdevice) { + cdevice = dynamic_cast<TDECPUDevice*>(findCPUBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber))); + } if (cdevice) { - if (cdevice->coreNumber() != processorNumber) modified = true; - cdevice->internalSetCoreNumber(processorNumber); + if (cdevice->coreNumber() != processorNumber) { + modified = true; + cdevice->internalSetCoreNumber(processorNumber); + } } } - if (curline.startsWith("model name")) { - curline.remove(0, curline.find(":")+1); - curline = curline.stripWhiteSpace(); - if (cdevice) { - if (cdevice->name() != curline) modified = true; + else if (cdevice && curline.startsWith("model name")) { + curline.remove(0, curline.find(":")+2); + if (cdevice->name() != curline) { + modified = true; cdevice->internalSetName(curline); } } - if (curline.startsWith("cpu MHz")) { - curline.remove(0, curline.find(":")+1); - curline = curline.stripWhiteSpace(); - if (cdevice) { - if (cdevice->frequency() != curline.toDouble()) modified = true; + else if (cdevice && curline.startsWith("cpu MHz")) { + curline.remove(0, curline.find(":")+2); + if (cdevice->frequency() != curline.toDouble()) { + modified = true; cdevice->internalSetFrequency(curline.toDouble()); - have_frequency = true; } + have_frequency = true; } - if (curline.startsWith("vendor_id")) { - curline.remove(0, curline.find(":")+1); - curline = curline.stripWhiteSpace(); - if (cdevice) { - if (cdevice->vendorName() != curline) modified = true; + else if (cdevice && curline.startsWith("vendor_id")) { + curline.remove(0, curline.find(":")+2); + if (cdevice->vendorName() != curline) { ** Diff limit reached (max: 250 lines) ** |