Greg Smith <[EMAIL PROTECTED]> writes:
> On Thu, 5 Jul 2007, Tom Lane wrote:
>> This would give us a safety margin such that buffers_to_clean is not
>> less than the largest demand observed in the last 100 iterations...and
>> it takes quite a while for the memory of a demand spike to be forgotten
> If you tested this strategy even on a steady load, I'd expect you'll find
> there are large spikes in allocations during the occasional period where
> everything is just right to pull a bunch of buffers in, and if you let
> that max linger around for 100 iterations you'll write a large number of
> buffers more than you need.
You seem to have the same misunderstanding as Heikki. What I was
proposing was not a target for how many to *write* on each cycle, but
a target for how far ahead of the clock sweep hand to look. If say
the target is 100, we'll scan forward from the sweep until we have seen
100 clean zero-usage-count buffers; but we only have to write whichever
of them weren't already clean.
This is actually not so different from my previous proposal, in that the
idea is to keep ahead of the sweep by a particular distance. The
previous idea was that that distance was "all the buffers", whereas this
idea is "a moving average of the actual demand rate". The excess writes
created by the previous proposal were because of the probability of
re-dirtying buffers between cleaning and recycling. We reduce that
probability by not trying to keep so many of 'em clean. But I think
that we can meet the goal of having backends do hardly any of the writes
with a relatively small increase in the target distance, and thus a
relatively small differential in the number of wasted writes. Heikki's
test showed that Itagaki-san's patch wasn't doing that well in
eliminating writes by backends, so we need a more aggressive target for
how many buffers to keep clean than it has; but I think not a huge
amount more, and thus my proposal.
BTW, somewhere upthread you suggested combining the target-distance
idea with the idea that the cleaning work uses a separate sweep hand and
thus doesn't re-examine the same buffers on every bgwriter iteration.
The problem is that it'd be very hard to track how far ahead of the
recycling sweep hand we are, because that number has to be measured
in usage-count-zero pages. I see no good way to know how many of the
pages we scanned before have been touched (and given nonzero usage
counts) unless we rescan them.
We could approximate it maybe: try to keep the cleaning hand N total
buffers ahead of the recycling hand, where N is the target number of
clean usage-count-zero buffers scaled by the average fraction of
count-zero buffers (which we can track a moving average of as we advance
the recycling hand). However I'm not sure the complexity and
uncertainty is worth it. What I took away from Heikki's experiment is
that trying to stay a large distance in front of the recycle sweep
isn't actually so useful because you get too many wasted writes due
to re-dirtying. So restructuring the algorithm to make it cheap
CPU-wise to stay well ahead is not so useful either.
> I ended up settling on max(moving average of the last 16,most recent
> allocation), and that seemed to work pretty well without being too
> wasteful from excessive writes.
I've been doing moving averages for years and years, and I find that the
multiplication approach works at least as well as explicitly storing the
last K observations. It takes a lot less storage and arithmetic too.
regards, tom lane
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend