// releaseMemory releases memory previously successfully registered // via reserveMemory(). func (mm *MemoryMonitor) releaseMemory(ctx context.Context, sz int64) { mm.mu.Lock() defer mm.mu.Unlock() if mm.mu.curAllocated < sz { panic(fmt.Sprintf("%s: no memory to release, current %d, free %d", mm.name, mm.mu.curAllocated, sz)) } mm.mu.curAllocated -= sz if mm.curBytesCount != nil { mm.curBytesCount.Dec(sz) } mm.adjustBudget(ctx) if log.V(2) { // We avoid VEventf here because we want to avoid computing the // trace string if there is nothing to log. log.Infof(ctx, "%s: now at %d bytes (-%d) - %s", mm.name, mm.mu.curAllocated, sz, util.GetSmallTrace(3)) } }
// reserveMemory declares an allocation to this monitor. An error is // returned if the allocation is denied. func (mm *MemoryMonitor) reserveMemory(ctx context.Context, x int64) error { mm.mu.Lock() defer mm.mu.Unlock() if mm.mu.curAllocated > mm.mu.curBudget.curAllocated+mm.reserved.curAllocated-x { if err := mm.increaseBudget(ctx, x); err != nil { return err } } mm.mu.curAllocated += x if mm.curBytesCount != nil { mm.curBytesCount.Inc(x) } if mm.mu.maxAllocated < mm.mu.curAllocated { mm.mu.maxAllocated = mm.mu.curAllocated } // Report "large" queries to the log for further investigation. if mm.mu.curAllocated > mm.noteworthyUsageBytes { // We only report changes in binary magnitude of the size. This // is to limit the amount of log messages when a size blowup is // caused by many small allocations. if util.RoundUpPowerOfTwo(mm.mu.curAllocated) != util.RoundUpPowerOfTwo(mm.mu.curAllocated-x) { log.Infof(ctx, "%s: memory usage increases to %s (+%d)", mm.name, humanizeutil.IBytes(mm.mu.curAllocated), x) } } if log.V(2) { // We avoid VEventf here because we want to avoid computing the // trace string if there is nothing to log. log.Infof(ctx, "%s: now at %d bytes (+%d) - %s", mm.name, mm.mu.curAllocated, x, util.GetSmallTrace(3)) } return nil }