Skip to content

Commit

Permalink
Merge pull request #799 from oceanprotocol/issue-768-env-cpu-mem
Browse files Browse the repository at this point in the history
Issue 768 env cpu mem
  • Loading branch information
paulo-ocean authored Jan 8, 2025
2 parents b96debe + 5a08aaf commit 43d7e41
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 10 deletions.
46 changes: 37 additions & 9 deletions src/components/c2d/compute_engine_docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { decryptFilesObject, omitDBComputeFieldsFromComputeJob } from './index.j
import * as drc from 'docker-registry-client'
import { ValidateParams } from '../httpRoutes/validateCommands.js'
import { convertGigabytesToBytes } from '../../utils/util.js'
import os from 'os'

export class C2DEngineDocker extends C2DEngine {
private envs: ComputeEnvironment[] = []
Expand Down Expand Up @@ -506,7 +507,7 @@ export class C2DEngineDocker extends C2DEngine {
const environment = await this.getJobEnvironment(job)
// create the container
const mountVols: any = { '/data': {} }
const hostConfig: HostConfig = {
let hostConfig: HostConfig = {
Mounts: [
{
Type: 'volume',
Expand All @@ -518,16 +519,12 @@ export class C2DEngineDocker extends C2DEngine {
}
if (environment != null) {
// limit container CPU & Memory usage according to env specs
hostConfig.CpuCount = environment.cpuNumber || 1
// if more than 1 CPU
if (hostConfig.CpuCount > 1) {
hostConfig.CpusetCpus = `0-${hostConfig.CpuCount - 1}`
hostConfig = {
...hostConfig,
...(await buildCPUAndMemoryConstraints(environment, this.docker))
}
hostConfig.Memory = 0 || convertGigabytesToBytes(environment.ramGB)
// set swap to same memory value means no swap (otherwise it use like 2X mem)
hostConfig.MemorySwap = hostConfig.Memory
}
// console.log('host config: ', hostConfig)

const containerInfo: ContainerCreateOptions = {
name: job.jobId + '-algoritm',
Image: job.containerImage,
Expand Down Expand Up @@ -1116,3 +1113,34 @@ export function checkManifestPlatform(
return false
return true
}
/**
* Helper function to build CPU constraints, also useful for testing purposes
* @param environment C2D environment
* @returns partial HostConfig object
*/
export async function buildCPUAndMemoryConstraints(
environment: ComputeEnvironment,
docker?: Dockerode
): Promise<HostConfig> {
const hostConfig: HostConfig = {}
// CPU
const systemInfo = docker ? await docker.info() : null
const existingCPUs = systemInfo ? systemInfo.NCPU : os.cpus().length
const confCPUs = environment.cpuNumber > 0 ? environment.cpuNumber : 1
// windows only
hostConfig.CpuCount = Math.min(confCPUs, existingCPUs)
// hostConfig.CpuShares = 1 / hostConfig.CpuCount
hostConfig.CpuPeriod = 100000 // 100 miliseconds is usually the default
hostConfig.CpuQuota = (1 / hostConfig.CpuCount) * hostConfig.CpuPeriod
// if more than 1 CPU, Limit the specific CPUs or cores a container can use.
if (hostConfig.CpuCount > 1) {
hostConfig.CpusetCpus = `0-${hostConfig.CpuCount - 1}`
}
// MEM
const existingMem = systemInfo ? systemInfo.MemTotal : os.totalmem()
const configuredRam = 0 || convertGigabytesToBytes(environment.ramGB)
hostConfig.Memory = 0 || Math.min(existingMem, configuredRam)
// set swap to same memory value means no swap (otherwise it use like 2X mem)
hostConfig.MemorySwap = hostConfig.Memory
return hostConfig
}
23 changes: 22 additions & 1 deletion src/test/unit/compute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import { ENVIRONMENT_VARIABLES } from '../../utils/constants.js'
import { completeDBComputeJob, dockerImageManifest } from '../data/assets.js'
import { omitDBComputeFieldsFromComputeJob } from '../../components/c2d/index.js'
import os from 'os'
import { checkManifestPlatform } from '../../components/c2d/compute_engine_docker.js'
import Dockerode from 'dockerode'
import {
buildCPUAndMemoryConstraints,
checkManifestPlatform
} from '../../components/c2d/compute_engine_docker.js'
import type { HostConfig } from 'dockerode'

describe('Compute Jobs Database', () => {
let envOverrides: OverrideEnvConfig[]
Expand Down Expand Up @@ -231,6 +236,22 @@ describe('Compute Jobs Database', () => {
expect(checkManifestPlatform(null, env)).to.be.equal(true)
})

it('should check cpu constraints on c2d docker env', async function () {
const size = config.c2dClusters.length
const dockerConfig = config.c2dClusters[size - 1].connection
const freeEnv: ComputeEnvironment = dockerConfig.freeComputeOptions
const cpus = os.cpus()
freeEnv.cpuNumber = cpus.length + 1 // should be capped to cpus.length
const docker = new Dockerode({ socketPath: '/var/run/docker.sock' })
let hostConfig: HostConfig = await buildCPUAndMemoryConstraints(freeEnv, docker)
expect(hostConfig.CpuCount).to.be.equal(cpus.length)
freeEnv.cpuNumber = -1
hostConfig = await buildCPUAndMemoryConstraints(freeEnv)
expect(hostConfig.CpuCount).to.be.equal(1)
const ram = os.totalmem()
expect(hostConfig.Memory).to.be.lessThanOrEqual(ram)
})

after(async () => {
await tearDownEnvironment(envOverrides)
})
Expand Down

0 comments on commit 43d7e41

Please sign in to comment.