mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 02:02:42 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
802359152e |
@@ -0,0 +1,21 @@
|
|||||||
|
# Android workspace memory diagnostic
|
||||||
|
|
||||||
|
Supplemental reproduction for [#4408](https://github.com/getpaseo/paseo/issues/4408), using the production 0.11.2 APK on an Android 16 emulator. This tests an adapted failure: opening the sidebar with 800 projects, each containing one workspace, produced a `LOW_MEMORY` exit after 66–90 seconds. It does not reproduce the reported 18-second cold-start ANR or establish its cause.
|
||||||
|
|
||||||
|
Before running:
|
||||||
|
|
||||||
|
- Use a dedicated emulator with the production APK installed and notifications permission settled. Bind the agent-device session to that emulator before running.
|
||||||
|
- Pair the app with an isolated daemon containing 800 active workspaces, each in its own project. Use Project grouping and leave projects expanded. The observed fixture used existing directories inside a Git checkout, with workspace titles permuted by `(index * 317) % 800`, no agents, and no terminals.
|
||||||
|
- Record the daemon revision, emulator RAM and Java heap settings, and the project/workspace distribution. Device memory pressure controls whether Android kills the app.
|
||||||
|
|
||||||
|
Run from the repository root with the agent-device session, Android serial, and an artifact directory:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
node packages/app/e2e/mobile/workspace-memory/android.mjs workspace-memory emulator-5556 .dev/workspace-memory
|
||||||
|
```
|
||||||
|
|
||||||
|
The test cold-starts the paired app, opens its sidebar, samples memory and the process ID every five seconds for two minutes, and verifies that closing the sidebar responds. A process exit or restart fails the assertion. Memory, exit records, and logs stay in the supplied artifact directory.
|
||||||
|
|
||||||
|
Control: repeat with 800 workspaces grouped into one project. That distribution survived the two-minute automated check and responded to closing the sidebar, with total PSS near 300 MB. The project-per-workspace fixture reached about 2.5 GB PSS before Android recorded `LOW_MEMORY`; its Java heap rose and fell rather than showing the reporter's full-heap ANR. Neither result proves that shared collators would fix the report.
|
||||||
|
|
||||||
|
This diagnostic is deliberately outside CI and contains no production change.
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
// Requires a paired production app and the workspace fixture described in README.md.
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { execFileSync } from "node:child_process";
|
||||||
|
import { mkdirSync, writeFileSync } from "node:fs";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { setTimeout as delay } from "node:timers/promises";
|
||||||
|
|
||||||
|
const [, , session, serial, artifacts] = process.argv;
|
||||||
|
assert(session && serial && artifacts, "Pass session, Android serial, and artifact directory");
|
||||||
|
mkdirSync(artifacts, { recursive: true });
|
||||||
|
|
||||||
|
function ad(...args) {
|
||||||
|
return execFileSync("agent-device", [...args, "--session", session], {
|
||||||
|
encoding: "utf8",
|
||||||
|
timeout: 60_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function adb(...args) {
|
||||||
|
return execFileSync("adb", ["-s", serial, ...args], {
|
||||||
|
encoding: "utf8",
|
||||||
|
timeout: 15_000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function pid() {
|
||||||
|
try {
|
||||||
|
return adb("shell", "pidof", "sh.paseo").trim();
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ad("open", "sh.paseo", "--relaunch", "--platform", "android");
|
||||||
|
ad("wait", "text", "Open menu", "15000");
|
||||||
|
assert.equal(
|
||||||
|
JSON.parse(ad("perf", "memory", "sample", "--json")).data.deviceId,
|
||||||
|
serial,
|
||||||
|
"Session and adb serial must address the same device",
|
||||||
|
);
|
||||||
|
const initialPid = pid();
|
||||||
|
assert(initialPid, "App must have a process before opening the sidebar");
|
||||||
|
ad("press", 'label="Open menu"', "--settle");
|
||||||
|
const startedAt = Date.now();
|
||||||
|
const samples = [];
|
||||||
|
try {
|
||||||
|
while (Date.now() - startedAt < 120_000) {
|
||||||
|
const currentPid = pid();
|
||||||
|
samples.push({
|
||||||
|
elapsedMs: Date.now() - startedAt,
|
||||||
|
pid: currentPid,
|
||||||
|
meminfo: currentPid ? adb("shell", "dumpsys", "meminfo", "sh.paseo") : "",
|
||||||
|
});
|
||||||
|
writeFileSync(join(artifacts, "samples.json"), JSON.stringify(samples, null, 2));
|
||||||
|
assert.equal(currentPid, initialPid, "Opening the workspace sidebar must keep the app alive");
|
||||||
|
await delay(5_000);
|
||||||
|
}
|
||||||
|
ad("press", 'label="Close sidebar"', "--settle");
|
||||||
|
ad("wait", "text", "Open menu", "10000");
|
||||||
|
console.log("PASS: app survived two minutes with the sidebar open and responded to Close");
|
||||||
|
} finally {
|
||||||
|
writeFileSync(
|
||||||
|
join(artifacts, "exit-info.txt"),
|
||||||
|
adb("shell", "dumpsys", "activity", "exit-info", "sh.paseo"),
|
||||||
|
);
|
||||||
|
writeFileSync(join(artifacts, "logcat.txt"), adb("logcat", "-d", "-t", "4000"));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user