module Database.VCache.Stats
( VCacheStats(..)
, vcacheStats
) where
import Data.IORef
import Control.Concurrent.MVar
import qualified Data.Map.Strict as Map
import Database.LMDB.Raw
import Database.VCache.Types
data VCacheStats = VCacheStats
{ vcstat_file_size :: !Int
, vcstat_vref_count :: !Int
, vcstat_pvar_count :: !Int
, vcstat_root_count :: !Int
, vcstat_mem_vrefs :: !Int
, vcstat_mem_pvars :: !Int
, vcstat_mem_addrs :: !Int
, vcstat_eph_count :: !Int
, vcstat_alloc_pos :: !Address
, vcstat_alloc_count :: !Int
, vcstat_cache_count :: !Int
, vcstat_cache_limit :: !Int
, vcstat_cache_size :: !Int
, vcstat_gc_count :: !Int
, vcstat_write_pvars :: !Int
, vcstat_write_sync :: !Int
, vcstat_write_frames :: !Int
} deriving (Show, Ord, Eq)
vcacheStats :: VSpace -> IO VCacheStats
vcacheStats vc = withRdOnlyTxn vc $ \ txnStat -> do
let db = vcache_db_env vc
envInfo <- mdb_env_info db
envStat <- mdb_env_stat db
dbMemStat <- mdb_stat' txnStat (vcache_db_memory vc)
rootStat <- mdb_stat' txnStat (vcache_db_vroots vc)
hashStat <- mdb_stat' txnStat (vcache_db_caddrs vc)
ephStat <- mdb_stat' txnStat (vcache_db_refct0 vc)
memory <- readMVar (vcache_memory vc)
gcCount <- readIORef (vcache_gc_count vc)
wct <- readIORef (vcache_ct_writes vc)
cLimit <- readIORef (vcache_climit vc)
cSizeEst <- readIORef (vcache_csize vc)
let fileSize = (1 + (fromIntegral $ me_last_pgno envInfo))
* (fromIntegral $ ms_psize envStat)
let vrefCount = (fromIntegral $ ms_entries hashStat)
let pvarCount = (fromIntegral $ ms_entries dbMemStat) vrefCount
let ephCount = (fromIntegral $ ms_entries ephStat)
let rootCount = (fromIntegral $ ms_entries rootStat)
let cvrefsCount = Map.foldl' (\ a b -> a + Map.size b) 0 (mem_cvrefs memory)
let evrefsCount = Map.foldl' (\ a b -> a + Map.size b) 0 (mem_evrefs memory)
let cacheSizeBytes = ceiling $ fromIntegral (Map.size (mem_cvrefs memory))
* csze_addr_size cSizeEst
let memVRefsCount = cvrefsCount + evrefsCount
let memPVarsCount = Map.size (mem_pvars memory)
let memAddrsCount = Map.size (mem_pvars memory)
+ Map.size (mem_cvrefs memory)
+ Map.size (mem_evrefs memory)
let allocPos = alloc_new_addr (mem_alloc memory)
let allocDiff = allocPos vcache_alloc_init vc
let allocCount = fromIntegral $ allocDiff `div` 2
return $ VCacheStats
{ vcstat_file_size = fileSize
, vcstat_vref_count = vrefCount
, vcstat_pvar_count = pvarCount
, vcstat_root_count = rootCount
, vcstat_mem_vrefs = memVRefsCount
, vcstat_mem_pvars = memPVarsCount
, vcstat_mem_addrs = memAddrsCount
, vcstat_eph_count = ephCount
, vcstat_alloc_pos = allocPos
, vcstat_alloc_count = allocCount
, vcstat_cache_count = cvrefsCount
, vcstat_cache_limit = cLimit
, vcstat_cache_size = cacheSizeBytes
, vcstat_write_sync = wct_sync wct
, vcstat_write_pvars = wct_pvars wct
, vcstat_write_frames = wct_frames wct
, vcstat_gc_count = gcCount
}