From 3a166240c7d2dce21e98fceb1a091ccaab5e5b3b Mon Sep 17 00:00:00 2001 From: Julian P Samaroo Date: Mon, 1 Apr 2024 14:33:19 -0700 Subject: [PATCH 1/2] Make memory query period programmable --- src/storage.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storage.jl b/src/storage.jl index bab92a6..47c7503 100644 --- a/src/storage.jl +++ b/src/storage.jl @@ -185,7 +185,7 @@ end QueriedMemInfo() = QueriedMemInfo(UInt64(0), UInt64(0)) const QUERY_MEM_AVAILABLE = Ref(QueriedMemInfo()) const QUERY_MEM_CAPACITY = Ref(QueriedMemInfo()) -const QUERY_MEM_PERIOD = 10 * 1000^2 # 10ms +const QUERY_MEM_PERIOD = Ref(10 * 1000^2) # 10ms const QUERY_MEM_OVERRIDE = ScopedValue(false) function _query_mem_periodically(kind::Symbol) if !(kind in (:available, :capacity)) @@ -198,7 +198,7 @@ function _query_mem_periodically(kind::Symbol) end mem_info = mem_bin[] now_ns = time_ns() - if QUERY_MEM_OVERRIDE[] || mem_info.last_ns < now_ns - QUERY_MEM_PERIOD + if QUERY_MEM_OVERRIDE[] || mem_info.last_ns < now_ns - QUERY_MEM_PERIOD[] if kind == :available new_mem_info = QueriedMemInfo(free_memory(), now_ns) elseif kind == :capacity From 1752f9983bdddf352fdfb89dd18884fa38875178 Mon Sep 17 00:00:00 2001 From: Julian P Samaroo Date: Mon, 1 Apr 2024 14:33:52 -0700 Subject: [PATCH 2/2] Optimizations for memory queries --- src/MemPool.jl | 1 + src/clock.jl | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ src/datastore.jl | 7 +++++- src/storage.jl | 2 +- 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/clock.jl diff --git a/src/MemPool.jl b/src/MemPool.jl index 98d0219..751fab4 100644 --- a/src/MemPool.jl +++ b/src/MemPool.jl @@ -54,6 +54,7 @@ approx_size(f::FileRef) = f.size include("io.jl") include("lock.jl") +include("clock.jl") include("datastore.jl") """ diff --git a/src/clock.jl b/src/clock.jl new file mode 100644 index 0000000..8857623 --- /dev/null +++ b/src/clock.jl @@ -0,0 +1,59 @@ +## +# This file is a part of MemPool.jl. License is MIT +# +# Based upon https://github.com/google/benchmark, which is licensed under Apache v2: +# https://github.com/google/benchmark/blob/master/LICENSE +# +# In compliance with the Apache v2 license, here are the original copyright notices: +# Copyright 2015 Google Inc. All rights reserved. +## + +struct TimeSpec + tv_sec::UInt64 # time_t + tv_nsec::UInt64 +end + +maketime(ts) = ts.tv_sec * UInt(1e9) + ts.tv_nsec + +# From bits/times.h on a Linux system +# Check if those are the same on BSD +if Sys.islinux() + const CLOCK_MONOTONIC = Cint(1) + const CLOCK_PROCESS_CPUTIME_ID = Cint(2) + const CLOCK_THREAD_CPUTIME_ID = Cint(3) + const CLOCK_MONOTONIC_COARSE = Cint(6) +elseif Sys.isfreebsd() # atleast on FreeBSD 11.1 + const CLOCK_MONOTONIC = Cint(4) + const CLOCK_PROCESS_CPUTIME_ID = Cint(14) +elseif Sys.isapple() # Version 10.12 required + const CLOCK_MONOTONIC = Cint(6) + const CLOCK_PROCESS_CPUTIME_ID = Cint(12) +end + +@static if Sys.isunix() +@inline function clock_gettime(cid) + ts = Ref{TimeSpec}() + ccall(:clock_gettime, Cint, (Cint, Ref{TimeSpec}), cid, ts) + return ts[] +end + +@inline function realtime() + maketime(clock_gettime(CLOCK_MONOTONIC)) +end + +@inline function cputime() + maketime(clock_gettime(CLOCK_PROCESS_CPUTIME_ID)) +end +end + +@static if Sys.islinux() +@inline function cputhreadtime() + maketime(clock_gettime(CLOCK_THREAD_CPUTIME_ID)) +end +@inline function fasttime() + maketime(clock_gettime(CLOCK_MONOTONIC_COARSE)) +end +else +@inline cputhreadtime() = time_ns() # HACK +@inline fasttime() = time_ns() # HACK +end diff --git a/src/datastore.jl b/src/datastore.jl index 0a66b8a..80c64ec 100644 --- a/src/datastore.jl +++ b/src/datastore.jl @@ -388,6 +388,11 @@ satisfied, or `max_sweeps` number of cycles have elapsed. function ensure_memory_reserved(size::Integer=0; max_sweeps::Integer=5) sat_sub(x::T, y::T) where T = x < y ? zero(T) : x-y + # Do a quick (cached) check, to optimize for many calls to this function when memory isn't tight + if Int(storage_available(CPURAMResource())) - size >= MEM_RESERVED[] + return + end + # Check whether the OS is running tight on memory sweep_ctr = 0 while true @@ -396,7 +401,7 @@ function ensure_memory_reserved(size::Integer=0; max_sweeps::Integer=5) end || break # We need more memory! Let's encourage the GC to clear some memory... - sweep_start = time_ns() + sweep_start = fasttime() mem_used = with(QUERY_MEM_OVERRIDE => true) do storage_utilized(CPURAMResource()) end diff --git a/src/storage.jl b/src/storage.jl index 47c7503..2b3e6aa 100644 --- a/src/storage.jl +++ b/src/storage.jl @@ -197,7 +197,7 @@ function _query_mem_periodically(kind::Symbol) QUERY_MEM_CAPACITY end mem_info = mem_bin[] - now_ns = time_ns() + now_ns = fasttime() if QUERY_MEM_OVERRIDE[] || mem_info.last_ns < now_ns - QUERY_MEM_PERIOD[] if kind == :available new_mem_info = QueriedMemInfo(free_memory(), now_ns)