diff options
| -rw-r--r-- | cmds/statsd/Android.mk | 6 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsService.cpp | 23 | ||||
| -rw-r--r-- | cmds/statsd/src/StatsService.h | 5 | ||||
| -rw-r--r-- | cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp | 99 | ||||
| -rw-r--r-- | cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h | 33 |
5 files changed, 163 insertions, 3 deletions
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 1b2f9da22ec1..b2798a060a4a 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -55,7 +55,8 @@ statsd_common_src := \ src/storage/DropboxWriter.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ - src/stats_util.cpp + src/stats_util.cpp \ + src/guardrail/MemoryLeakTrackUtil.cpp statsd_common_c_includes := \ $(LOCAL_PATH)/src \ @@ -82,7 +83,8 @@ statsd_common_shared_libraries := \ libhidltransport \ libhwbinder \ android.hardware.power@1.0 \ - android.hardware.power@1.1 + android.hardware.power@1.1 \ + libmemunreachable # ========= # statsd diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 1a056df8e367..65b3da1cd258 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -17,10 +17,11 @@ #define DEBUG true #include "Log.h" -#include "android-base/stringprintf.h" #include "StatsService.h" +#include "android-base/stringprintf.h" #include "config/ConfigKey.h" #include "config/ConfigManager.h" +#include "guardrail/MemoryLeakTrackUtil.h" #include "storage/DropboxReader.h" #include <android-base/file.h> @@ -226,6 +227,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& if (!args[0].compare(String8("clear-config"))) { return cmd_remove_config_files(out); } + + if (!args[0].compare(String8("meminfo"))) { + return cmd_dump_memory_info(out); + } } print_cmd_help(out); @@ -238,6 +243,15 @@ void StatsService::print_cmd_help(FILE* out) { "[timestamp_nsec_optional]\n"); fprintf(out, "\n"); fprintf(out, "\n"); + fprintf(out, "usage: adb shell cmd stats meminfo\n"); + fprintf(out, "\n"); + fprintf(out, " Prints the malloc debug information. You need to run the following first: \n"); + fprintf(out, " # adb shell stop\n"); + fprintf(out, " # adb shell setprop libc.debug.malloc.program statsd \n"); + fprintf(out, " # adb shell setprop libc.debug.malloc.options backtrace \n"); + fprintf(out, " # adb shell start\n"); + fprintf(out, "\n"); + fprintf(out, "\n"); fprintf(out, "usage: adb shell cmd stats print-uid-map \n"); fprintf(out, "\n"); fprintf(out, " Prints the UID, app name, version mapping.\n"); @@ -507,6 +521,13 @@ status_t StatsService::cmd_remove_config_files(FILE* out) { return NO_ERROR; } +status_t StatsService::cmd_dump_memory_info(FILE* out) { + std::string s = dumpMemInfo(100); + fprintf(out, "Memory Info\n"); + fprintf(out, "%s", s.c_str()); + return NO_ERROR; +} + Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version, const vector<String16>& app) { if (DEBUG) ALOGD("StatsService::informAllUidData was called"); diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index 4d768f630362..47f0bb601fef 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -160,6 +160,11 @@ private: */ status_t cmd_remove_config_files(FILE* out); + /* + * Dump memory usage by statsd. + */ + status_t cmd_dump_memory_info(FILE* out); + /** * Update a configuration. */ diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp new file mode 100644 index 000000000000..e1947c4a5fe8 --- /dev/null +++ b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define DEBUG true // STOPSHIP if true +#include "Log.h" + +#include <sstream> +#include "MemoryLeakTrackUtil.h" + +/* + * The code here originally resided in MediaPlayerService.cpp + */ + +// Figure out the abi based on defined macros. +#if defined(__arm__) +#define ABI_STRING "arm" +#elif defined(__aarch64__) +#define ABI_STRING "arm64" +#elif defined(__mips__) && !defined(__LP64__) +#define ABI_STRING "mips" +#elif defined(__mips__) && defined(__LP64__) +#define ABI_STRING "mips64" +#elif defined(__i386__) +#define ABI_STRING "x86" +#elif defined(__x86_64__) +#define ABI_STRING "x86_64" +#else +#error "Unsupported ABI" +#endif + +extern std::string backtrace_string(const uintptr_t* frames, size_t frame_count); + +namespace android { +namespace os { +namespace statsd { + +extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, size_t* infoSize, + size_t* totalMemory, size_t* backtraceSize); + +extern "C" void free_malloc_leak_info(uint8_t* info); + +std::string dumpMemInfo(size_t limit) { + uint8_t* info; + size_t overallSize; + size_t infoSize; + size_t totalMemory; + size_t backtraceSize; + get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); + + size_t count; + if (info == nullptr || overallSize == 0 || infoSize == 0 || + (count = overallSize / infoSize) == 0) { + ALOGD("no malloc info, libc.debug.malloc.program property should be set"); + return std::string(); + } + + std::ostringstream oss; + oss << totalMemory << " bytes in " << count << " allocations\n"; + oss << " ABI: '" ABI_STRING "'" + << "\n\n"; + if (count > limit) count = limit; + + // The memory is sorted based on total size which is useful for finding + // worst memory offenders. For diffs, sometimes it is preferable to sort + // based on the backtrace. + for (size_t i = 0; i < count; i++) { + struct AllocEntry { + size_t size; // bit 31 is set if this is zygote allocated memory + size_t allocations; + uintptr_t backtrace[]; + }; + + const AllocEntry* const e = (AllocEntry*)(info + i * infoSize); + + oss << (e->size * e->allocations) << " bytes ( " << e->size << " bytes * " << e->allocations + << " allocations )\n"; + oss << backtrace_string(e->backtrace, backtraceSize) << "\n"; + } + oss << "\n"; + free_malloc_leak_info(info); + return oss.str(); +} + +} // namespace statsd +} // namespace os +} // namespace android
\ No newline at end of file diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h new file mode 100644 index 000000000000..444ed92cc9bb --- /dev/null +++ b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <iostream> + +namespace android { +namespace os { +namespace statsd { +/* + * Dump the heap memory of the calling process, sorted by total size + * (allocation size * number of allocations). + * + * limit is the number of unique allocations to return. + */ +extern std::string dumpMemInfo(size_t limit); + +} // namespace statsd +} // namespace os +} // namespace android
\ No newline at end of file |