/* * $Revision: 2633 $ * * last checkin: * $Author: gutwenger $ * $Date: 2012-07-18 09:09:28 +0200 (Mi, 18. Jul 2012) $ ***************************************************************/ /** \file * \brief Implementation of System class. * * \author Carsten Gutwenger * * \par License: * This file is part of the Open Graph Drawing Framework (OGDF). * * \par * Copyright (C)
* See README.txt in the root directory of the OGDF installation for details. * * \par * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * Version 2 or 3 as published by the Free Software Foundation; * see the file LICENSE.txt included in the packaging of this file * for details. * * \par * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * \par * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * \see http://www.gnu.org/copyleft/gpl.html ***************************************************************/ #include "basic.h" #ifdef __APPLE__ #include #include #include #include #include #include #include #include #elif defined(OGDF_SYSTEM_UNIX) #include #endif #if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__) #include #endif #ifdef _MSC_VER #include #elif defined(OGDF_SYSTEM_UNIX) || (defined(__MINGW32__) && !defined(__MINGW64__)) #include #include #include static void __cpuid(int CPUInfo[4], int infoType) { uint32_t a = CPUInfo[0]; uint32_t b = CPUInfo[1]; uint32_t c = CPUInfo[2]; uint32_t d = CPUInfo[3]; #if defined(__i386__) || defined(__x86_64__) && !defined(__APPLE__) __asm__ __volatile__ ("xchgl %%ebx,%0\n\t" "cpuid \n\t" "xchgl %%ebx,%0\n\t" : "+r" (b), "=a" (a), "=c" (c), "=d" (d) : "1" (infoType), "2" (c)); #else // not supported on other systems! a = b = c = d = 0; infoType = 0; #endif CPUInfo[0] = a; CPUInfo[1] = b; CPUInfo[2] = c; CPUInfo[3] = d; } #endif namespace ogdf { unsigned int System::s_cpuFeatures; int System::s_cacheSize; int System::s_cacheLine; int System::s_pageSize; int System::s_numberOfProcessors; #if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__) LARGE_INTEGER System::s_HPCounterFrequency; #endif void System::init() { s_cpuFeatures = 0; s_cacheSize = 0; s_cacheLine = 0; // currently not working for shared libs on Linux #if !defined(OGDF_DLL) || !defined(OGDF_SYSTEM_UNIX) int CPUInfo[4] = {-1}; __cpuid(CPUInfo, 0); unsigned int nIds = CPUInfo[0]; if(nIds >= 1) { __cpuid(CPUInfo, 1); int featureInfoECX = CPUInfo[2]; int featureInfoEDX = CPUInfo[3]; if(featureInfoEDX & (1 << 23)) s_cpuFeatures |= cpufmMMX; if(featureInfoEDX & (1 << 25)) s_cpuFeatures |= cpufmSSE; if(featureInfoEDX & (1 << 26)) s_cpuFeatures |= cpufmSSE2; if(featureInfoECX & (1 << 0)) s_cpuFeatures |= cpufmSSE3; if(featureInfoECX & (1 << 9)) s_cpuFeatures |= cpufmSSSE3; if(featureInfoECX & (1 << 19)) s_cpuFeatures |= cpufmSSE4_1; if(featureInfoECX & (1 << 20)) s_cpuFeatures |= cpufmSSE4_2; if(featureInfoECX & (1 << 5)) s_cpuFeatures |= cpufmVMX; if(featureInfoECX & (1 << 6)) s_cpuFeatures |= cpufmSMX; if(featureInfoECX & (1 << 7)) s_cpuFeatures |= cpufmEST; if(featureInfoECX & (1 << 3)) s_cpuFeatures |= cpufmMONITOR; } __cpuid(CPUInfo, 0x80000000); unsigned int nExIds = CPUInfo[0]; if(nExIds >= 0x80000006) { __cpuid(CPUInfo, 0x80000006); s_cacheLine = CPUInfo[2] & 0xff; s_cacheSize = (CPUInfo[2] >> 16) & 0xffff; } #if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__) QueryPerformanceFrequency(&s_HPCounterFrequency); SYSTEM_INFO siSysInfo; GetSystemInfo(&siSysInfo); s_pageSize = siSysInfo.dwPageSize; s_numberOfProcessors = siSysInfo.dwNumberOfProcessors; #elif defined(OGDF_SYSTEM_UNIX) && defined(__APPLE__) unsigned long long value; size_t size = sizeof( value ); if (sysctlbyname("hw.pagesize", &value, &size, NULL, 0) !=-1) s_pageSize = (int)value; else s_pageSize = 0; if (sysctlbyname("hw.ncpu", &value, &size, NULL, 0) !=-1) s_numberOfProcessors = (int)value; else s_numberOfProcessors = 1; #elif defined(OGDF_SYSTEM_UNIX) s_pageSize = sysconf(_SC_PAGESIZE); s_numberOfProcessors = (int)sysconf(_SC_NPROCESSORS_CONF); #else s_pageSize = 0; // just a placeholder!!! s_numberOfProcessors = 1; // just a placeholder!!! #endif #endif } #if defined(OGDF_SYSTEM_WINDOWS) || defined(__CYGWIN__) void System::getHPCounter(LARGE_INTEGER &counter) { QueryPerformanceCounter(&counter); } double System::elapsedSeconds( const LARGE_INTEGER &startCounter, const LARGE_INTEGER &endCounter) { return double(endCounter.QuadPart - startCounter.QuadPart) / s_HPCounterFrequency.QuadPart; } __int64 System::usedRealTime(__int64 &t) { __int64 tStart = t; t = GetTickCount(); return t - tStart; } long long System::physicalMemory() { #if !defined(__CYGWIN__) || (_WIN32_WINNT >= 0x0500) MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); return statex.ullTotalPhys; #else MEMORYSTATUS stat; stat.dwLength = sizeof (stat); GlobalMemoryStatus (&stat); return stat.dwTotalPhys; #endif } long long System::availablePhysicalMemory() { #if !defined(__CYGWIN__) || (_WIN32_WINNT >= 0x0500) MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); return statex.ullAvailPhys; #else MEMORYSTATUS stat; stat.dwLength = sizeof (stat); GlobalMemoryStatus (&stat); return stat.dwAvailPhys; #endif } size_t System::memoryUsedByProcess() { PROCESS_MEMORY_COUNTERS pmc; GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); return pmc.WorkingSetSize; } size_t System::peakMemoryUsedByProcess() { PROCESS_MEMORY_COUNTERS pmc; GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); return pmc.PeakWorkingSetSize; } #elif __APPLE__ long long System::physicalMemory() { unsigned long long value; size_t size = sizeof( value ); if (sysctlbyname("hw.memsize", &value, &size, NULL, 0) !=-1) return value; else return 0; } long long System::availablePhysicalMemory() { unsigned long long pageSize; long long result; size_t size = sizeof( pageSize ); sysctlbyname("hw.pagesize", &pageSize, &size, NULL, 0); vm_statistics_data_t vm_stat; int count = ((mach_msg_type_number_t) (sizeof(vm_statistics_data_t)/sizeof(integer_t))); host_statistics(mach_host_self(), HOST_VM_INFO, (integer_t*)&vm_stat, (mach_msg_type_number_t*)&count); result = (unsigned long long)(vm_stat.free_count + vm_stat.inactive_count) * pageSize; return result; } size_t System::memoryUsedByProcess() { /*int pid = getpid(); static char filename[32]; sprintf(filename, 32, "/proc/%d/statm", pid); int fd = open(filename, O_RDONLY, 0); if(fd==-1) OGDF_THROW(Exception); static char sbuf[256]; sbuf[read(fd, sbuf, sizeof(sbuf) - 1)] = 0; close(fd); long size, resident, share, trs, lrs, drs, dt; sscanf(sbuf, "%ld %ld %ld %ld %ld %ld %ld", &size, // total program size (in pages) &resident, // number of resident set (non-swapped) pages (4k) &share, // number of pages of shared (mmap'd) memory &trs, // text resident set size &lrs, // shared-lib resident set size &drs, // data resident set size &dt); // dirty pages return resident*4*1024;*/ return 0; } #else // LINUX, NOT MAC OS long long System::physicalMemory() { return (long long)(sysconf(_SC_PHYS_PAGES)) * sysconf(_SC_PAGESIZE); } long long System::availablePhysicalMemory() { return (long long)(sysconf(_SC_AVPHYS_PAGES)) * sysconf(_SC_PAGESIZE); } size_t System::memoryUsedByProcess() { int pid = getpid(); static char filename[32]; sprintf(filename, 32, "/proc/%d/statm", pid); int fd = open(filename, O_RDONLY, 0); if(fd==-1) OGDF_THROW(Exception); static char sbuf[256]; sbuf[read(fd, sbuf, sizeof(sbuf) - 1)] = 0; close(fd); long size, resident, share, trs, lrs, drs, dt; sscanf(sbuf, "%ld %ld %ld %ld %ld %ld %ld", &size, // total program size (in pages) &resident, // number of resident set (non-swapped) pages (4k) &share, // number of pages of shared (mmap'd) memory &trs, // text resident set size &lrs, // shared-lib resident set size &drs, // data resident set size &dt); // dirty pages return resident*4*1024; } #endif #ifdef OGDF_SYSTEM_WINDOWS size_t System::memoryAllocatedByMalloc() { _HEAPINFO hinfo; int heapstatus; hinfo._pentry = NULL; size_t allocMem = 0; while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) { if(hinfo._useflag == _USEDENTRY) allocMem += hinfo._size; } return allocMem; } size_t System::memoryInFreelistOfMalloc() { _HEAPINFO hinfo; int heapstatus; hinfo._pentry = NULL; size_t allocMem = 0; while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) { if(hinfo._useflag == _FREEENTRY) allocMem += hinfo._size; } return allocMem; } #elif __APPLE__ size_t System::memoryAllocatedByMalloc() { return mstats().chunks_used; } size_t System::memoryInFreelistOfMalloc() { return mstats().chunks_free; } #else size_t System::memoryAllocatedByMalloc() { return mallinfo().uordblks; } size_t System::memoryInFreelistOfMalloc() { return mallinfo().fordblks; } #endif #if !defined(OGDF_SYSTEM_WINDOWS) && !defined(__CYGWIN__) __int64 System::usedRealTime(__int64 &t) { __int64 tStart = t; timeval tv; gettimeofday(&tv, 0); t = __int64(tv.tv_sec) * 1000 + tv.tv_usec/1000; return t - tStart; } #endif size_t System::memoryAllocatedByMemoryManager() { return PoolMemoryAllocator::memoryAllocatedInBlocks(); } size_t System::memoryInGlobalFreeListOfMemoryManager() { return PoolMemoryAllocator::memoryInGlobalFreeList(); } size_t System::memoryInThreadFreeListOfMemoryManager() { return PoolMemoryAllocator::memoryInThreadFreeList(); } } // namespace ogdf