Wednesday, October 8, 2008

fine-grained dirty_ratio and dirty_background_ratio

A process that writes something to a file generates dirty pages in the page cache. Dirty pages must be kept in sync with their backing store (the file defined on the block device).

In the Linux kernel the frequency to writeback dirty pages is controlled by two parameters: vm.dirty_ratio and vm.dirty_background_ratio. Both are expressed a percentage of dirtyable memory, that is the free memory + reclaimable memory (active and inactive pages in the LRU list).

The first parameter controls when a process will itself start writing out dirty data, the second controls when the kernel thread [pdflush] must be woken up and it will start writing out dirty data globally on behalf of the processes (dirty_background_ratio is always less than dirty_ratio; if dirty_background_ratio >= dirty_ratio the kernel automatically set it to dirty_ratio / 2).

Unfortunately, both percentages are int and the kernel doesn't even allow to set them below 5%. This means that in large memory machine those limits are too coarse. On a machine that has 1GB of dirtyable memory the kernel will start to writeback dirty pages in chunks of 50MB (!!!) minimum (with dirty_ratio = 5).

Even if it could be fine for batch or server machines, this behaviour could be unpleasant for desktop or latency-sensitive environments, when the large writeback can be perceived as a lack of responsiveness in the whole system.

IMHO we really need an interface to define fine-grained limits (to writeback small amount of data, often) and the best solution for this without breaking the compatibility with the old interface seems to introduce a new interface to define pcm (milli-percent) values.

At least this would resolve the problem for today machines... until 1TB memory servers will become popular...

2 comments:

Anonymous said...

(dirty_ratio is always less than dirty_background_ratio; if dirty_background_ratio >= dirty_ratio the kernel automatically set it to dirty_ratio / 2)

...makes no sense, you mean:

(dirty_ratio is always less than dirty_background_ratio; if dirty_ratio >= dirty_background_ratio the kernel automatically set it to dirty_background_ratio / 2)?

arighi said...

Fixed. The correct sentence is:

(dirty_background_ratio is always less than dirty_ratio; if dirty_background_ratio >= dirty_ratio the kernel automatically set it to dirty_ratio / 2)

BTW this problem has been resolved in the kernel, now we have dirty_background_bytes and dirty_bytes, that allows to define a limit in bytes, instead of percentage (see http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=2da02997e08d3efe8174c7a47696e6f7cbe69ba9 for details).

Thanks for reporting!