Skip to content

Commit 60ea349

Browse files
authored
fix(profiler): support rare apps with multiple pids (#274)
* 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
1 parent 1a5aa21 commit 60ea349

File tree

8 files changed

+62
-26
lines changed

8 files changed

+62
-26
lines changed
Binary file not shown.
Binary file not shown.
135 KB
Binary file not shown.
Binary file not shown.

packages/platforms/android/cpp-profiler/src/main.cpp

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,40 +40,47 @@ class PidClosedError : public std::runtime_error
4040
: std::runtime_error(message) {}
4141
};
4242

43-
void printCpuStats(string pid)
43+
void printCpuStats(std::vector<string> pids)
4444
{
45-
string path = "/proc/" + pid + "/task";
46-
47-
if (!fs::exists(path))
45+
for (string pid : pids)
4846
{
49-
throw PidClosedError("Directory does not exist: " + path);
50-
}
47+
string path = "/proc/" + pid + "/task";
5148

52-
for (const auto &entry : fs::directory_iterator(path))
53-
{
54-
string subProcessPath = entry.path().string() + "/stat";
55-
readFile(subProcessPath);
49+
if (!fs::exists(path))
50+
{
51+
throw PidClosedError("Directory does not exist: " + path);
52+
}
53+
54+
for (const auto &entry : fs::directory_iterator(path))
55+
{
56+
string subProcessPath = entry.path().string() + "/stat";
57+
readFile(subProcessPath);
58+
}
5659
}
5760
}
5861

59-
void printMemoryStats(string pid)
62+
void printMemoryStats(std::vector<string> pids)
6063
{
61-
string memoryFilePath = "/proc/" + pid + "/statm";
62-
readFile(memoryFilePath);
64+
for (string pid : pids)
65+
{
66+
string memoryFilePath = "/proc/" + pid + "/statm";
67+
readFile(memoryFilePath);
68+
}
6369
}
6470

65-
long long printPerformanceMeasure(string pid)
71+
long long printPerformanceMeasure(std::vector<string> pids)
6672
{
6773
auto start = std::chrono::system_clock::now();
6874

6975
string separator = "=SEPARATOR=";
7076
log("=START MEASURE=");
71-
log(pid);
77+
// Log the first pid as the main pid
78+
log(pids[0]);
7279
log(separator);
73-
printCpuStats(pid);
80+
printCpuStats(pids);
7481
auto cpuEnd = std::chrono::system_clock::now();
7582
log(separator);
76-
printMemoryStats(pid);
83+
printMemoryStats(pids);
7784
auto memoryEnd = std::chrono::system_clock::now();
7885
log(separator);
7986
// TODO handle ATrace not available on OS
@@ -100,15 +107,15 @@ long long printPerformanceMeasure(string pid)
100107
return totalDuration.count();
101108
}
102109

103-
std::string pidOf(string bundleId)
110+
std::vector<string> pidOf(string bundleId)
104111
{
105112
auto result = executeCommand("pidof " + bundleId);
106-
return result.substr(0, result.find_first_of("\n"));
113+
return split(result, ' ');
107114
}
108115

109116
void pollPerformanceMeasures(std::string bundleId, int interval)
110117
{
111-
string pid = "";
118+
std::vector<string> pids;
112119

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

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

121-
while (pid == "")
128+
while (pids.empty())
122129
{
123130
clearATraceLines();
124-
pid = pidOf(bundleId);
131+
pids = pidOf(bundleId);
125132
std::this_thread::sleep_for(std::chrono::milliseconds(50));
126133
}
127134

128135
try
129136
{
130137
while (true)
131138
{
132-
auto duration = printPerformanceMeasure(pid);
139+
auto duration = printPerformanceMeasure(pids);
133140
std::this_thread::sleep_for(std::chrono::milliseconds(interval - duration));
134141
}
135142
}
136143
catch (const PidClosedError &e)
137144
{
138-
cerr << "CPP_ERROR_MAIN_PID_CLOSED " + pid << endl;
145+
cerr << "CPP_ERROR_MAIN_PID_CLOSED " << e.what() << endl;
139146
pollPerformanceMeasures(bundleId, interval);
140147
return;
141148
}
@@ -166,7 +173,9 @@ int main(int argc, char **argv)
166173
}
167174
else if (methodName == "printPerformanceMeasure")
168175
{
169-
printPerformanceMeasure(argv[2]);
176+
std::vector<string> pids;
177+
pids.push_back(argv[2]);
178+
printPerformanceMeasure(pids);
170179
}
171180
else if (methodName == "printCpuClockTick")
172181
{

packages/platforms/android/cpp-profiler/src/utils.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,23 @@ std::string executeCommand(std::string command)
3737
}
3838
return result;
3939
}
40+
41+
std::vector<std::string> split(const std::string &str, char delimiter)
42+
{
43+
std::vector<std::string> result;
44+
std::string currentResult = "";
45+
for (char c : str)
46+
{
47+
if (c == delimiter || c == '\n')
48+
{
49+
result.push_back(currentResult);
50+
currentResult = "";
51+
}
52+
else
53+
{
54+
currentResult += c;
55+
}
56+
}
57+
58+
return result;
59+
}

packages/platforms/android/cpp-profiler/src/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
void log(const std::string &msg);
77
void logTimestamp();
88
std::string executeCommand(std::string command);
9+
std::vector<std::string> split(const std::string &str, char delimiter);
910

1011
#endif /* UTILS_H */

packages/platforms/android/src/commands/ram/pollRamUsage.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,11 @@ import { getRAMPageSize } from "../cppProfiler";
33
const BYTES_PER_MB = 1024 * 1024;
44

55
export const processOutput = (result: string) => {
6-
return (parseInt(result.split(" ")[1], 10) * getRAMPageSize()) / BYTES_PER_MB;
6+
const lines = result.split("\n");
7+
let total = 0;
8+
9+
for (const line of lines) {
10+
total += (parseInt(line.split(" ")[1], 10) * getRAMPageSize()) / BYTES_PER_MB;
11+
}
12+
return total;
713
};

0 commit comments

Comments
 (0)