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 GatherRss(uint64_t * rss_bytes)64void GatherRss(uint64_t* rss_bytes) { 65 android::meminfo::ProcMemInfo proc_mem(getpid()); 66 const std::vector<android::meminfo::Vma>& maps = proc_mem.MapsWithoutUsageStats(); 67 for (auto& vma : maps) { 68 if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") || 69 android::base::StartsWith(vma.name, "[anon:GWP-ASan")) { 70 android::meminfo::Vma update_vma(vma); 71 if (!proc_mem.FillInVmaStats(update_vma)) { 72 err(1, "FillInVmaStats failed\n"); 73 } 74 *rss_bytes += update_vma.usage.rss; 75 } 76 } 77 } 78 #endif 79 SetBenchmarkCounters(benchmark::State & state)80void MemoryTracker::SetBenchmarkCounters(benchmark::State& state) { 81 total_iterations_ += state.iterations(); 82 #if defined(__BIONIC__) 83 state.counters["MEAN_RSS_BYTES"] = total_rss_bytes_ / static_cast<double>(total_iterations_); 84 state.counters["MAX_RSS_BYTES"] = max_rss_bytes_; 85 state.counters["MIN_RSS_BYTES"] = min_rss_bytes_; 86 #endif 87 state.counters["MEAN_ALLOCATED_BYTES"] = 88 total_alloc_bytes_ / static_cast<double>(total_iterations_); 89 state.counters["MAX_ALLOCATED_BYTES"] = max_alloc_bytes_; 90 state.counters["MIN_ALLOCATED_BYTES"] = min_alloc_bytes_; 91 } 92 StartTrackingAllocations()93void MemoryTracker::StartTrackingAllocations() { 94 #if defined(__BIONIC__) 95 mallopt(M_PURGE, 0); 96 rss_bytes_before_ = 0; 97 GatherRss(&rss_bytes_before_); 98 #endif 99 alloc_bytes_before_ = mallinfo().uordblks; 100 } 101 StopTrackingAllocations()102void MemoryTracker::StopTrackingAllocations() { 103 #if defined(__BIONIC__) 104 mallopt(M_PURGE, 0); 105 #endif 106 uint64_t bytes_alloced = mallinfo().uordblks - alloc_bytes_before_; 107 total_alloc_bytes_ += bytes_alloced; 108 if (bytes_alloced > max_alloc_bytes_) max_alloc_bytes_ = bytes_alloced; 109 if (bytes_alloced < min_alloc_bytes_) min_alloc_bytes_ = bytes_alloced; 110 #if defined(__BIONIC__) 111 uint64_t rss_bytes = 0; 112 GatherRss(&rss_bytes); 113 total_rss_bytes_ += rss_bytes - rss_bytes_before_; 114 if (rss_bytes > max_rss_bytes_) max_rss_bytes_ = rss_bytes; 115 if (rss_bytes < min_rss_bytes_) min_rss_bytes_ = rss_bytes; 116 #endif 117 } 118