Skip to content

Commit

Permalink
fix(profiler): support rare apps with multiple pids (#274)
Browse files Browse the repository at this point in the history
* fix(profiler): use first pid for app with multiple pids

* fix(profiler): add other pids tasks in cpu profiling

* fix(profiler): add other pids in ram profiling

* chore(profiler): generate binaries

* refactor(profiler): extract split method
  • Loading branch information
Almouro authored Apr 18, 2024
1 parent 1a5aa21 commit 60ea349
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 26 deletions.
Binary file not shown.
Binary file not shown.
Binary file modified packages/platforms/android/cpp-profiler/bin/BAMPerfProfiler-x86
Binary file not shown.
Binary file not shown.
59 changes: 34 additions & 25 deletions packages/platforms/android/cpp-profiler/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,40 +40,47 @@ class PidClosedError : public std::runtime_error
: std::runtime_error(message) {}
};

void printCpuStats(string pid)
void printCpuStats(std::vector<string> pids)
{
string path = "/proc/" + pid + "/task";

if (!fs::exists(path))
for (string pid : pids)
{
throw PidClosedError("Directory does not exist: " + path);
}
string path = "/proc/" + pid + "/task";

for (const auto &entry : fs::directory_iterator(path))
{
string subProcessPath = entry.path().string() + "/stat";
readFile(subProcessPath);
if (!fs::exists(path))
{
throw PidClosedError("Directory does not exist: " + path);
}

for (const auto &entry : fs::directory_iterator(path))
{
string subProcessPath = entry.path().string() + "/stat";
readFile(subProcessPath);
}
}
}

void printMemoryStats(string pid)
void printMemoryStats(std::vector<string> pids)
{
string memoryFilePath = "/proc/" + pid + "/statm";
readFile(memoryFilePath);
for (string pid : pids)
{
string memoryFilePath = "/proc/" + pid + "/statm";
readFile(memoryFilePath);
}
}

long long printPerformanceMeasure(string pid)
long long printPerformanceMeasure(std::vector<string> pids)
{
auto start = std::chrono::system_clock::now();

string separator = "=SEPARATOR=";
log("=START MEASURE=");
log(pid);
// Log the first pid as the main pid
log(pids[0]);
log(separator);
printCpuStats(pid);
printCpuStats(pids);
auto cpuEnd = std::chrono::system_clock::now();
log(separator);
printMemoryStats(pid);
printMemoryStats(pids);
auto memoryEnd = std::chrono::system_clock::now();
log(separator);
// TODO handle ATrace not available on OS
Expand All @@ -100,15 +107,15 @@ long long printPerformanceMeasure(string pid)
return totalDuration.count();
}

std::string pidOf(string bundleId)
std::vector<string> pidOf(string bundleId)
{
auto result = executeCommand("pidof " + bundleId);
return result.substr(0, result.find_first_of("\n"));
return split(result, ' ');
}

void pollPerformanceMeasures(std::string bundleId, int interval)
{
string pid = "";
std::vector<string> pids;

// We read atrace lines before the app is started
// since it can take a bit of time to start and clear the traceOutputPath
Expand All @@ -118,24 +125,24 @@ void pollPerformanceMeasures(std::string bundleId, int interval)

cout << "Waiting for process to start..." << endl;

while (pid == "")
while (pids.empty())
{
clearATraceLines();
pid = pidOf(bundleId);
pids = pidOf(bundleId);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}

try
{
while (true)
{
auto duration = printPerformanceMeasure(pid);
auto duration = printPerformanceMeasure(pids);
std::this_thread::sleep_for(std::chrono::milliseconds(interval - duration));
}
}
catch (const PidClosedError &e)
{
cerr << "CPP_ERROR_MAIN_PID_CLOSED " + pid << endl;
cerr << "CPP_ERROR_MAIN_PID_CLOSED " << e.what() << endl;
pollPerformanceMeasures(bundleId, interval);
return;
}
Expand Down Expand Up @@ -166,7 +173,9 @@ int main(int argc, char **argv)
}
else if (methodName == "printPerformanceMeasure")
{
printPerformanceMeasure(argv[2]);
std::vector<string> pids;
pids.push_back(argv[2]);
printPerformanceMeasure(pids);
}
else if (methodName == "printCpuClockTick")
{
Expand Down
20 changes: 20 additions & 0 deletions packages/platforms/android/cpp-profiler/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,23 @@ std::string executeCommand(std::string command)
}
return result;
}

std::vector<std::string> split(const std::string &str, char delimiter)
{
std::vector<std::string> result;
std::string currentResult = "";
for (char c : str)
{
if (c == delimiter || c == '\n')
{
result.push_back(currentResult);
currentResult = "";
}
else
{
currentResult += c;
}
}

return result;
}
1 change: 1 addition & 0 deletions packages/platforms/android/cpp-profiler/src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
void log(const std::string &msg);
void logTimestamp();
std::string executeCommand(std::string command);
std::vector<std::string> split(const std::string &str, char delimiter);

#endif /* UTILS_H */
8 changes: 7 additions & 1 deletion packages/platforms/android/src/commands/ram/pollRamUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ import { getRAMPageSize } from "../cppProfiler";
const BYTES_PER_MB = 1024 * 1024;

export const processOutput = (result: string) => {
return (parseInt(result.split(" ")[1], 10) * getRAMPageSize()) / BYTES_PER_MB;
const lines = result.split("\n");
let total = 0;

for (const line of lines) {
total += (parseInt(line.split(" ")[1], 10) * getRAMPageSize()) / BYTES_PER_MB;
}
return total;
};

0 comments on commit 60ea349

Please sign in to comment.