Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(profiler): support rare apps with multiple pids #274

Merged
merged 5 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
};