diff options
| -rw-r--r-- | indra/llcommon/llsys.cpp | 248 | 
1 files changed, 72 insertions, 176 deletions
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 99e61433c6..37733cf9ad 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -68,9 +68,11 @@ using namespace llsd;  #	include <sys/utsname.h>  #	include <stdint.h>  #	include <Carbon/Carbon.h> -#   include <sys/wait.h> -#   include <string.h>  #   include <stdexcept> +#	include <mach/host_info.h> +#	include <mach/mach_host.h> +#	include <mach/task.h> +#	include <mach/task_info.h>  #elif LL_LINUX  #	include <errno.h>  #	include <sys/utsname.h> @@ -990,194 +992,88 @@ LLSD LLMemoryInfo::loadStatsMap()  	stats.add("PrivateUsage KB",               pmem.PrivateUsage/1024);  #elif LL_DARWIN -	uint64_t phys = 0; - -	size_t len = sizeof(phys);	 -	if (sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0) -	{ -		stats.add("Total Physical KB", phys/1024); -	} -	else -	{ -		LL_WARNS("LLMemoryInfo") << "Unable to collect hw.memsize memory information" << LL_ENDL; -	} - -	FILE* pout = popen("vm_stat 2>&1", "r"); -	if (! pout)                     // popen() couldn't run vm_stat +	const vm_size_t pagekb(vm_page_size / 1024); +	 +	// +	// Collect the vm_stat's +	// +	  	{ -		// Save errno right away. -		int popen_errno(errno); -		LL_WARNS("LLMemoryInfo") << "Unable to collect vm_stat memory information: "; -		char buffer[256]; -		if (0 == strerror_r(popen_errno, buffer, sizeof(buffer))) +		vm_statistics_data_t vmstat; +		mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT; +		 +		if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS)  		{ -			LL_CONT << buffer; +			LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;  		}  		else  		{ -			LL_CONT << "errno " << popen_errno; +			stats.add("Pages free KB",		pagekb * vmstat.free_count); +			stats.add("Pages active KB",	pagekb * vmstat.active_count); +			stats.add("Pages inactive KB",	pagekb * vmstat.inactive_count); +			stats.add("Pages wired KB",		pagekb * vmstat.wire_count); + +			stats.add("Pages zero fill",		vmstat.zero_fill_count); +			stats.add("Page reactivations",		vmstat.reactivations); +			stats.add("Page-ins",				vmstat.pageins); +			stats.add("Page-outs",				vmstat.pageouts); +			 +			stats.add("Faults",					vmstat.faults); +			stats.add("Faults copy-on-write",	vmstat.cow_faults); +			 +			stats.add("Cache lookups",			vmstat.lookups); +			stats.add("Cache hits",				vmstat.hits); +			 +			stats.add("Page purgeable count",	vmstat.purgeable_count); +			stats.add("Page purges",			vmstat.purges); +			 +			stats.add("Page speculative reads",	vmstat.speculative_count);  		} -		LL_CONT << LL_ENDL;  	} -	else                            // popen() launched vm_stat + +	// +	// Collect the misc task info +	// +	  	{ -		// Mach Virtual Memory Statistics: (page size of 4096 bytes) -		// Pages free:					 462078. -		// Pages active:				 142010. -		// Pages inactive:				 220007. -		// Pages wired down:			 159552. -		// "Translation faults":	  220825184. -		// Pages copy-on-write:			2104153. -		// Pages zero filled:		  167034876. -		// Pages reactivated:			  65153. -		// Pageins:						2097212. -		// Pageouts:					  41759. -		// Object cache: 841598 hits of 7629869 lookups (11% hit rate) - -		// Intentionally don't pass the boost::no_except flag. These -		// boost::regex objects are constructed with string literals, so they -		// should be valid every time. If they become invalid, we WANT an -		// exception, hopefully even before the dev checks in. -		boost::regex pagesize_rx("\\(page size of ([0-9]+) bytes\\)"); -		boost::regex stat_rx("(.+): +([0-9]+)\\."); -		boost::regex cache_rx("Object cache: ([0-9]+) hits of ([0-9]+) lookups " -							  "\\(([0-9]+)% hit rate\\)"); -		boost::cmatch matched; -		LLSD::Integer pagesizekb(4096/1024); - -		// Here 'pout' is vm_stat's stdout. Search it for relevant data. -		char line[100]; -		line[sizeof(line)-1] = '\0'; -		while (fgets(line, sizeof(line)-1, pout)) +		task_events_info_data_t taskinfo; +		unsigned taskinfoSize = sizeof(taskinfo); +		 +		if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)  		{ -			size_t linelen(strlen(line)); -			// Truncate any trailing newline -			if (line[linelen - 1] == '\n') -			{ -				line[--linelen] = '\0'; -			} -			LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL; -			if (regex_search_no_exc(line, matched, pagesize_rx)) -			{ -				// "Mach Virtual Memory Statistics: (page size of 4096 bytes)" -				std::string pagesize_str(matched[1].first, matched[1].second); -				try -				{ -					// Reasonable to assume that pagesize will always be a -					// multiple of 1Kb? -					pagesizekb = boost::lexical_cast<LLSD::Integer>(pagesize_str)/1024; -				} -				catch (const boost::bad_lexical_cast&) -				{ -					LL_WARNS("LLMemoryInfo") << "couldn't parse '" << pagesize_str -											 << "' in vm_stat line: " << line << LL_ENDL; -					continue; -				} -				stats.add("page size", pagesizekb); -			} -			else if (regex_match_no_exc(line, matched, stat_rx)) -			{ -				// e.g. "Pages free:					 462078." -				// Strip double-quotes off certain statistic names -				const char *key_begin(matched[1].first), *key_end(matched[1].second); -				if (key_begin[0] == '"' && key_end[-1] == '"') -				{ -					++key_begin; -					--key_end; -				} -				LLSD::String key(key_begin, key_end); -				LLSD::String value_str(matched[2].first, matched[2].second); -				LLSD::Integer value(0); -				try -				{ -					value = boost::lexical_cast<LLSD::Integer>(value_str); -				} -				catch (const boost::bad_lexical_cast&) -				{ -					LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str -											 << "' in vm_stat line: " << line << LL_ENDL; -					continue; -				} -				// Store this statistic. -				stats.add(key, value); -				// Is this in units of pages? If so, convert to Kb. -				static const LLSD::String pages("Pages "); -				if (key.substr(0, pages.length()) == pages) -				{ -					// Synthesize a new key with kb in place of Pages -					LLSD::String kbkey("kb "); -					kbkey.append(key.substr(pages.length())); -					stats.add(kbkey, value * pagesizekb); -				} -			} -			else if (regex_match_no_exc(line, matched, cache_rx)) -			{ -				// e.g. "Object cache: 841598 hits of 7629869 lookups (11% hit rate)" -				static const char* cache_keys[] = { "cache hits", "cache lookups", "cache hit%" }; -				std::vector<LLSD::Integer> cache_values; -				for (size_t i = 0; i < (sizeof(cache_keys)/sizeof(cache_keys[0])); ++i) -				{ -					LLSD::String value_str(matched[i+1].first, matched[i+1].second); -					LLSD::Integer value(0); -					try -					{ -						value = boost::lexical_cast<LLSD::Integer>(value_str); -					} -					catch (boost::bad_lexical_cast&) -					{ -						LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str -												 << "' in vm_stat line: " << line << LL_ENDL; -						continue; -					} -					stats.add(cache_keys[i], value); -				} -			} -			else -			{ -				LL_WARNS("LLMemoryInfo") << "unrecognized vm_stat line: " << line << LL_ENDL; -			} +			LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;  		} -		int status(pclose(pout)); -		if (status == -1)           // pclose() couldn't retrieve rc +		else  		{ -			// Save errno right away. -			int pclose_errno(errno); -			// The ECHILD error happens so frequently that unless filtered, -			// the warning below spams the log file. This is too bad, because -			// sometimes the logic above fails to produce any output derived -			// from vm_stat, but we've been unable to observe any specific -			// error indicating the problem. -			if (pclose_errno != ECHILD) -			{ -				LL_WARNS("LLMemoryInfo") << "Unable to obtain vm_stat termination code: "; -				char buffer[256]; -				if (0 == strerror_r(pclose_errno, buffer, sizeof(buffer))) -				{ -					LL_CONT << buffer; -				} -				else -				{ -					LL_CONT << "errno " << pclose_errno; -				} -				LL_CONT << LL_ENDL; -			} +			stats.add("Task page-ins",					taskinfo.pageins); +			stats.add("Task copy-on-write faults",		taskinfo.cow_faults); +			stats.add("Task messages sent",				taskinfo.messages_sent); +			stats.add("Task messages received",			taskinfo.messages_received); +			stats.add("Task mach system call count",	taskinfo.syscalls_mach); +			stats.add("Task unix system call count",	taskinfo.syscalls_unix); +			stats.add("Task context switch count",		taskinfo.csw);  		} -		else                        // pclose() retrieved rc; analyze +	}	 +	 +	// +	// Collect the basic task info +	// + +	{ +		task_basic_info_64_data_t taskinfo; +		unsigned taskinfoSize = sizeof(taskinfo); +		 +		if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)  		{ -			if (WIFEXITED(status)) -			{ -				int rc(WEXITSTATUS(status)); -				if (rc != 0) -				{ -					LL_WARNS("LLMemoryInfo") << "vm_stat terminated with rc " << rc << LL_ENDL; -				} -			} -			else if (WIFSIGNALED(status)) -			{ -				LL_WARNS("LLMemoryInfo") << "vm_stat terminated by signal " << WTERMSIG(status) -										 << LL_ENDL; -			} +			LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL; +		} +		else +		{ +			stats.add("Basic suspend count",					taskinfo.suspend_count); +			stats.add("Basic virtual memory KB",				taskinfo.virtual_size / 1024); +			stats.add("Basic resident memory KB",				taskinfo.resident_size / 1024); +			stats.add("Basic new thread policy",				taskinfo.policy);  		}  	}  | 
