flipper CPU plugin sidebar
Summary: Add sidebar to the flipper CPU plugin. Sidebar displays detailed information about the selected CPU core Differential Revision: D15696198 fbshipit-source-id: 47e687b4354653e6bef626cd3f27adcb219dbd28
This commit is contained in:
committed by
Facebook Github Bot
parent
6792fb0bea
commit
c225795b73
@@ -16,6 +16,9 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
ManagedTable,
|
ManagedTable,
|
||||||
colors,
|
colors,
|
||||||
|
styled,
|
||||||
|
Panel,
|
||||||
|
DetailSidebar,
|
||||||
} from 'flipper';
|
} from 'flipper';
|
||||||
|
|
||||||
type ADBClient = any;
|
type ADBClient = any;
|
||||||
@@ -30,6 +33,9 @@ type CPUFrequency = {|
|
|||||||
scaling_cur_freq: number,
|
scaling_cur_freq: number,
|
||||||
scaling_min_freq: number,
|
scaling_min_freq: number,
|
||||||
scaling_max_freq: number,
|
scaling_max_freq: number,
|
||||||
|
scaling_available_freqs: Array<number>,
|
||||||
|
scaling_governor: string,
|
||||||
|
scaling_available_governors: Array<string>,
|
||||||
cpuinfo_max_freq: number,
|
cpuinfo_max_freq: number,
|
||||||
cpuinfo_min_freq: number,
|
cpuinfo_min_freq: number,
|
||||||
|};
|
|};
|
||||||
@@ -39,6 +45,7 @@ type CPUState = {|
|
|||||||
cpuCount: number,
|
cpuCount: number,
|
||||||
monitoring: boolean,
|
monitoring: boolean,
|
||||||
hardwareInfo: string,
|
hardwareInfo: string,
|
||||||
|
selectedIds: Array<number>,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
type ShellCallBack = (output: string) => void;
|
type ShellCallBack = (output: string) => void;
|
||||||
@@ -77,8 +84,22 @@ const Columns = {
|
|||||||
value: 'MAX Frequency',
|
value: 'MAX Frequency',
|
||||||
resizable: true,
|
resizable: true,
|
||||||
},
|
},
|
||||||
|
scaling_governor: {
|
||||||
|
value: 'Scaling Governor',
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Heading = styled('div')({
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 13,
|
||||||
|
display: 'block',
|
||||||
|
marginBottom: 10,
|
||||||
|
'&:not(:first-child)': {
|
||||||
|
marginTop: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// check if str is a number
|
// check if str is a number
|
||||||
function isNormalInteger(str) {
|
function isNormalInteger(str) {
|
||||||
let n = Math.floor(Number(str));
|
let n = Math.floor(Number(str));
|
||||||
@@ -107,6 +128,7 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
cpuCount: 0,
|
cpuCount: 0,
|
||||||
monitoring: false,
|
monitoring: false,
|
||||||
hardwareInfo: '',
|
hardwareInfo: '',
|
||||||
|
selectedIds: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
static supportsDevice(device: Device) {
|
static supportsDevice(device: Device) {
|
||||||
@@ -132,6 +154,9 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
scaling_max_freq: -1,
|
scaling_max_freq: -1,
|
||||||
cpuinfo_min_freq: -1,
|
cpuinfo_min_freq: -1,
|
||||||
cpuinfo_max_freq: -1,
|
cpuinfo_max_freq: -1,
|
||||||
|
scaling_available_freqs: [],
|
||||||
|
scaling_governor: 'N/A',
|
||||||
|
scaling_available_governors: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -170,6 +195,44 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
}, 'cat /sys/devices/system/cpu/cpu' + core + '/cpufreq/' + type);
|
}, 'cat /sys/devices/system/cpu/cpu' + core + '/cpufreq/' + type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateAvailableFrequencies = (core: number) => {
|
||||||
|
this.executeShell((output: string) => {
|
||||||
|
let cpuFreq = this.state.cpuFreq;
|
||||||
|
let freqs = output.split(' ').map((num: string) => {
|
||||||
|
return parseInt(num, 10);
|
||||||
|
});
|
||||||
|
cpuFreq[core].scaling_available_freqs = freqs;
|
||||||
|
let maxFreq = cpuFreq[core].scaling_max_freq;
|
||||||
|
if (maxFreq > 0 && freqs.indexOf(maxFreq) == -1) {
|
||||||
|
freqs.push(maxFreq); // always add scaling max to available frequencies
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
cpuFreq: cpuFreq,
|
||||||
|
});
|
||||||
|
}, 'cat /sys/devices/system/cpu/cpu' + core + '/cpufreq/scaling_available_frequencies');
|
||||||
|
};
|
||||||
|
|
||||||
|
updateCoreGovernor = (core: number) => {
|
||||||
|
this.executeShell((output: string) => {
|
||||||
|
let cpuFreq = this.state.cpuFreq;
|
||||||
|
cpuFreq[core].scaling_governor = output;
|
||||||
|
this.setState({
|
||||||
|
cpuFreq: cpuFreq,
|
||||||
|
});
|
||||||
|
}, 'cat /sys/devices/system/cpu/cpu' + core + '/cpufreq/scaling_governor');
|
||||||
|
};
|
||||||
|
|
||||||
|
readAvailableGovernors = (core: number) => {
|
||||||
|
this.executeShell((output: string) => {
|
||||||
|
let cpuFreq = this.state.cpuFreq;
|
||||||
|
cpuFreq[core].scaling_available_governors = output.split(' ');
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
cpuFreq: cpuFreq,
|
||||||
|
});
|
||||||
|
}, 'cat /sys/devices/system/cpu/cpu' + core + '/cpufreq/scaling_available_governors');
|
||||||
|
};
|
||||||
|
|
||||||
readCoreFrequency = (core: number) => {
|
readCoreFrequency = (core: number) => {
|
||||||
let freq = this.state.cpuFreq[core];
|
let freq = this.state.cpuFreq[core];
|
||||||
if (freq.cpuinfo_max_freq < 0) {
|
if (freq.cpuinfo_max_freq < 0) {
|
||||||
@@ -222,10 +285,15 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
if (this.intervalID) {
|
if (this.intervalID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
for (let i = 0; i < this.state.cpuCount; ++i) {
|
||||||
|
this.readAvailableGovernors(i);
|
||||||
|
}
|
||||||
|
|
||||||
this.intervalID = setInterval(() => {
|
this.intervalID = setInterval(() => {
|
||||||
for (let i = 0; i < this.state.cpuCount; ++i) {
|
for (let i = 0; i < this.state.cpuCount; ++i) {
|
||||||
this.readCoreFrequency(i);
|
this.readCoreFrequency(i);
|
||||||
|
this.updateCoreGovernor(i);
|
||||||
|
this.updateAvailableFrequencies(i); // scaling max might change, so we also update this
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
@@ -253,6 +321,8 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
cpuFreq[i].scaling_cur_freq = -1;
|
cpuFreq[i].scaling_cur_freq = -1;
|
||||||
cpuFreq[i].scaling_min_freq = -1;
|
cpuFreq[i].scaling_min_freq = -1;
|
||||||
cpuFreq[i].scaling_max_freq = -1;
|
cpuFreq[i].scaling_max_freq = -1;
|
||||||
|
cpuFreq[i].scaling_available_freqs = [];
|
||||||
|
cpuFreq[i].scaling_governor = 'N/A';
|
||||||
// we don't cleanup cpuinfo_min_freq, cpuinfo_max_freq
|
// we don't cleanup cpuinfo_min_freq, cpuinfo_max_freq
|
||||||
// because usually they are fixed (hardware)
|
// because usually they are fixed (hardware)
|
||||||
}
|
}
|
||||||
@@ -265,7 +335,8 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
this.cleanup();
|
this.cleanup();
|
||||||
};
|
};
|
||||||
|
|
||||||
buildRow = (freq: CPUFrequency) => {
|
buildRow = (freq: CPUFrequency, idx: number) => {
|
||||||
|
let selected = this.state.selectedIds.indexOf(idx) >= 0;
|
||||||
let style = {};
|
let style = {};
|
||||||
if (freq.scaling_cur_freq == -2) {
|
if (freq.scaling_cur_freq == -2) {
|
||||||
style = {
|
style = {
|
||||||
@@ -282,7 +353,8 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
) {
|
) {
|
||||||
style = {
|
style = {
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: colors.redTint,
|
backgroundColor: selected ? colors.red : colors.redTint,
|
||||||
|
// better visibility when highlighted
|
||||||
color: colors.red,
|
color: colors.red,
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
},
|
},
|
||||||
@@ -319,18 +391,133 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
cpuinfo_max_freq: {
|
cpuinfo_max_freq: {
|
||||||
value: <Text>{formatFrequency(freq.cpuinfo_max_freq)}</Text>,
|
value: <Text>{formatFrequency(freq.cpuinfo_max_freq)}</Text>,
|
||||||
},
|
},
|
||||||
|
scaling_governor: {
|
||||||
|
value: <Text>{freq.scaling_governor}</Text>,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
key: freq.cpu_id,
|
key: freq.cpu_id,
|
||||||
|
|
||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
frequencyRows = (cpuFreqs: Array<CPUFrequency>): TableRows => {
|
frequencyRows = (cpuFreqs: Array<CPUFrequency>): TableRows => {
|
||||||
let rows = [];
|
return cpuFreqs.map(this.buildRow);
|
||||||
for (const cpuFreq of cpuFreqs) {
|
};
|
||||||
rows.push(this.buildRow(cpuFreq));
|
|
||||||
|
buildAvailableFreqList = (freq: CPUFrequency) => {
|
||||||
|
if (freq.scaling_available_freqs.length == 0) {
|
||||||
|
return <Text>N/A</Text>;
|
||||||
}
|
}
|
||||||
return rows;
|
let info = freq;
|
||||||
|
return (
|
||||||
|
<Text>
|
||||||
|
{freq.scaling_available_freqs.map((freq, idx) => {
|
||||||
|
let style = {};
|
||||||
|
if (
|
||||||
|
freq == info.scaling_cur_freq ||
|
||||||
|
freq == info.scaling_min_freq ||
|
||||||
|
freq == info.scaling_max_freq
|
||||||
|
) {
|
||||||
|
style.fontWeight = 'bold';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Text key={idx} style={style}>
|
||||||
|
{formatFrequency(freq)}
|
||||||
|
{freq == info.scaling_cur_freq && (
|
||||||
|
<Text style={style}> (scaling current)</Text>
|
||||||
|
)}
|
||||||
|
{freq == info.scaling_min_freq && (
|
||||||
|
<Text style={style}> (scaling min)</Text>
|
||||||
|
)}
|
||||||
|
{freq == info.scaling_max_freq && (
|
||||||
|
<Text style={style}> (scaling max)</Text>
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
buildAvailableGovList = (freq: CPUFrequency): string => {
|
||||||
|
if (freq.scaling_available_governors.length == 0) {
|
||||||
|
return 'N/A';
|
||||||
|
}
|
||||||
|
return freq.scaling_available_governors.join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
buildSidebarRow = (key: string, val: any) => {
|
||||||
|
return {
|
||||||
|
columns: {
|
||||||
|
key: {value: <Text>{key}</Text>},
|
||||||
|
value: {
|
||||||
|
value: val,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
key: key,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sidebarRows = (id: number) => {
|
||||||
|
let availableFreqTitle = 'Scaling Available Frequencies';
|
||||||
|
let selected = this.state.cpuFreq[id];
|
||||||
|
if (selected.scaling_available_freqs.length > 0) {
|
||||||
|
availableFreqTitle +=
|
||||||
|
' (' + selected.scaling_available_freqs.length.toString() + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys = [availableFreqTitle, 'Scaling Available Governors'];
|
||||||
|
|
||||||
|
let vals = [
|
||||||
|
this.buildAvailableFreqList(selected),
|
||||||
|
this.buildAvailableGovList(selected),
|
||||||
|
];
|
||||||
|
return keys.map<any>((key, idx) => {
|
||||||
|
return this.buildSidebarRow(key, vals[idx]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderSidebar = () => {
|
||||||
|
if (this.state.selectedIds.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let id = this.state.selectedIds[0];
|
||||||
|
let cols = {
|
||||||
|
key: {
|
||||||
|
value: 'key',
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
value: 'value',
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let colSizes = {
|
||||||
|
key: '35%',
|
||||||
|
value: 'flex',
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<DetailSidebar width={500}>
|
||||||
|
<Panel
|
||||||
|
padded={true}
|
||||||
|
heading="CPU details"
|
||||||
|
floating={false}
|
||||||
|
collapsable={true}>
|
||||||
|
<Heading>CPU_{id}</Heading>
|
||||||
|
<ManagedTable
|
||||||
|
columnSizes={colSizes}
|
||||||
|
multiline={true}
|
||||||
|
columns={cols}
|
||||||
|
autoHeight={true}
|
||||||
|
floating={false}
|
||||||
|
zebra={true}
|
||||||
|
rows={this.sidebarRows(id)}
|
||||||
|
/>
|
||||||
|
</Panel>
|
||||||
|
</DetailSidebar>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -357,7 +544,14 @@ export default class CPUFrequencyTable extends FlipperDevicePlugin<CPUState> {
|
|||||||
floating={false}
|
floating={false}
|
||||||
zebra={true}
|
zebra={true}
|
||||||
rows={this.frequencyRows(this.state.cpuFreq)}
|
rows={this.frequencyRows(this.state.cpuFreq)}
|
||||||
|
onRowHighlighted={selectedIds => {
|
||||||
|
this.setState({
|
||||||
|
selectedIds: selectedIds,
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{this.renderSidebar()}
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user