LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_resource.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 45 56 80.4 %
Date: 2021-09-14 22:17:06 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /* (author) M.L. Kersten
      10             :  */
      11             : #include "monetdb_config.h"
      12             : #include "mal_exception.h"
      13             : #include "mal_resource.h"
      14             : #include "mal_private.h"
      15             : #include "mal_instruction.h"
      16             : 
      17             : /* Memory based admission does not seem to have a major impact so far. */
      18             : static lng memorypool = 0;      /* memory claimed by concurrent threads */
      19             : 
      20             : void
      21         264 : mal_resource_reset(void)
      22             : {
      23         264 :         memorypool = (lng) MEMORY_THRESHOLD;
      24         264 : }
      25             : /*
      26             :  * Running all eligible instructions in parallel creates
      27             :  * resource contention. This means we should implement
      28             :  * an admission control scheme where threads are temporarily
      29             :  * postponed if the claim for memory exceeds a threshold
      30             :  * In general such contentions will be hard to predict,
      31             :  * because they depend on the algorithm, the input sizes,
      32             :  * concurrent use of the same variables, and the output produced.
      33             :  *
      34             :  * One heuristic is based on calculating the storage footprint
      35             :  * of the operands and assuming it preferrably should fit in memory.
      36             :  * Ofcourse, there may be intermediate structures being
      37             :  * used and the size of the result is not a priori known.
      38             :  * For this, we use a high watermark on the amount of
      39             :  * physical memory we pre-allocate for the claims.
      40             :  *
      41             :  * Instructions are eligible to be executed when the
      42             :  * total footprint of all concurrent executions stays below
      43             :  * the high-watermark or it is the single expensive
      44             :  * instruction being started.
      45             :  *
      46             :  * When we run out of memory, the instruction is delayed.
      47             :  * How long depends on the other instructions to free up
      48             :  * resources. The current policy simple takes a local
      49             :  * decision by delaying the instruction based on its
      50             :  * claim of the memory.
      51             :  */
      52             : 
      53             : /*
      54             :  * The memory claim is the estimate for the amount of memory hold.
      55             :  * Views are consider cheap and ignored.
      56             :  * Given that auxiliary structures are important for performance,
      57             :  * we use their maximum as an indication of the memory footprint.
      58             :  * An alternative would be to focus solely on the base table cost.
      59             :  * (Good for a MSc study)
      60             :  */
      61             : lng
      62    23430137 : getMemoryClaim(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int i, int flag)
      63             : {
      64             :         lng total = 0, itotal = 0, t;
      65             :         BAT *b;
      66             : 
      67             :         (void)mb;
      68    23430137 :         if (stk->stk[getArg(pci, i)].vtype == TYPE_bat) {
      69    15242735 :                 b = BATdescriptor( stk->stk[getArg(pci, i)].val.bval);
      70    15263665 :                 if (b == NULL)
      71             :                         return 0;
      72    14746763 :                 MT_lock_set(&b->theaplock);
      73    14750499 :                 if (flag && isVIEW(b)) {
      74           0 :                         MT_lock_unset(&b->theaplock);
      75           0 :                         BBPunfix(b->batCacheid);
      76           0 :                         return 0;
      77             :                 }
      78             : 
      79             :                 /* calculate the basic scan size */
      80    14750499 :                 total += BATcount(b) << b->tshift;
      81    14750499 :                 total += heapinfo(b->tvheap, b->batCacheid);
      82    14750499 :                 MT_lock_unset(&b->theaplock);
      83             : 
      84             :                 /* indices should help, find their maximum footprint */
      85    14760849 :                 MT_rwlock_rdlock(&b->thashlock);
      86    14753254 :                 itotal = hashinfo(b->thash, d->batCacheid);
      87    14753254 :                 MT_rwlock_rdunlock(&b->thashlock);
      88    14756369 :                 t = IMPSimprintsize(b);
      89             :                 if( t > itotal)
      90             :                         itotal = t;
      91             :                 /* We should also consider the ordered index size */
      92    14754376 :                 t = b->torderidx && b->torderidx != (Heap *) 1 ? (lng) b->torderidx->free : 0;
      93             :                 if( t > itotal)
      94             :                         itotal = t;
      95             :                 //total = total > (lng)(MEMORY_THRESHOLD ) ? (lng)(MEMORY_THRESHOLD ) : total;
      96    14754376 :                 BBPunfix(b->batCacheid);
      97             :                 if ( total < itotal)
      98             :                         total = itotal;
      99             :         }
     100             :         return total;
     101             : }
     102             : 
     103             : /*
     104             :  * The argclaim provides a hint on how much we actually may need to execute
     105             :  *
     106             :  * The client context also keeps bounds on the memory claim/client.
     107             :  * Surpassing this bound may be a reason to not admit the instruction to proceed.
     108             :  */
     109             : static MT_Lock admissionLock = MT_LOCK_INITIALIZER(admissionLock);
     110             : 
     111             : int
     112    16868251 : MALadmission_claim(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, lng argclaim)
     113             : {
     114             :         (void) mb;
     115             :         (void) pci;
     116             : 
     117             :         /* Check if we are allowed to allocate another worker thread for this client */
     118             :         /* It is somewhat tricky, because we may be in a dataflow recursion, each of which should be counted for.
     119             :          * A way out is to attach the thread count to the MAL stacks, which just limits the level
     120             :          * of parallism for a single dataflow graph.
     121             :          */
     122    16868251 :         if(cntxt->workerlimit && cntxt->workerlimit < stk->workers){
     123             :                 return -1;
     124             :         }
     125    16868251 :         if (argclaim == 0)
     126             :                 return 0;
     127             : 
     128     7852651 :         MT_lock_set(&admissionLock);
     129             :         /* Determine if the total memory resource is exhausted, because it is overall limitation.  */
     130     7882986 :         if ( memorypool <= 0){
     131             :                 // we accidently released too much memory or need to initialize
     132         255 :                 memorypool = (lng) MEMORY_THRESHOLD;
     133             :         }
     134             : 
     135             :         /* the argument claim is based on the input for an instruction */
     136     7882986 :         if ( memorypool > argclaim || stk->workers == 0 ) {
     137             :                 /* If we are low on memory resources, limit the user if he exceeds his memory budget
     138             :                  * but make sure there is at least one worker thread active */
     139     7882986 :                 if ( cntxt->memorylimit) {
     140           0 :                         if (argclaim + stk->memory > (lng) cntxt->memorylimit * LL_CONSTANT(1048576)){
     141           0 :                                 MT_lock_unset(&admissionLock);
     142           0 :                                 return -1;
     143             :                         }
     144           0 :                         stk->memory += argclaim;
     145             :                 }
     146     7882986 :                 memorypool -= argclaim;
     147     7882986 :                 stk->workers++;
     148     7882986 :                 stk->memory += argclaim;
     149     7882986 :                 if( mb->workers < stk->workers)
     150       19670 :                         mb->workers = stk->workers;
     151     7882986 :                 if( mb->memory < stk->memory)
     152       36015 :                         mb->memory = stk->memory;
     153     7882986 :                 MT_lock_unset(&admissionLock);
     154     7881326 :                 return 0;
     155             :         }
     156           0 :         MT_lock_unset(&admissionLock);
     157           0 :         return -1;
     158             : }
     159             : 
     160             : void
     161    16784349 : MALadmission_release(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, lng argclaim)
     162             : {
     163             :         /* release memory claimed before */
     164             :         (void) cntxt;
     165             :         (void) mb;
     166             :         (void) pci;
     167    16784349 :         if (argclaim == 0 )
     168             :                 return;
     169             : 
     170     7844352 :         MT_lock_set(&admissionLock);
     171     7882986 :         if ( cntxt->memorylimit) {
     172           0 :                 stk->memory -= argclaim;
     173             :         }
     174     7882986 :         memorypool += argclaim;
     175     7882986 :         if ( memorypool > (lng) MEMORY_THRESHOLD ){
     176           0 :                 memorypool = (lng) MEMORY_THRESHOLD;
     177             :         }
     178     7882986 :         stk->workers--;
     179     7882986 :         stk->memory -= argclaim;
     180     7882986 :         MT_lock_unset(&admissionLock);
     181     7880157 :         return;
     182             : }

Generated by: LCOV version 1.14