1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <err.h> 18 #include <stdint.h> 19 20 #include <benchmark/benchmark.h> 21 #include <malloc.h> 22 23 #include <string> 24 #include <vector> 25 26 #include <android-base/file.h> 27 #include <android-base/strings.h> 28 #include <benchmark/benchmark.h> 29 30 #include <unwindstack/Elf.h> 31 #include <unwindstack/Memory.h> 32 33 #include "utils/OfflineUnwindUtils.h" 34 35 #include "Utils.h" 36 GetBenchmarkFilesDirectory()37std::string GetBenchmarkFilesDirectory() { 38 std::string path = android::base::GetExecutableDirectory() + "/benchmarks/files/"; 39 unwindstack::DecompressFiles(path); 40 return path; 41 } 42 GetElfFile()43std::string GetElfFile() { 44 return GetBenchmarkFilesDirectory() + "libart_arm.so"; 45 } 46 GetSymbolSortedElfFile()47std::string GetSymbolSortedElfFile() { 48 return GetBenchmarkFilesDirectory() + "boot_arm.oat"; 49 } 50 GetLargeCompressedFrameElfFile()51std::string GetLargeCompressedFrameElfFile() { 52 return GetBenchmarkFilesDirectory() + "libpac.so"; 53 } 54 GetLargeEhFrameElfFile()55std::string GetLargeEhFrameElfFile() { 56 return GetBenchmarkFilesDirectory() + "libLLVM_android.so"; 57 } 58 59 #if defined(__BIONIC__) 60 61 #include <meminfo/procmeminfo.h> 62 #include <procinfo/process_map.h> 63 GetRSSBytes()64uint64_t GetRSSBytes() { 65 uint64_t total_bytes = 0; 66 android::meminfo::ProcMemInfo proc_mem(getpid()); 67 const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats(); 68 for (auto& vma : maps) { 69 if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") || 70 android::base::StartsWith(vma.name, "[anon:GWP-ASan")) { 71 android::meminfo::Vma update_vma(vma); 72 if (!proc_mem.FillInVmaStats(update_vma)) { 73 err(1, "FillInVmaStats failed"); 74 } 75 total_bytes += update_vma.usage.rss; 76 } 77 } 78 return total_bytes; 79 } 80 #endif 81 SetBenchmarkCounters(benchmark::State & state)82void MemoryTracker::SetBenchmarkCounters(benchmark::State& state) { 83 double total_iterations = static_cast<double>(state.iterations()); 84 #if defined(__BIONIC__) 85 state.counters["AVG_RSS_BYTES"] = total_rss_bytes_ / total_iterations; 86 state.counters["MAX_RSS_BYTES"] = max_rss_bytes_; 87 state.counters["MIN_RSS_BYTES"] = min_rss_bytes_; 88 #endif 89 state.counters["AVG_ALLOCATED_BYTES"] = total_alloc_bytes_ / total_iterations; 90 state.counters["MAX_ALLOCATED_BYTES"] = max_alloc_bytes_; 91 state.counters["MIN_ALLOCATED_BYTES"] = min_alloc_bytes_; 92 } 93 StartTrackingAllocations()94void MemoryTracker::StartTrackingAllocations() { 95 #if defined(__BIONIC__) 96 mallopt(M_PURGE_ALL, 0); 97 rss_bytes_before_ = GetRSSBytes(); 98 #endif 99 alloc_bytes_before_ = mallinfo().uordblks; 100 } 101 StopTrackingAllocations()102void MemoryTracker::StopTrackingAllocations() { 103 #if defined(__BIONIC__) 104 mallopt(M_PURGE_ALL, 0); 105 #endif 106 uint64_t alloc_bytes = 0; 107 uint64_t alloc_bytes_after = mallinfo().uordblks; 108 if (alloc_bytes_after > alloc_bytes_before_) { 109 alloc_bytes = alloc_bytes_after - alloc_bytes_before_; 110 } 111 total_alloc_bytes_ += alloc_bytes; 112 if (alloc_bytes > max_alloc_bytes_) max_alloc_bytes_ = alloc_bytes; 113 if (alloc_bytes < min_alloc_bytes_) min_alloc_bytes_ = alloc_bytes; 114 #if defined(__BIONIC__) 115 uint64_t rss_bytes = 0; 116 uint64_t rss_bytes_after = GetRSSBytes(); 117 if (rss_bytes_after > rss_bytes_before_) { 118 rss_bytes = rss_bytes_after - rss_bytes_before_; 119 } 120 total_rss_bytes_ += rss_bytes; 121 if (rss_bytes > max_rss_bytes_) max_rss_bytes_ = rss_bytes; 122 if (rss_bytes < min_rss_bytes_) min_rss_bytes_ = rss_bytes; 123 #endif 124 } 125