Override total threads

I run Photstructure node for windows on a dedicated VM.
The VM has 10 cores and dynamic memory.

If i set PS_CPU_LOAD_PERCENT to 100 as I dont mind photostructure utilizing all resources it can get it’s hands on i still only get 2 syncs & 2 threads/sync. According to the settings comment some consideration is made in regards to available memory when determining sync/thread count.

I would like a setting to hardcode the maximum thread count that photstructure is allowed to use regardless of available memory. I don’t know how photostructure want to distribute threadcount over sync instances but maybe a maximum thread count override where photostrucuture calculates the distribution?

I could of course workaround the problem by configured fixed memory allocation or increase the memory buffer on the host but it feels wasteful on a home server without endless amounts of RAM…

Until I ship something better, know that you can “oversubscribe” your VM by setting the value to values > 100%, like 150.

Please tell me if this doesn’t work as expected!

Ok, I’ll try :slight_smile:

How is Photostructure taking memory in consideration when calculating threads?

export const estimatedFreeMem = lazy(() => (freemem() * 2 + totalmem()) / 3)

export const totalCpus = lazy(() => cpus().length)

export const maxCpus = lazy(() => {
  // they may bloat, but they'll recycle if they get too big.
  const worstCaseMemPerProc = 1 * GB
  // We don't want to over-subscribe system memory, but we need to run at
  // least one:
  const maxProcs = Math.max(
    1,
    Math.floor(estimatedFreeMem() / worstCaseMemPerProc)
  )
  const cpuCount = (Settings.cpuLoadPercent.valueOrDefault / 100) * totalCpus()
  return clamp(1, maxProcs, Math.floor(cpuCount))
})

export const sharpThreadsPerSystem = lazy(() => {
  const worstCasePerSharpThread = 500 * MB
  const maxThreadsForMem = Math.floor(
    estimatedFreeMem() / worstCasePerSharpThread
  )
  const maxThreads = Math.max(
    1,
    Math.floor(
      1.5 * totalCpus() * (Settings.cpuLoadPercent.valueOrDefault / 100)
    )
  )
  return clamp(1, maxThreads, maxThreadsForMem)
})

export const maxSyncFileJobs = lazy(() => {
  // We can host 2-6 sharp threads per sync-file. It's better for concurrency to
  // have > 1 sync-file than > 1 sharp thread, but that uses more memory.
  return clamp(1, 24, maxCpus())
})

// Now that we've decided how many sync-file jobs we can run, we can decide how
// many sharp threads we use per sync-file:
export const sharpThreadsPerJob = lazy(() =>
  // Even if we've got tons of RAM, we don't get a huge performance win with >
  // 8 graphics threads. 6 is fine.
  clamp(1, 6, Math.ceil(sharpThreadsPerSystem() / maxSyncFileJobs()))
)