public void updateCPUInfo(Result result) { if (prevUpTime > 0L && result.upTime > prevUpTime) { // elapsedCpu is in ns and elapsedTime is in ms. long elapsedCpu = result.processCpuTime - prevProcessCpuTime; long elapsedTime = result.upTime - prevUpTime; // cpuUsage could go higher than 100% because elapsedTime // and elapsedCpu are not fetched simultaneously. Limit to // 99% to avoid Plotter showing a scale from 0% to 200%. float cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * result.nCPUs)); getPlotter() .addValues(result.timeStamp, Math.round(cpuUsage * Math.pow(10.0, CPU_DECIMALS))); getInfoLabel() .setText( Resources.format( Messages.CPU_USAGE_FORMAT, String.format("%." + CPU_DECIMALS + "f", cpuUsage))); } this.prevUpTime = result.upTime; this.prevProcessCpuTime = result.processCpuTime; }
// Set K/V cache goals. // Allow (or disallow) allocations. // Called from the Cleaner, when "cacheUsed" has changed significantly. // Called from any FullGC notification, and HEAP/POJO_USED changed. // Called on any OOM allocation public static void set_goals(String msg, boolean oom, long bytes) { // Our best guess of free memory, as of the last GC cycle final long heapUsed = Boot.HEAP_USED_AT_LAST_GC; final long timeGC = Boot.TIME_AT_LAST_GC; final long freeHeap = MEM_MAX - heapUsed; assert freeHeap >= 0 : "I am really confused about the heap usage; MEM_MAX=" + MEM_MAX + " heapUsed=" + heapUsed; // Current memory held in the K/V store. final long cacheUsage = myHisto.histo(false)._cached; // Our best guess of POJO object usage: Heap_used minus cache used final long pojoUsedGC = Math.max(heapUsed - cacheUsage, 0); // Block allocations if: // the cache is > 7/8 MEM_MAX, OR // we cannot allocate an equal amount of POJOs, pojoUsedGC > freeHeap. // Decay POJOS_USED by 1/8th every 5 sec: assume we got hit with a single // large allocation which is not repeating - so we do not need to have // double the POJO amount. // Keep at least 1/8th heap for caching. // Emergency-clean the cache down to the blocking level. long d = MEM_CRITICAL; // Decay POJO amount long p = pojoUsedGC; long age = (System.currentTimeMillis() - timeGC); // Age since last FullGC age = Math.min(age, 10 * 60 * 1000); // Clip at 10mins while ((age -= 5000) > 0) p = p - (p >> 3); // Decay effective POJO by 1/8th every 5sec d -= 2 * p - bytes; // Allow for the effective POJO, and again to throttle GC rate d = Math.max(d, MEM_MAX >> 3); // Keep at least 1/8th heap H2O.Cleaner.DESIRED = d; String m = ""; if (cacheUsage > H2O.Cleaner.DESIRED) { m = (CAN_ALLOC ? "Blocking! " : "blocked: "); if (oom) setMemLow(); // Stop allocations; trigger emergency clean Boot.kick_store_cleaner(); } else { // Else we are not *emergency* cleaning, but may be lazily cleaning. if (!CAN_ALLOC) m = "Unblocking:"; else m = "MemGood: "; setMemGood(); if (oom) // Confused? OOM should have FullGCd should have set low-mem goals Log.warn( Sys.CLEAN, "OOM but no FullGC callback? MEM_MAX = " + MEM_MAX + ", DESIRED = " + d + ", CACHE = " + cacheUsage + ", p = " + p + ", bytes = " + bytes); } // No logging if under memory pressure: can deadlock the cleaner thread if (Log.flag(Sys.CLEAN)) { String s = m + msg + ", HEAP_LAST_GC=" + (heapUsed >> 20) + "M, KV=" + (cacheUsage >> 20) + "M, POJO=" + (pojoUsedGC >> 20) + "M, free=" + (freeHeap >> 20) + "M, MAX=" + (MEM_MAX >> 20) + "M, DESIRED=" + (H2O.Cleaner.DESIRED >> 20) + "M" + (oom ? " OOM!" : " NO-OOM"); if (CAN_ALLOC) Log.debug(Sys.CLEAN, s); else Log.unwrap(System.err, s); } }