I have to disagree with @Baggypants on this. Time is an illusion. Lunchtime doubly so… or to be more accurate, time is a social construct. The idea that fractions of milliseconds should matter any more than milliseconds themselves being fractions of seconds seems absurd!
An xrun is an underrun or overrun (hence the ‘x’ acting as a wildcard in its name). These occur when there is insufficient or excessive data delivered to a software or hardware audio module.
An underrun occurs when the source is slow and delivers too little data in the prescribed time period. The destination must continue without the expected data which (usually) leaves a hole (silence) in the audio (although could leave previous (stale) data depending on the code) which manifests as a click.
An overrun occurs when the destination is slow and cannot receive / process the data before the source needs to reuse it’s output buffer. The data must be discarded which results in a discontinuity and may even lead to a subsequent underrun.
Softmode allows overrurns to write over destination input buffer rather than discarded whole buffer. The same sample slippage occurs but the audible effect may be less impactful. This may have significant effect on the module if it depends heavily on the data, e.g. convolution.
The core aim is to allow each module to complete it’s process of receiving a block of data, processing it and delivering it to its output buffer within the period defined by jackd. This includes ADC and DAC which will run at their own clock rate(s). Jackd should use the ADC/DAC clock hence you should use a samplerate that is native to the soundcard. Many soundcards allow this to be changed, e.g. 32000, 44100, 48000, 88200, 96000 samples per second. I would say this is the first thing to configure so that jackd is running at a rate supported by the soundcard. Consistently timed periodic xruns is an indication that this is wrong. The drift between soundcard samplerate and jackd (unlocked) rate will cause xrun after a quantity of periods when the buffer had emptied / filled hence the xrun occurs with regular period.
Most modules have peaky load. The CPU (and other hardware / software resources) may be able to process a module’s average load okay but may fail occasionally due to a (possibly sustained) peak of high processing. This may result in the module failing to complete it’s processing in a period, triggering an xrun. Reducing the load can reduce the risk of this, e.g. using less demanding configuration / preset. Increasing the available time to process each block of data also reduces this risk, e.g. increasing quantity / size of buffers. This smoothes out the load, giving more time during each processing period for those peaks to be processed. This allows modules to run without xruns if they have high transient peaks but a low average load. It doesn’t fix persistently high load. Increasing the time for proceeding increases the latency.
Jackd process all nodes in its graph synchronously which means that everything has the same latency. If you have a module that needs longer to process is data then all other modules must wait the same time. This means you can’t have lower latency where needed whilst allowing modules that may not benefit from low latency to run slower, e.g. synths with slow attack.
Pipewire does allow different latencies but this requires a greater overhead within the sound system. I am eager to investigate if / when Pipewire can provide comparable performance as jackd and whether such features may provide tangible benefits within Zynthian.