mirror of
https://github.com/computernewb/collabvm-1.2.ts.git
synced 2025-01-22 10:42:00 -05:00
cvmts: Allow specifying cgroup cpu period
probably limited utility wise but it's there now
This commit is contained in:
parent
fe82973b9f
commit
405e88bd1b
3 changed files with 30 additions and 13 deletions
|
@ -57,20 +57,29 @@ qemuArgs = "qemu-system-x86_64"
|
||||||
vncPort = 5900
|
vncPort = 5900
|
||||||
snapshots = true
|
snapshots = true
|
||||||
|
|
||||||
# Resource limits. Only works on Linux, with `Delegate=yes` set in your .service file. No-op on other platforms.
|
# Resource limits.
|
||||||
|
# Only works on Linux, with `Delegate=yes` set in your .service file. No-op on other platforms.
|
||||||
#
|
#
|
||||||
# cpuUsageMax optionally specifies the max CPU usage as percentage in the common top notation, so 200% means 2 CPUs, 400% is 4 CPUs,
|
# cpuUsageMax is an optional value specifies the max CPU usage as percentage in the common top notation.
|
||||||
# so on.
|
# 200% means 2 CPUs, 400% is 4 CPUs.
|
||||||
|
#
|
||||||
|
# A general reccomendation is to set this to 100*[vCPU count].
|
||||||
|
# For example, if your QEMU command line contains -smp cores=2, then cpuUsageMax should be 200.
|
||||||
|
# For an overcomitted host, you can use lower values,
|
||||||
|
# but it *can* get noticable if you throttle CPU too low.
|
||||||
#
|
#
|
||||||
# runOnCpus is an optional array that specifies what CPUs the VM is allowed to run on.
|
# runOnCpus is an optional array that specifies what CPUs the VM is allowed to run on.
|
||||||
# Systemd user slices can not delegate the cpuset controller, meaning this option will *not* work if you do not use a system service.
|
# This option will *not* work if you do not use a system service. (effectively, it will be a loud no-op that logs an error on startup).
|
||||||
# (effectively, it will be a loud no-op that logs an error on startup)
|
|
||||||
#
|
#
|
||||||
# limitProcess is optional (default false) and determines if only qemu vCPU threads are put into the cgroup,
|
# periodMs is an optional value in milliseconds that specifies the cgroup's CPU accounting period.
|
||||||
|
# The default is 100 ms (which matches the cgroups2 defaults), and should work in pretty much all cases, but
|
||||||
|
# it's a knob provided for any addl. tuning purposes.
|
||||||
|
#
|
||||||
|
# limitProcess is an optional boolean (default false) that determines if only qemu vCPU threads are put into the cgroup,
|
||||||
# or the entire QEMU process (incl. all its threads). The default behaviour of only limiting vCPU threads
|
# or the entire QEMU process (incl. all its threads). The default behaviour of only limiting vCPU threads
|
||||||
# is more than likely what you want, so the example configuration omits specifying this key.
|
# is more than likely what you want, so the example configuration omits specifying this key.
|
||||||
#
|
#
|
||||||
# Commenting this inline table from the configuration disables resource limiting entirely.
|
# Commenting or removing this table from the configuration disables resource limiting entirely.
|
||||||
resourceLimits = { cpuUsageMax = 100, runOnCpus = [ 2, 4 ] }
|
resourceLimits = { cpuUsageMax = 100, runOnCpus = [ 2, 4 ] }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ export class CGroupController {
|
||||||
WriteValue(key: string, value: string) {
|
WriteValue(key: string, value: string) {
|
||||||
try {
|
try {
|
||||||
writeFileSync(path.join(this.cg.Path(), `${this.controller}.${key}`), value);
|
writeFileSync(path.join(this.cg.Path(), `${this.controller}.${key}`), value);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
logger.error({error: e, controller_key: `${this.controller}.${key}`, value: value }, 'Failed to set CGroup controller value')
|
logger.error({ error: e, controller_name: this.controller, controller_key: `${this.controller}.${key}`, value: value }, 'Failed to set CGroup controller value');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,11 @@ export class CGroup {
|
||||||
InitControllers(wants_cpuset: boolean) {
|
InitControllers(wants_cpuset: boolean) {
|
||||||
// Configure this "root" cgroup to provide cpu and cpuset controllers to the leaf
|
// Configure this "root" cgroup to provide cpu and cpuset controllers to the leaf
|
||||||
// QEMU cgroups. A bit iffy but whatever.
|
// QEMU cgroups. A bit iffy but whatever.
|
||||||
if(wants_cpuset) {
|
if (wants_cpuset) {
|
||||||
try {
|
try {
|
||||||
writeFileSync(path.join(this.path, 'cgroup.subtree_control'), '+cpu +cpuset');
|
writeFileSync(path.join(this.path, 'cgroup.subtree_control'), '+cpu +cpuset');
|
||||||
} catch(err) {
|
} catch (err) {
|
||||||
logger.error({error: err}, 'Could not provide cpuset controller to subtree');
|
logger.error({ error: err }, 'Could not provide cpuset controller to subtree. runOnCpus will not function.');
|
||||||
// just give up if this fails
|
// just give up if this fails
|
||||||
writeFileSync(path.join(this.path, 'cgroup.subtree_control'), '+cpu');
|
writeFileSync(path.join(this.path, 'cgroup.subtree_control'), '+cpu');
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { CGroup } from '../util/cgroup.js';
|
||||||
export interface CgroupLimits {
|
export interface CgroupLimits {
|
||||||
cpuUsageMax?: number;
|
cpuUsageMax?: number;
|
||||||
runOnCpus?: number[];
|
runOnCpus?: number[];
|
||||||
|
periodMs?: number;
|
||||||
limitProcess?: boolean;
|
limitProcess?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,12 +20,19 @@ interface CGroupValue {
|
||||||
function MakeValuesFromLimits(limits: CgroupLimits): CGroupValue[] {
|
function MakeValuesFromLimits(limits: CgroupLimits): CGroupValue[] {
|
||||||
let option_array = [];
|
let option_array = [];
|
||||||
|
|
||||||
|
// The default period is 100 ms, which matches cgroups2 defaults.
|
||||||
|
let periodUs = 100 * 1000;
|
||||||
|
|
||||||
|
// Convert a user-configured period to us, since that's what cgroups2 expects.
|
||||||
|
if(limits.periodMs)
|
||||||
|
periodUs = limits.periodMs * 1000;
|
||||||
|
|
||||||
if (limits.cpuUsageMax) {
|
if (limits.cpuUsageMax) {
|
||||||
// cpu.max
|
// cpu.max
|
||||||
option_array.push({
|
option_array.push({
|
||||||
controller: 'cpu',
|
controller: 'cpu',
|
||||||
key: 'max',
|
key: 'max',
|
||||||
value: `${(limits.cpuUsageMax / 100) * 100000} 100000`
|
value: `${(limits.cpuUsageMax / 100) * periodUs} ${periodUs}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue