Fix high pkd CPU usage issue
Summary: Running `instruments -s devices` causes the `pkd` process in catalina to spike to ~100% for a few seconds. Flipper runs this command every 3 seconds to poll for devices. This switches it to use `idb list-targets` instead which is much more performant. Currently switched off in the open-source version while we make sure it's working well. If you set the GK value 'flipper_use_idb_to_list_devices' to true, then you'll get the new behaviour. Reviewed By: passy Differential Revision: D23102067 fbshipit-source-id: 9e17155d938a4fe326e082511f747444e4b533a2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
939b624dbb
commit
d423afd75d
@@ -24,14 +24,15 @@
|
|||||||
"emotion": "^10.0.23",
|
"emotion": "^10.0.23",
|
||||||
"expand-tilde": "^2.0.2",
|
"expand-tilde": "^2.0.2",
|
||||||
"flipper-client-sdk": "^0.0.2",
|
"flipper-client-sdk": "^0.0.2",
|
||||||
"flipper-plugin": "0.52.1",
|
|
||||||
"flipper-doctor": "0.52.1",
|
"flipper-doctor": "0.52.1",
|
||||||
|
"flipper-plugin": "0.52.1",
|
||||||
"flipper-plugin-lib": "0.52.1",
|
"flipper-plugin-lib": "0.52.1",
|
||||||
"fs-extra": "^8.0.1",
|
"fs-extra": "^8.0.1",
|
||||||
"immer": "^6.0.0",
|
"immer": "^6.0.0",
|
||||||
"immutable": "^4.0.0-rc.12",
|
"immutable": "^4.0.0-rc.12",
|
||||||
"invariant": "^2.2.2",
|
"invariant": "^2.2.2",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
|
"lodash.memoize": "^4.1.2",
|
||||||
"npm-api": "^1.0.0",
|
"npm-api": "^1.0.0",
|
||||||
"open": "^7.0.0",
|
"open": "^7.0.0",
|
||||||
"openssl-wrapper": "^0.3.4",
|
"openssl-wrapper": "^0.3.4",
|
||||||
@@ -69,8 +70,9 @@
|
|||||||
"7zip-bin-mac": "^1.0.1"
|
"7zip-bin-mac": "^1.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@testing-library/react": "^10.4.3",
|
|
||||||
"@testing-library/dom": "^7.20.2",
|
"@testing-library/dom": "^7.20.2",
|
||||||
|
"@testing-library/react": "^10.4.3",
|
||||||
|
"@types/lodash.memoize": "^4.1.6",
|
||||||
"flipper-test-utils": "0.52.1",
|
"flipper-test-utils": "0.52.1",
|
||||||
"metro": "^0.60.0",
|
"metro": "^0.60.0",
|
||||||
"mock-fs": "^4.12.0",
|
"mock-fs": "^4.12.0",
|
||||||
|
|||||||
@@ -81,9 +81,11 @@ async function queryDevices(store: Store, logger: Logger): Promise<any> {
|
|||||||
getActiveSimulators().then((devices) => {
|
getActiveSimulators().then((devices) => {
|
||||||
processDevices(store, logger, devices, 'emulator');
|
processDevices(store, logger, devices, 'emulator');
|
||||||
}),
|
}),
|
||||||
getActiveDevices().then((devices) => {
|
getActiveDevices(store.getState().settingsState.idbPath).then(
|
||||||
processDevices(store, logger, devices, 'physical');
|
(devices: IOSDeviceParams[]) => {
|
||||||
}),
|
processDevices(store, logger, devices, 'physical');
|
||||||
|
},
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,8 +175,8 @@ function getActiveSimulators(): Promise<Array<IOSDeviceParams>> {
|
|||||||
.catch((_) => []);
|
.catch((_) => []);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActiveDevices(): Promise<Array<IOSDeviceParams>> {
|
function getActiveDevices(idbPath: string): Promise<Array<IOSDeviceParams>> {
|
||||||
return iosUtil.targets().catch((e) => {
|
return iosUtil.targets(idbPath).catch((e) => {
|
||||||
console.error(e.message);
|
console.error(e.message);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
@@ -233,12 +235,12 @@ async function isXcodeDetected(): Promise<boolean> {
|
|||||||
.catch((_) => false);
|
.catch((_) => false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActiveDevicesAndSimulators(): Promise<
|
export async function getActiveDevicesAndSimulators(
|
||||||
Array<IOSDevice>
|
store: Store,
|
||||||
> {
|
): Promise<Array<IOSDevice>> {
|
||||||
const activeDevices: Array<Array<IOSDeviceParams>> = await Promise.all([
|
const activeDevices: Array<Array<IOSDeviceParams>> = await Promise.all([
|
||||||
getActiveSimulators(),
|
getActiveSimulators(),
|
||||||
getActiveDevices(),
|
getActiveDevices(store.getState().settingsState.idbPath),
|
||||||
]);
|
]);
|
||||||
const allDevices = activeDevices[0].concat(activeDevices[1]);
|
const allDevices = activeDevices[0].concat(activeDevices[1]);
|
||||||
return allDevices.map((device) => {
|
return allDevices.map((device) => {
|
||||||
|
|||||||
@@ -342,28 +342,30 @@ export default class CertificateProvider {
|
|||||||
// It's a simulator, the deviceId is in the filepath.
|
// It's a simulator, the deviceId is in the filepath.
|
||||||
return Promise.resolve(matches[1]);
|
return Promise.resolve(matches[1]);
|
||||||
}
|
}
|
||||||
return iosUtil.targets().then((targets) => {
|
return iosUtil
|
||||||
if (targets.length === 0) {
|
.targets(this.store.getState().settingsState.idbPath)
|
||||||
throw new Error('No iOS devices found');
|
.then((targets) => {
|
||||||
}
|
if (targets.length === 0) {
|
||||||
const deviceMatchList = targets.map((target) =>
|
throw new Error('No iOS devices found');
|
||||||
this.iOSDeviceHasMatchingCSR(
|
|
||||||
deviceCsrFilePath,
|
|
||||||
target.udid,
|
|
||||||
appName,
|
|
||||||
csr,
|
|
||||||
).then((isMatch) => {
|
|
||||||
return {id: target.udid, isMatch};
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
return Promise.all(deviceMatchList).then((devices) => {
|
|
||||||
const matchingIds = devices.filter((m) => m.isMatch).map((m) => m.id);
|
|
||||||
if (matchingIds.length == 0) {
|
|
||||||
throw new Error(`No matching device found for app: ${appName}`);
|
|
||||||
}
|
}
|
||||||
return matchingIds[0];
|
const deviceMatchList = targets.map((target) =>
|
||||||
|
this.iOSDeviceHasMatchingCSR(
|
||||||
|
deviceCsrFilePath,
|
||||||
|
target.udid,
|
||||||
|
appName,
|
||||||
|
csr,
|
||||||
|
).then((isMatch) => {
|
||||||
|
return {id: target.udid, isMatch};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return Promise.all(deviceMatchList).then((devices) => {
|
||||||
|
const matchingIds = devices.filter((m) => m.isMatch).map((m) => m.id);
|
||||||
|
if (matchingIds.length == 0) {
|
||||||
|
throw new Error(`No matching device found for app: ${appName}`);
|
||||||
|
}
|
||||||
|
return matchingIds[0];
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
androidDeviceHasMatchingCSR(
|
androidDeviceHasMatchingCSR(
|
||||||
|
|||||||
@@ -10,11 +10,13 @@
|
|||||||
import child_process from 'child_process';
|
import child_process from 'child_process';
|
||||||
import {promisify} from 'util';
|
import {promisify} from 'util';
|
||||||
import {Mutex} from 'async-mutex';
|
import {Mutex} from 'async-mutex';
|
||||||
import {notNull} from './typeUtils';
|
|
||||||
const unsafeExec = promisify(child_process.exec);
|
const unsafeExec = promisify(child_process.exec);
|
||||||
import {killOrphanedInstrumentsProcesses} from './processCleanup';
|
import {killOrphanedInstrumentsProcesses} from './processCleanup';
|
||||||
import {reportPlatformFailures} from './metrics';
|
import {reportPlatformFailures} from './metrics';
|
||||||
import {promises, constants} from 'fs';
|
import {promises, constants} from 'fs';
|
||||||
|
import memoize from 'lodash.memoize';
|
||||||
|
import GK from '../fb-stubs/GK';
|
||||||
|
import {notNull} from './typeUtils';
|
||||||
|
|
||||||
// Use debug to get helpful logs when idb fails
|
// Use debug to get helpful logs when idb fails
|
||||||
const idbLogLevel = 'DEBUG';
|
const idbLogLevel = 'DEBUG';
|
||||||
@@ -22,6 +24,15 @@ const operationPrefix = 'iosContainerUtility';
|
|||||||
|
|
||||||
const mutex = new Mutex();
|
const mutex = new Mutex();
|
||||||
|
|
||||||
|
type IdbTarget = {
|
||||||
|
name: string;
|
||||||
|
udid: string;
|
||||||
|
state: string;
|
||||||
|
type: string;
|
||||||
|
os_version: string;
|
||||||
|
architecture: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type DeviceTarget = {
|
export type DeviceTarget = {
|
||||||
udid: string;
|
udid: string;
|
||||||
type: 'physical' | 'emulator';
|
type: 'physical' | 'emulator';
|
||||||
@@ -44,23 +55,38 @@ function safeExec(command: string): Promise<{stdout: string; stderr: string}> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function targets(): Promise<Array<DeviceTarget>> {
|
async function targets(idbPath: string): Promise<Array<DeviceTarget>> {
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
await killOrphanedInstrumentsProcesses();
|
if (GK.get('flipper_use_idb_to_list_devices')) {
|
||||||
return safeExec('instruments -s devices').then(({stdout}) =>
|
await memoize(checkIdbIsInstalled)(idbPath);
|
||||||
stdout
|
return safeExec(`${idbPath} list-targets --json`).then(({stdout}) =>
|
||||||
.toString()
|
stdout
|
||||||
.split('\n')
|
.toString()
|
||||||
.map((line) => line.trim())
|
.split('\n')
|
||||||
.map((line) => /(.+) \([^(]+\) \[(.*)\]( \(Simulator\))?/.exec(line))
|
.map((line) => line.trim())
|
||||||
.filter(notNull)
|
.map((line) => JSON.parse(line))
|
||||||
.filter(([_match, _name, _udid, isSim]) => !isSim)
|
.filter(({type}: IdbTarget) => type !== 'simulator')
|
||||||
.map(([_match, name, udid]) => {
|
.map((target: IdbTarget) => {
|
||||||
return {udid: udid, type: 'physical', name: name};
|
return {udid: target.udid, type: 'physical', name: target.name};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
await killOrphanedInstrumentsProcesses();
|
||||||
|
return safeExec('instruments -s devices').then(({stdout}) =>
|
||||||
|
stdout
|
||||||
|
.toString()
|
||||||
|
.split('\n')
|
||||||
|
.map((line) => line.trim())
|
||||||
|
.map((line) => /(.+) \([^(]+\) \[(.*)\]( \(Simulator\))?/.exec(line))
|
||||||
|
.filter(notNull)
|
||||||
|
.filter(([_match, _name, _udid, isSim]) => !isSim)
|
||||||
|
.map(([_match, name, udid]) => {
|
||||||
|
return {udid: udid, type: 'physical', name: name};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function push(
|
async function push(
|
||||||
@@ -70,7 +96,7 @@ async function push(
|
|||||||
dst: string,
|
dst: string,
|
||||||
idbPath: string,
|
idbPath: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await checkIdbIsInstalled(idbPath);
|
await memoize(checkIdbIsInstalled)(idbPath);
|
||||||
return wrapWithErrorMessage(
|
return wrapWithErrorMessage(
|
||||||
reportPlatformFailures(
|
reportPlatformFailures(
|
||||||
safeExec(
|
safeExec(
|
||||||
@@ -92,7 +118,7 @@ async function pull(
|
|||||||
dst: string,
|
dst: string,
|
||||||
idbPath: string,
|
idbPath: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await checkIdbIsInstalled(idbPath);
|
await memoize(checkIdbIsInstalled)(idbPath);
|
||||||
return wrapWithErrorMessage(
|
return wrapWithErrorMessage(
|
||||||
reportPlatformFailures(
|
reportPlatformFailures(
|
||||||
safeExec(
|
safeExec(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export async function listDevices(store: Store): Promise<Array<BaseDevice>> {
|
|||||||
: [];
|
: [];
|
||||||
const iOSDevices: BaseDevice[] = state.application
|
const iOSDevices: BaseDevice[] = state.application
|
||||||
.xcodeCommandLineToolsDetected
|
.xcodeCommandLineToolsDetected
|
||||||
? await getActiveDevicesAndSimulators()
|
? await getActiveDevicesAndSimulators(store)
|
||||||
: [];
|
: [];
|
||||||
return [...androidDevices, ...iOSDevices];
|
return [...androidDevices, ...iOSDevices];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2136,6 +2136,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/lodash" "*"
|
"@types/lodash" "*"
|
||||||
|
|
||||||
|
"@types/lodash.memoize@^4.1.6":
|
||||||
|
version "4.1.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash.memoize/-/lodash.memoize-4.1.6.tgz#3221f981790a415cab1a239f25c17efd8b604c23"
|
||||||
|
integrity sha512-mYxjKiKzRadRJVClLKxS4wb3Iy9kzwJ1CkbyKiadVxejnswnRByyofmPMscFKscmYpl36BEEhCMPuWhA1R/1ZQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/lodash" "*"
|
||||||
|
|
||||||
"@types/lodash@*", "@types/lodash@^4.14.150":
|
"@types/lodash@*", "@types/lodash@^4.14.150":
|
||||||
version "4.14.157"
|
version "4.14.157"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.157.tgz#fdac1c52448861dfde1a2e1515dbc46e54926dc8"
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.157.tgz#fdac1c52448861dfde1a2e1515dbc46e54926dc8"
|
||||||
|
|||||||
Reference in New Issue
Block a user