Be smarter about age-counter overflow in formatting.c caches.

The previous code here simply threw away whatever it knew about cache
entry ages whenever a counter overflow occurred.  Since the counter
is int width and will be bumped once per format function execution,
overflows are not really so rare as to not be worth thinking about.
Instead, let's deal with the situation by halving all the age values,
essentially rescaling the age metric.  In that way, we retain a
pretty accurate (if not quite perfect) idea of which entries are oldest.
This commit is contained in:
Tom Lane 2018-10-16 14:57:14 -04:00
parent f7a953c2d8
commit 2c300c6807
1 changed files with 38 additions and 32 deletions

View File

@ -3376,20 +3376,32 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
}
}
/*
* The invariant for DCH cache entry management is that DCHCounter is equal
* to the maximum age value among the existing entries, and we increment it
* whenever an access occurs. If we approach overflow, deal with that by
* halving all the age values, so that we retain a fairly accurate idea of
* which entries are oldest.
*/
static inline void
DCH_prevent_counter_overflow(void)
{
if (DCHCounter >= (INT_MAX - 1))
{
for (int i = 0; i < n_DCHCache; i++)
DCHCache[i]->age >>= 1;
DCHCounter >>= 1;
}
}
/* select a DCHCacheEntry to hold the given format picture */
static DCHCacheEntry *
DCH_cache_getnew(const char *str)
{
DCHCacheEntry *ent;
/* handle counter overflow by resetting all ages */
if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
{
DCHCounter = 0;
for (int i = 0; i < n_DCHCache; i++)
DCHCache[i]->age = (++DCHCounter);
}
/* Ensure we can advance DCHCounter below */
DCH_prevent_counter_overflow();
/*
* If cache is full, remove oldest entry (or recycle first not-valid one)
@ -3445,14 +3457,8 @@ DCH_cache_getnew(const char *str)
static DCHCacheEntry *
DCH_cache_search(const char *str)
{
/* handle counter overflow by resetting all ages */
if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
{
DCHCounter = 0;
for (int i = 0; i < n_DCHCache; i++)
DCHCache[i]->age = (++DCHCounter);
}
/* Ensure we can advance DCHCounter below */
DCH_prevent_counter_overflow();
for (int i = 0; i < n_DCHCache; i++)
{
@ -4057,20 +4063,26 @@ do { \
(_n)->zero_end = 0; \
} while(0)
/* This works the same as DCH_prevent_counter_overflow */
static inline void
NUM_prevent_counter_overflow(void)
{
if (NUMCounter >= (INT_MAX - 1))
{
for (int i = 0; i < n_NUMCache; i++)
NUMCache[i]->age >>= 1;
NUMCounter >>= 1;
}
}
/* select a NUMCacheEntry to hold the given format picture */
static NUMCacheEntry *
NUM_cache_getnew(const char *str)
{
NUMCacheEntry *ent;
/* handle counter overflow by resetting all ages */
if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
{
NUMCounter = 0;
for (int i = 0; i < n_NUMCache; i++)
NUMCache[i]->age = (++NUMCounter);
}
/* Ensure we can advance NUMCounter below */
NUM_prevent_counter_overflow();
/*
* If cache is full, remove oldest entry (or recycle first not-valid one)
@ -4126,14 +4138,8 @@ NUM_cache_getnew(const char *str)
static NUMCacheEntry *
NUM_cache_search(const char *str)
{
/* handle counter overflow by resetting all ages */
if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
{
NUMCounter = 0;
for (int i = 0; i < n_NUMCache; i++)
NUMCache[i]->age = (++NUMCounter);
}
/* Ensure we can advance NUMCounter below */
NUM_prevent_counter_overflow();
for (int i = 0; i < n_NUMCache; i++)
{