diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 8a4f1424b..b19027826 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -18,8 +18,9 @@ extern void trace(unsigned int level, const char *message); // Format memory allocated, separate thousands by comma. extern std::string format_memsize_MB(size_t n); // Return string to be added to the boost::log output to inform about the current process memory allocation. -// The string is non-empty only if the loglevel >= info (3). -extern std::string log_memory_info(); +// The string is non-empty if the loglevel >= info (3) or ignore_loglevel==true. +// Latter is used to get the memory info from SysInfoDialog. +extern std::string log_memory_info(bool ignore_loglevel = false); extern void disable_multi_threading(); // Returns the size of physical memory (RAM) in bytes. extern size_t total_physical_memory(); diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 0718ebf0e..ea5e3edec 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -435,84 +435,81 @@ std::string format_memsize_MB(size_t n) return out + "MB"; } -#ifdef WIN32 -#ifndef PROCESS_MEMORY_COUNTERS_EX - // MingW32 doesn't have this struct in psapi.h - typedef struct _PROCESS_MEMORY_COUNTERS_EX { - DWORD cb; - DWORD PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; - SIZE_T PrivateUsage; - } PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX; -#endif /* PROCESS_MEMORY_COUNTERS_EX */ - -std::string log_memory_info() +// Returns platform-specific string to be used as log output or parsed in SysInfoDialog. +// The latter parses the string with (semi)colons as separators, it should look about as +// "desc1: value1; desc2: value2" or similar (spaces should not matter). +std::string log_memory_info(bool ignore_loglevel) { std::string out; - if (logSeverity <= boost::log::trivial::info) { + if (ignore_loglevel || logSeverity <= boost::log::trivial::info) { +#ifdef WIN32 + #ifndef PROCESS_MEMORY_COUNTERS_EX + // MingW32 doesn't have this struct in psapi.h + typedef struct _PROCESS_MEMORY_COUNTERS_EX { + DWORD cb; + DWORD PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivateUsage; + } PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX; + #endif /* PROCESS_MEMORY_COUNTERS_EX */ + + HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); if (hProcess != nullptr) { PROCESS_MEMORY_COUNTERS_EX pmc; if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) - out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + " PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + " Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; + out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; + else + out += " Used memory: N/A"; CloseHandle(hProcess); } - } - return out; -} #elif defined(__linux__) or defined(__APPLE__) -std::string log_memory_info() -{ - std::string out = " Unable to get current memory usage."; - - // Get current memory usage. -#ifdef __APPLE__ - struct mach_task_basic_info info; - mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; - if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount ) == KERN_SUCCESS ) - out = " Memory usage: resident: " + format_memsize_MB((size_t)info.resident_size); -#else // i.e. __linux__ - - size_t tSize = 0, resident = 0, share = 0; - std::ifstream buffer("/proc/self/statm"); - if (buffer) { - if ((buffer >> tSize >> resident >> share)) { + // Get current memory usage. + #ifdef __APPLE__ + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + out += " Resident memory: "; + if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount ) == KERN_SUCCESS ) + out += format_memsize_MB((size_t)info.resident_size); + else + out += "N/A"; + #else // i.e. __linux__ + size_t tSize = 0, resident = 0, share = 0; + std::ifstream buffer("/proc/self/statm"); + if (buffer && (buffer >> tSize >> resident >> share)) { size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE); // in case x86-64 is configured to use 2MB pages size_t rss = resident * page_size; - out = " Memory usage: resident: " + format_memsize_MB(rss); - out += " shared: " + format_memsize_MB(share * page_size); - out += " private: " + format_memsize_MB(rss - share * page_size); + out += " Resident memory: " + format_memsize_MB(rss); + out += "; Shared memory: " + format_memsize_MB(share * page_size); + out += "; Private memory: " + format_memsize_MB(rss - share * page_size); } - } + else + out += " Used memory: N/A"; + #endif + // Now get peak memory usage. + out += "; Peak memory usage: "; + rusage memory_info; + if (getrusage(RUSAGE_SELF, &memory_info) == 0) + { + size_t peak_mem_usage = (size_t)memory_info.ru_maxrss; + #ifdef __linux__ + peak_mem_usage *= 1024;// getrusage returns the value in kB on linux + #endif + out += format_memsize_MB(peak_mem_usage); + } + else + out += "N/A"; #endif - // Now get peak memory usage. - rusage memory_info; - if (getrusage(RUSAGE_SELF, &memory_info) != 0) - out += " Could not get peak memory usage."; - else { - size_t peak_mem_usage = (size_t)memory_info.ru_maxrss; - #ifdef __linux - peak_mem_usage *= 1024L;// getrusage returns the value in kB on linux - #endif - out += " Peak Memory Usage: " + format_memsize_MB(peak_mem_usage); } - return out; } -#else -std::string log_memory_info() -{ - return std::string(); -} - -#endif // Returns the size of physical memory (RAM) in bytes. // http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index e9487ee15..a1bae8742 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -58,21 +58,19 @@ std::string get_mem_info(bool format_as_html) std::string b_end = format_as_html ? "" : ""; std::string line_end = format_as_html ? "
" : "\n"; - const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack_main(); - out << b_start << "RAM size reserved for the Undo / Redo stack [MB]: " << b_end << Slic3r::format_memsize_MB(stack.get_memory_limit()) << line_end; - out << b_start << "RAM size occupied by the Undo / Redo stack [MB]: " << b_end << Slic3r::format_memsize_MB(stack.memsize()) << line_end << line_end; - -#ifdef _WIN32 - HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); - if (hProcess != nullptr) { - PROCESS_MEMORY_COUNTERS_EX pmc; - if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) - out << b_start << "WorkingSet [MB]: " << b_end << format_memsize_MB(pmc.WorkingSetSize) << line_end - << b_start << "PrivateBytes [MB]: " << b_end << format_memsize_MB(pmc.PrivateUsage) << line_end - << b_start << "Pagefile(peak) [MB]: " << b_end << format_memsize_MB(pmc.PagefileUsage) << "(" << format_memsize_MB(pmc.PeakPagefileUsage) << ")" << line_end; - CloseHandle(hProcess); + std::string mem_info_str = log_memory_info(true); + std::istringstream mem_info(mem_info_str); + std::string value; + while (std::getline(mem_info, value, ':')) { + out << b_start << (value+": ") << b_end; + std::getline(mem_info, value, ';'); + out << value << line_end; } -#endif + + const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack_main(); + out << b_start << "RAM size reserved for the Undo / Redo stack: " << b_end << Slic3r::format_memsize_MB(stack.get_memory_limit()) << line_end; + out << b_start << "RAM size occupied by the Undo / Redo stack: " << b_end << Slic3r::format_memsize_MB(stack.memsize()) << line_end << line_end; + return out.str(); }