|
3 | 3 | /// |
4 | 4 | /// \author Pascal Boeschoten ([email protected]) |
5 | 5 |
|
6 | | -#pragma once |
| 6 | +#include "MemoryMaps.h" |
7 | 7 |
|
| 8 | +#include <fstream> |
8 | 9 | #include <map> |
| 10 | +#include <sstream> |
| 11 | +#include <string> |
| 12 | +#include <iostream> |
9 | 13 | #include <boost/throw_exception.hpp> |
10 | | -#include <boost/algorithm/string/split.hpp> |
| 14 | +#include <boost/algorithm/string.hpp> |
| 15 | +#include <boost/lexical_cast.hpp> |
| 16 | +#include "Common/System.h" |
11 | 17 |
|
12 | 18 | namespace AliceO2 { |
13 | 19 | namespace roc { |
14 | 20 | namespace Utilities { |
15 | 21 |
|
16 | | -std::vector<MemoryMap> getMemoryMaps() |
| 22 | +namespace { |
| 23 | +std::string slurp(std::string file) |
17 | 24 | { |
18 | | - std::vector<MemoryMap> memoryMaps; |
| 25 | + std::ifstream ifstream(file); |
| 26 | + std::stringstream buffer; |
| 27 | + buffer << ifstream.rdbuf(); |
| 28 | + return buffer.str(); |
| 29 | +} |
| 30 | + |
| 31 | +/// Splits string into rows and "columns" |
| 32 | +std::vector<std::vector<std::string>> tablify(std::string string) { |
| 33 | + std::vector<std::string> lines; |
| 34 | + boost::split(lines, string, boost::is_any_of("\n"), boost::token_compress_on); |
| 35 | + std::vector<std::vector<std::string>> splitLines(lines.size()); |
| 36 | + for (size_t i = 0; i < lines.size(); ++i) { |
| 37 | + boost::split(splitLines.at(i), lines.at(i), boost::is_any_of(" "), boost::token_compress_on); |
| 38 | + } |
| 39 | + return splitLines; |
| 40 | +} |
| 41 | + |
| 42 | +struct Mapping |
| 43 | +{ |
| 44 | + uintptr_t addressStart; |
| 45 | + uintptr_t addressEnd; |
| 46 | + std::string permissions; |
| 47 | + uintptr_t offset; |
| 48 | + std::string dev; |
| 49 | + size_t inode; |
| 50 | + std::string path; |
| 51 | +}; |
| 52 | + |
| 53 | +struct NumaMapping |
| 54 | +{ |
| 55 | + std::string path; |
| 56 | + size_t pageSizeKiB; |
| 57 | +}; |
| 58 | + |
| 59 | +std::vector<Mapping> getMaps() |
| 60 | +{ |
| 61 | + std::vector<Mapping> maps; |
| 62 | + auto procMaps = slurp("/proc/self/maps"); |
| 63 | + auto table = tablify(procMaps); |
| 64 | + |
| 65 | + for (const auto& row : table) { |
| 66 | + if (row.size() != 6) { |
| 67 | + continue; |
| 68 | + } |
| 69 | + |
| 70 | + Mapping mapping; |
| 71 | + std::vector<std::string> addressSplit; |
| 72 | + boost::split(addressSplit, row.at(0), boost::is_any_of("-"), boost::token_compress_on); |
| 73 | + mapping.addressStart = std::strtoul(addressSplit.at(0).c_str(), nullptr, 16); |
| 74 | + mapping.addressEnd = std::strtoul(addressSplit.at(1).c_str(), nullptr, 16); |
| 75 | + mapping.permissions = boost::trim_copy(row.at(1)); |
| 76 | + mapping.offset = std::strtoul(row.at(2).c_str(), nullptr, 16); |
| 77 | + mapping.dev = boost::trim_copy(row.at(3)); |
| 78 | + mapping.inode = boost::lexical_cast<size_t>(row.at(4)); |
| 79 | + mapping.path = boost::trim_copy(row.at(5)); |
| 80 | + maps.push_back(mapping); |
| 81 | + } |
19 | 82 |
|
20 | | - auto procMaps = executeCommand("cat /proc/self/maps"); |
21 | | - auto procNumaMaps = executeCommand("cat /proc/self/numa_maps"); |
| 83 | + return maps; |
| 84 | +} |
| 85 | + |
| 86 | +std::map<uintptr_t, NumaMapping> getNumaMaps() |
| 87 | +{ |
| 88 | + std::map<uintptr_t, NumaMapping> maps; |
| 89 | + auto numaMaps = slurp("/proc/self/numa_maps"); |
| 90 | + auto table = tablify(numaMaps); |
| 91 | + |
| 92 | + for (const auto& row : table) { |
| 93 | + auto address = std::strtoul(row.at(0).c_str(), nullptr, 16); |
22 | 94 |
|
23 | | - auto splitLines = [](std::string string) { |
24 | | - std::vector<std::string> lines; |
25 | | - boost::split(lines, string, boost::is_any_of("\n")); |
| 95 | + NumaMapping mapping; |
26 | 96 |
|
27 | | - std::vector<std::vector<std::string>> splitLines(lines.size()); |
28 | | - for (int i = 0; i < lines.size(); ++i) { |
29 | | - boost::split(splitLines.at(i), lines, boost::is_any_of(" ")); |
| 97 | + for (const auto& item : row) { |
| 98 | + auto setKeyValue = [&](std::string key, auto setFunction) { |
| 99 | + if (item.find(key) == 0) { |
| 100 | + setFunction(item.substr(key.size() + 1)); // Add 1 for the = |
| 101 | + } |
| 102 | + }; |
| 103 | + |
| 104 | + setKeyValue("file", [&](auto value){mapping.path = value;}); |
| 105 | + setKeyValue("kernelpagesize_kB", [&](auto value){mapping.pageSizeKiB = boost::lexical_cast<size_t>(value);}); |
| 106 | + |
| 107 | + if (item.find("huge") == 0) { |
| 108 | + mapping.pageSizeKiB = 2*1024; |
| 109 | + } |
30 | 110 | } |
31 | 111 |
|
32 | | - return splitLines; |
33 | | - }; |
| 112 | + maps[address] = mapping; |
| 113 | + } |
| 114 | + |
| 115 | + return maps; |
| 116 | +} |
| 117 | + |
| 118 | + |
| 119 | +} // Anonymous namespace |
| 120 | + |
| 121 | +std::vector<MemoryMap> getMemoryMaps() |
| 122 | +{ |
| 123 | + std::vector<MemoryMap> memoryMaps; |
34 | 124 |
|
35 | | - auto mapsTable = splitLines(procMaps); |
36 | | - auto numaMapsTable = splitLines(procNumaMaps); |
| 125 | + const auto maps = getMaps(); |
| 126 | + const auto numaMaps = getNumaMaps(); |
37 | 127 |
|
38 | | - for (int i = 0; i < mapsTable.size(); ++i) { |
39 | | - std::vector<std::string> memoryRange; |
40 | | - const auto& memoryRangeString = mapsTable.at(i).at(0); |
41 | | - boost::split(memoryRange, memoryRangeString, boost::is_any_of(" ")); |
| 128 | + for (const auto& map : maps) { |
| 129 | + MemoryMap memMap; |
| 130 | + memMap.addressStart = map.addressStart; |
| 131 | + memMap.addressEnd = map.addressEnd; |
| 132 | + memMap.path = map.path; |
| 133 | + if (numaMaps.count(map.addressStart)) { |
| 134 | + memMap.pageSizeKiB = numaMaps.at(map.addressStart).pageSizeKiB; |
| 135 | + } |
| 136 | + memoryMaps.push_back(memMap); |
42 | 137 | } |
43 | 138 |
|
44 | 139 | return memoryMaps; |
|
0 commit comments