Skip to content

Commit 7d5f248

Browse files
committed
fix: dedupe iOS perf samples by pid
1 parent dfebcb5 commit 7d5f248

2 files changed

Lines changed: 54 additions & 9 deletions

File tree

src/platforms/ios/__tests__/perf.test.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,26 @@ test('sampleApplePerfMetrics uses xctrace Activity Monitor for iOS devices', asy
263263
'</node>',
264264
'</trace-query-result>',
265265
].join('');
266-
const secondCaptureXml = firstCaptureXml.replace(
267-
'<duration-on-core fmt="100.00 ms">100000000</duration-on-core>',
268-
'<duration-on-core fmt="350.00 ms">350000000</duration-on-core>',
269-
);
266+
const secondCaptureXml = firstCaptureXml
267+
.replace(
268+
'<duration-on-core fmt="100.00 ms">100000000</duration-on-core>',
269+
'<duration-on-core fmt="350.00 ms">350000000</duration-on-core>',
270+
)
271+
.replace(
272+
'</row><row><start-time fmt="00:00.124">124</start-time>',
273+
[
274+
'</row>',
275+
'<row>',
276+
'<start-time fmt="00:00.123">123</start-time>',
277+
'<process fmt="ExampleDeviceApp (4001)"><pid fmt="4001">4001</pid></process>',
278+
'<duration-on-core fmt="350.00 ms">350000000</duration-on-core>',
279+
'<size-in-bytes fmt="8.00 MiB">8388608</size-in-bytes>',
280+
'<pid fmt="4001">4001</pid>',
281+
'</row>',
282+
'<row>',
283+
'<start-time fmt="00:00.124">124</start-time>',
284+
].join(''),
285+
);
270286
let exportCount = 0;
271287

272288
mockRunCmd.mockImplementation(async (cmd, args) => {

src/platforms/ios/perf.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -449,10 +449,29 @@ function summarizeIosDevicePerfSnapshot(
449449
});
450450
}
451451

452-
const cpuTimeValues = matchedSamples
452+
const latestSamplesByPid = new Map<number, IosDevicePerfProcessSample>();
453+
for (const sample of matchedSamples) {
454+
const previous = latestSamplesByPid.get(sample.pid);
455+
if (!previous) {
456+
latestSamplesByPid.set(sample.pid, sample);
457+
continue;
458+
}
459+
latestSamplesByPid.set(sample.pid, {
460+
pid: sample.pid,
461+
processName: sample.processName || previous.processName,
462+
cpuTimeNs: maxNullableNumber(previous.cpuTimeNs, sample.cpuTimeNs),
463+
residentMemoryBytes: maxNullableNumber(
464+
previous.residentMemoryBytes,
465+
sample.residentMemoryBytes,
466+
),
467+
});
468+
}
469+
470+
const latestSamples = [...latestSamplesByPid.values()];
471+
const cpuTimeValues = latestSamples
453472
.map((sample) => sample.cpuTimeNs)
454473
.filter((value): value is number => value !== null);
455-
const residentMemoryValues = matchedSamples
474+
const residentMemoryValues = latestSamples
456475
.map((sample) => sample.residentMemoryBytes)
457476
.filter((value): value is number => value !== null);
458477
return {
@@ -462,7 +481,7 @@ function summarizeIosDevicePerfSnapshot(
462481
residentMemoryValues.length > 0
463482
? residentMemoryValues.reduce((total, value) => total + value, 0)
464483
: null,
465-
matchedProcesses: uniqueStrings(matchedSamples.map((sample) => sample.processName)),
484+
matchedProcesses: uniqueStrings(latestSamples.map((sample) => sample.processName)),
466485
};
467486
}
468487

@@ -704,8 +723,12 @@ function resolveProcessName(
704723
}
705724

706725
function readXmlAttribute(openTag: string, attribute: string): string | undefined {
707-
const match = openTag.match(new RegExp(`\\b${attribute}="([^"]+)"`));
708-
return match?.[1];
726+
for (const match of openTag.matchAll(/\b([^\s=/>]+)="([^"]*)"/g)) {
727+
if (match[1] === attribute) {
728+
return match[2];
729+
}
730+
}
731+
return undefined;
709732
}
710733

711734
function resolveIosDevicePerfHint(stdout: string, stderr: string): string {
@@ -724,3 +747,9 @@ function resolveIosDevicePerfHint(stdout: string, stderr: string): string {
724747
function roundPercent(value: number): number {
725748
return Math.round(value * 10) / 10;
726749
}
750+
751+
function maxNullableNumber(left: number | null, right: number | null): number | null {
752+
if (left === null) return right;
753+
if (right === null) return left;
754+
return Math.max(left, right);
755+
}

0 commit comments

Comments
 (0)