Changeset: 2bfd82708703 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2bfd82708703
Modified Files:
gdk/gdk_bbp.c
gdk/gdk_private.h
gdk/gdk_utils.c
gdk/gdk_utils.h
Branch: default
Log Message:
Removed trimming on malloc failure; removed trim thread.
diffs (truncated from 771 to 300 lines):
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -185,7 +185,6 @@ getBBPsize(void)
static MT_Lock BBP_curstampLock MT_LOCK_INITIALIZER("BBP_curstampLock");
#endif
static volatile ATOMIC_TYPE BBP_curstamp = 0; /* unique stamp for creation of
a bat */
-MT_Id BBP_notrim = ~((MT_Id) 0); /* avoids BBPtrim when we really do not
want it */
int BBP_dirty = 0; /* BBP structures modified? */
int BBPin = 0; /* bats loaded statistic */
int BBPout = 0; /* bats saved statistic */
@@ -284,12 +283,11 @@ BBPlock(void)
for (i = 0; i <= BBP_THREADMASK; i++)
MT_lock_set(&GDKtrimLock(i));
- BBP_notrim = MT_getpid();
for (i = 0; i <= BBP_THREADMASK; i++)
MT_lock_set(&GDKcacheLock(i));
for (i = 0; i <= BBP_BATMASK; i++)
MT_lock_set(&GDKswapLock(i));
- locked_by = BBP_notrim;
+ locked_by = MT_getpid();
MT_lock_unset(&GDKunloadLock);
}
@@ -303,7 +301,6 @@ BBPunlock(void)
MT_lock_unset(&GDKswapLock(i));
for (i = BBP_THREADMASK; i >= 0; i--)
MT_lock_unset(&GDKcacheLock(i));
- BBP_notrim = 0;
locked_by = 0;
for (i = BBP_THREADMASK; i >= 0; i--)
MT_lock_unset(&GDKtrimLock(i));
@@ -357,14 +354,11 @@ BBPselectfarm(int role, int type, enum h
/*
* BBPextend must take the trimlock, as it is called when other BBP
- * locks are held and it will allocate memory. This could trigger a
- * BBPtrim, causing deadlock.
+ * locks are held and it will allocate memory.
*/
static void
BBPextend(int idx, int buildhash)
{
- BBP_notrim = MT_getpid();
-
if ((bat) ATOMIC_GET(BBPsize, BBPsizeLock) >= N_BBPINIT * BBPINIT)
GDKfatal("BBPextend: trying to extend BAT pool beyond the "
"limit (%d)\n", N_BBPINIT * BBPINIT);
@@ -387,7 +381,6 @@ BBPextend(int idx, int buildhash)
BBP_free(i) = 0;
BBPinithash(idx);
}
- BBP_notrim = 0;
}
static inline str
@@ -1401,7 +1394,6 @@ BBPinit(void)
}
BBPinithash(0);
- BBP_notrim = 0;
OIDbase(BBPoid);
@@ -2089,8 +2081,7 @@ BBPinsert(BAT *bn)
MT_lock_unset(&GDKcacheLock(idx));
MT_lock_unset(&GDKtrimLock(idx));
}
- /* rest of the work outside the lock , as GDKstrdup/GDKmalloc
- * may trigger a BBPtrim */
+ /* rest of the work outside the lock */
/* fill in basic BBP fields for the new bat */
@@ -2294,7 +2285,6 @@ BBPrename(bat bid, const char *nme)
MT_lock_unset(&GDKtrimLock(idx));
return BBPRENAME_ALREADY;
}
- BBP_notrim = MT_getpid();
/* carry through the name change */
if (BBP_logical(bid) && BBPtmpcheck(BBP_logical(bid)) == 0) {
@@ -2318,7 +2308,6 @@ BBPrename(bat bid, const char *nme)
BBPdirty(1);
}
MT_lock_unset(&GDKnameLock);
- BBP_notrim = 0;
MT_lock_unset(&GDKtrimLock(idx));
return 0;
}
@@ -2832,418 +2821,19 @@ BBPfree(BAT *b, const char *calledFrom)
}
/*
- * @- Storage trimming
- * BBPtrim unloads the least recently used BATs to free memory
- * resources. It gets passed targets in bytes of physical memory and
- * logical virtual memory resources to free. Overhead costs are
- * reduced by making just one scan, analyzing the first BBPMAXTRIM
- * bats and keeping the result in a list for later use (the oldest bat
- * now is going to be the oldest bat in the future as well). This
- * list is sorted on last-used timestamp. BBPtrim keeps unloading BATs
- * till the targets are met or there are no more BATs to unload.
- *
- * In determining whether a BAT will be unloaded, first it has to be
- * BBPswappable, and second its resources occupied must be of the
- * requested type. The algorithm actually makes two passes, in the
- * first only clean bats are unloaded (in order of their stamp).
- *
- * In order to keep this under control with multiple threads all
- * running out of memory at the same time, we make sure that
- * @itemize
- * @item
- * just one thread does a BBPtrim at a time (by having a BBPtrimLock
- * set).
- * @item
- * while decisions are made as to which bats to unload (1) the BBP is
- * scanned, and (2) unload decisions are made. Due to these
- * properties, the search&decide phase of BBPtrim acquires both
- * GDKcacheLock (due to (1)) and all GDKswapLocks (due to (2)). They
- * must be released during the actual unloading. (as otherwise
- * deadlock occurs => unloading a bat may e.g. kill an accelerator
- * that is a BAT, which in turn requires BBP lock acquisition).
- * @item
- * to avoid further deadlock, the update functions in BBP that hold
- * either GDKcacheLock or a GDKswapLock may never cause a BBPtrim
- * (notice that BBPtrim could theoretically be set off just by
- * allocating a little piece of memory, e.g. GDKstrdup()). If these
- * routines must alloc memory, they must set the BBP_notrim variable,
- * acquiring the addition GDKtrimLock, in order to prevent such
- * deadlock.
- * @item
- * the BBPtrim is atomic; only releases its locks when all BAT unload
- * work is done. This ensures that if all memory requests that
- * triggered BBPtrim could possible be satisfied by unloading BATs,
- * this will succeed.
- * @end itemize
- *
- * The scan phase was optimized further in order to stop early when it
- * is a priori known that the targets are met (which is the case if
- * the BBPtrim is not due to memory shortage but due to the ndesc
- * quota). Note that scans may always stop before BBPsize as the
- * BBPMAXTRIM is a fixed number which may be smaller. As such, a
- * mechanism was added to resume a broken off scan at the point where
- * scanning was broken off rather than always starting at BBP[1] (this
- * does more justice to the lower numbered bats and will more quickly
- * find fresh unload candidates).
- *
- * We also refined the swap criterion. If the BBPtrim was initiated
- * due to:
- * - too much descriptors: small bats are unloaded first (from LRU
- * cold to hot)
- * - too little memory: big bats are unloaded first (from LRU cold to
- * hot).
- * Unloading-first is enforced by subtracting @math{2^31} from the
- * stamp in the field where the candidates are sorted on.
- *
- * BBPtrim is abandoned when the application has indicated that it
- * does not need it anymore.
- */
-#define BBPMAXTRIM 40000
-#define BBPSMALLBAT 1000
-
-typedef struct {
- bat bid; /* bat id */
- int next; /* next position in list */
- BUN cnt; /* bat count */
-#if SIZEOF_BUN == SIZEOF_INT
- BUN dummy; /* padding to power-of-two size */
-#endif
-} bbptrim_t;
-
-static unsigned lastused[BBPMAXTRIM]; /* bat lastused stamp; sort on this
field */
-static bbptrim_t bbptrim[BBPMAXTRIM];
-static int bbptrimfirst = BBPMAXTRIM, bbptrimlast = 0, bbpunloadtail,
bbpunload, bbptrimmax = BBPMAXTRIM, bbpscanstart = 1;
-
-static bat
-BBPtrim_scan(bat bbppos, bat bbplim)
-{
- bbptrimlast = 0;
- bbptrimmax = BBPMAXTRIM;
- MEMDEBUG fprintf(stderr, "#TRIMSCAN: start=%d, limit=%d\n", (int)
bbppos, (int) bbplim);
-
- if (bbppos < (bat) ATOMIC_GET(BBPsize, BBPsizeLock))
- do {
- if (BBPvalid(bbppos)) {
- BAT *b = BBP_cache(bbppos);
-
- if (BBPtrimmable(b)) {
- /* when unloading for memory,
- * treat small BATs with a
- * preference over big ones.
- * rationale: I/O penalty for
- * cache miss is relatively
- * higher for small bats
- */
- BUN cnt = BATcount(b);
- unsigned swap_first = (cnt >=
BBPSMALLBAT);
-
- /* however, when we are
- * looking to decrease the
- * number of descriptors, try
- * to put the small bats in
- * front of the load list
- * instead..
- */
-
- /* subtract 2-billion to make
- * sure the swap_first class
- * bats are unloaded first */
- lastused[bbptrimlast] = (unsigned)
BBPLASTUSED(BBP_lastused(bbppos)) | (swap_first << 31);
- bbptrim[bbptrimlast].bid = bbppos;
- bbptrim[bbptrimlast].cnt = cnt;
- if (++bbptrimlast == bbptrimmax)
- break;
- }
- }
- if (++bbppos == (bat) ATOMIC_GET(BBPsize, BBPsizeLock))
- bbppos = 1; /* treat BBP as a circular
buffer */
- } while (bbppos != bbplim);
-
- if (bbptrimlast > 0) {
- int i;
- /* sort lastused array as (signed) int */
- GDKqsort(lastused, bbptrim, NULL, bbptrimlast,
- sizeof(lastused[0]), sizeof(bbptrim[0]), TYPE_int);
- for (i = bbptrimfirst = 0; i < bbptrimlast; i++) {
- MEMDEBUG fprintf(stderr, "#TRIMSCAN: %11d%c %9d=%s\t(#"
BUNFMT ")\n", (int) BBPLASTUSED(lastused[i]), lastused[i] & ((unsigned) 1 <<
31) ? '*' : ' ', i, BBPname(bbptrim[i].bid), bbptrim[i].cnt);
-
- bbptrim[i].next = i + 1;
- }
- bbptrim[bbptrimlast - 1].next = BBPMAXTRIM;
- } else {
- bbptrimfirst = BBPMAXTRIM;
- }
- MEMDEBUG fprintf(stderr, "#TRIMSCAN: end at %d (size=%d)\n", bbppos,
(int) (bat) ATOMIC_GET(BBPsize, BBPsizeLock));
-
- return bbppos;
-}
-
-
-/* insert BATs to unload from bbptrim list into bbpunload list;
- * rebuild bbptrimlist only with the useful leftovers */
-static size_t
-BBPtrim_select(size_t target, int dirty)
-{
- int bbptrimtail = BBPMAXTRIM, next = bbptrimfirst;
-
- MEMDEBUG fprintf(stderr, "#TRIMSELECT: dirty = %d\n", dirty);
-
- /* make the bbptrim-list empty; we will insert the untouched
- * elements in it */
- bbptrimfirst = BBPMAXTRIM;
-
- while (next != BBPMAXTRIM) {
- int cur = next; /* cur is the entry in the old bbptrimlist we
are processing */
- int untouched = BBPLASTUSED(BBP_lastused(bbptrim[cur].bid)) <=
(int) BBPLASTUSED(lastused[cur]);
- BAT *b = BBP_cache(bbptrim[cur].bid);
-
- next = bbptrim[cur].next; /* do now, because we overwrite
bbptrim[cur].next below */
-
- MEMDEBUG if (b) {
- fprintf(stderr,
- "#TRIMSELECT: candidate=%s BAT*=" PTRFMT "\n",
- BBPname(bbptrim[cur].bid),
- PTRFMTCAST(void *)b);
-
- fprintf(stderr,
- "# (cnt=" BUNFMT ", mode=%d, "
- "refs=%d, wait=%d, parent=%d, "
- "lastused=%d,%d,%d)\n",
- bbptrim[cur].cnt,
- (int) b->batPersistence,
- BBP_refs(b->batCacheid),
- (BBP_status(b->batCacheid) & BBPWAITING) != 0,
- VIEWtparent(b),
- BBP_lastused(b->batCacheid),
- (int) BBPLASTUSED(lastused[cur]),
- (int) lastused[cur]);
- }
- /* recheck if conditions encountered by trimscan in
- * the past still hold */
- if (BBPtrimmable(b) && untouched) {
- size_t memdelta = BATmemsize(b, FALSE) + BATvmsize(b,
FALSE);
- size_t memdirty = BATmemsize(b, TRUE) + BATvmsize(b,
TRUE);
-
- if (((b->batPersistence == TRANSIENT &&
- BBP_lrefs(bbptrim[cur].bid) == 0) || /* needs not
be saved when unloaded, OR.. */
- memdirty <= sizeof(BAT) || /* the BAT is actually
clean, OR.. */
- dirty) /* we are allowed to cause I/O (second
run).. */
- && /* AND ... */
- target > 0 && memdelta > 0)
- /* there is some reward in terms of
- * memory requirements */
- {
- /* only then we unload! */
- MEMDEBUG {
- fprintf(stderr,
- "#TRIMSELECT: unload %s ["
SZFMT "] bytes [" SZFMT "] dirty\n",
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list