endurance test + multiple fixes

This commit is contained in:
voidlizard 2025-08-19 20:21:57 +03:00
parent 421be6ec9d
commit 4ab17008c4
8 changed files with 84 additions and 34 deletions

View File

@ -67,6 +67,7 @@ ncqStorageOpen fp upd = do
ncqStateUse <- newTVarIO mempty ncqStateUse <- newTVarIO mempty
ncqServiceSem <- atomically $ newTSem 1 ncqServiceSem <- atomically $ newTSem 1
ncqFileLock <- newTVarIO Nothing ncqFileLock <- newTVarIO Nothing
ncqCurrentFossils <- newTVarIO mempty
let ncq = NCQStorage{..} & upd let ncq = NCQStorage{..} & upd
@ -231,7 +232,7 @@ ncqTryLoadState me@NCQStorage{..} = do
if not corrupted then do if not corrupted then do
debug $ yellow "indexing" <+> pretty dataFile debug $ yellow "indexing" <+> pretty dataFile
ncqIndexFile me dataFile ncqIndexFile me Nothing dataFile
else do else do
o <- ncqFileTryRecover path o <- ncqFileTryRecover path

View File

@ -7,6 +7,8 @@ import HBS2.Storage.NCQ3.Internal.Types
import System.Posix.Files qualified as PFS import System.Posix.Files qualified as PFS
import Data.List qualified as List import Data.List qualified as List
{- HLINT ignore "Eta reduce" -}
removeFile :: MonadIO m => FilePath -> m () removeFile :: MonadIO m => FilePath -> m ()
removeFile fp = do removeFile fp = do
@ -49,29 +51,36 @@ ncqListFilesBy me@NCQStorage{..} filt = do
pure $ List.sortOn ( Down . fst ) r pure $ List.sortOn ( Down . fst ) r
ncqFindMinPairOfBy :: forall fa m . (ToFileName fa, MonadUnliftIO m)
=> NCQStorage
-> (fa -> Bool) -- ^ eligible predicate
-> [fa]
-> m (Maybe (NCQFileSize, fa, fa))
ncqFindMinPairOfBy sto eligible lst =
go lst Nothing
where
go :: [fa] -> Maybe (NCQFileSize, fa, fa) -> m (Maybe (NCQFileSize, fa, fa))
go (a:b:rest) best = do
best' <- if eligible a && eligible b
then do
let pa = ncqGetFileName sto a
let pb = ncqGetFileName sto b
s1 <- fsize pa
s2 <- fsize pb
let sz = fromIntegral (s1 + s2)
pure $ case best of
Nothing -> Just (sz, a, b)
Just (sz0,_,_) | sz<sz0 -> Just (sz, a, b)
_ -> best
else pure best
go (b:rest) best'
go _ best = pure best
fsize s = liftIO (PFS.getFileStatus s) <&> PFS.fileSize
ncqFindMinPairOf :: forall fa m . (ToFileName fa, MonadUnliftIO m) ncqFindMinPairOf :: forall fa m . (ToFileName fa, MonadUnliftIO m)
=> NCQStorage => NCQStorage
-> [fa] -> [fa]
-> m (Maybe (NCQFileSize, fa, fa)) -> m (Maybe (NCQFileSize, fa, fa))
ncqFindMinPairOf sto lst = do ncqFindMinPairOf sto lst = ncqFindMinPairOfBy sto (const True) lst
let files = fmap (\x -> (x, ncqGetFileName sto x)) lst
flip fix (files, Nothing) $ \next (fs, r) -> do
case fs of
[] -> pure r
[ _ ] -> pure r
( s1 : s2 : ss ) -> do
size1 <- fsize (snd s1)
size2 <- fsize (snd s2)
let size = fromIntegral $ size1 + size2
case r of
Nothing -> next (s2 : ss, Just (size, fst s1, fst s2) )
e@(Just (size0, _, _)) | size0 > size -> next (s2 : ss, Just (size, fst s1, fst s2) )
| otherwise -> next (s2:ss, e)
where fsize s = liftIO (PFS.getFileStatus s) <&> PFS.fileSize

View File

@ -1,3 +1,4 @@
{-# Language RecordWildCards #-}
module HBS2.Storage.NCQ3.Internal.Fossil where module HBS2.Storage.NCQ3.Internal.Fossil where
import HBS2.Storage.NCQ3.Internal.Prelude import HBS2.Storage.NCQ3.Internal.Prelude
@ -7,6 +8,7 @@ import HBS2.Storage.NCQ3.Internal.Index
import HBS2.Storage.NCQ3.Internal.State import HBS2.Storage.NCQ3.Internal.State
import Data.HashSet qualified as HS import Data.HashSet qualified as HS
import Data.HashMap.Strict qualified as HM
import Data.List qualified as List import Data.List qualified as List
import Data.ByteString.Lazy qualified as LBS import Data.ByteString.Lazy qualified as LBS
import Data.ByteString qualified as BS import Data.ByteString qualified as BS
@ -61,6 +63,7 @@ ncqFossilMergeStep :: forall m . MonadUnliftIO m
-> m Bool -> m Bool
ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pure $ callCC \exit -> do ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pure $ callCC \exit -> do
tmax <- liftIO getPOSIXTime >>= newTVarIO
debug "ncqFossilMergeStep" debug "ncqFossilMergeStep"
@ -69,7 +72,12 @@ ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pu
<&> fmap DataFile . HS.toList . ncqStateFiles <&> fmap DataFile . HS.toList . ncqStateFiles
<&> List.sortOn Down <&> List.sortOn Down
r' <- lift $ ncqFindMinPairOf me files NCQState{..} <- readTVarIO ncqState
let tss = ncqStateIndex & fmap (\(Down x, y) -> (y, realToFrac x :: POSIXTime)) & HM.fromList
cur <- readTVarIO ncqCurrentFossils
r' <- lift $ ncqFindMinPairOfBy me (\x -> not (HS.member (coerce x) cur)) files
r@(sumSize, f1, f2) <- ContT $ maybe1 r' (pure False) r@(sumSize, f1, f2) <- ContT $ maybe1 r' (pure False)
@ -84,6 +92,7 @@ ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pu
ContT $ bracket none $ const do ContT $ bracket none $ const do
removeFile outFile removeFile outFile
liftIO $ withBinaryFileAtomic outFile WriteMode $ \fwh -> do liftIO $ withBinaryFileAtomic outFile WriteMode $ \fwh -> do
fd <- handleToFd fwh fd <- handleToFd fwh
@ -96,8 +105,7 @@ ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pu
Nothing -> pure False Nothing -> pure False
Just (InMemory{}) -> pure False Just (InMemory{}) -> pure False
Just (InFossil fk oi si) -> do Just (InFossil fk oi si) -> do
let skip = fk > fik || (fk == fik && o < fromIntegral oi) let beWritten = fk == fik && o == fromIntegral oi
let beWritten = not skip
-- let c = if skip then green else id -- let c = if skip then green else id
-- when (si == ncqTombEntrySize) do -- when (si == ncqTombEntrySize) do
@ -107,9 +115,11 @@ ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pu
-- <+> "write" <+> c (pretty beWritten) -- <+> "write" <+> c (pretty beWritten)
atomically do atomically do
tj <- readTVar tmax
modifyTVar tmax (max (fromMaybe tj (HM.lookup fk tss)))
here <- readTVar already <&> HS.member k here <- readTVar already <&> HS.member k
let proceed = not here && beWritten let proceed = not here && beWritten
modifyTVar already (HS.insert k) when proceed $ modifyTVar already (HS.insert k)
pure proceed pure proceed
appendTailSection fd appendTailSection fd
@ -126,7 +136,8 @@ ncqFossilMergeStep me@NCQStorage{..} = withSem ncqServiceSem $ flip runContT pu
ncqStateUpdate me do ncqStateUpdate me do
ncqStateAddFact (P (PData f3 ss)) ncqStateAddFact (P (PData f3 ss))
lift $ ncqIndexFile me f3 ts <- readTVarIO tmax
lift $ ncqIndexFile me (Just ts) f3
ncqStateUpdate me do ncqStateUpdate me do
ncqStateDelDataFile (coerce f1) ncqStateDelDataFile (coerce f1)

View File

@ -84,8 +84,12 @@ ncqLocate :: MonadUnliftIO m => NCQStorage -> HashRef -> m (Maybe Location)
ncqLocate me href = ncqOperation me (pure Nothing) do ncqLocate me href = ncqOperation me (pure Nothing) do
ncqLocate_ True me href ncqLocate_ True me href
ncqIndexFile :: MonadUnliftIO m => NCQStorage -> DataFile FileKey -> m (Maybe FilePath) ncqIndexFile :: MonadUnliftIO m
ncqIndexFile n fk = runMaybeT do => NCQStorage
-> Maybe POSIXTime
-> DataFile FileKey
-> m (Maybe FilePath)
ncqIndexFile n ts' fk = runMaybeT do
let fp = toFileName fk & ncqGetFileName n let fp = toFileName fk & ncqGetFileName n
fki <- ncqGetNewFileKey n IndexFile fki <- ncqGetNewFileKey n IndexFile
@ -110,7 +114,7 @@ ncqIndexFile n fk = runMaybeT do
moveFile result dest moveFile result dest
stat <- liftIO $ PFS.getFileStatus dest stat <- liftIO $ PFS.getFileStatus dest
let ts = PFS.modificationTimeHiRes stat let ts = fromMaybe (PFS.modificationTimeHiRes stat) ts'
midx <- liftIO (nwayHashMMapReadOnly dest) midx <- liftIO (nwayHashMMapReadOnly dest)

View File

@ -49,7 +49,9 @@ ncqStorageRun ncq@NCQStorage{..} = flip runContT pure do
if not stop then STM.retry else pure Nothing if not stop then STM.retry else pure Nothing
maybe1 what none $ \(fk :: FileKey) -> do maybe1 what none $ \(fk :: FileKey) -> do
ncqIndexFile ncq (DataFile fk) >> loop ncqIndexFile ncq Nothing (DataFile fk)
atomically $ modifyTVar ncqCurrentFossils (HS.delete fk)
loop
let shLast = V.length ncqWriteOps - 1 let shLast = V.length ncqWriteOps - 1
spawnActivity $ pooledForConcurrentlyN_ (V.length ncqWriteOps) [0..shLast] $ \i -> do spawnActivity $ pooledForConcurrentlyN_ (V.length ncqWriteOps) [0..shLast] $ \i -> do
@ -212,6 +214,8 @@ ncqStorageRun ncq@NCQStorage{..} = flip runContT pure do
openNewDataFile = do openNewDataFile = do
fk <- ncqGetNewFileKey ncq DataFile fk <- ncqGetNewFileKey ncq DataFile
atomically $ modifyTVar ncqCurrentFossils (HS.insert fk)
ncqStateUpdate ncq (ncqStateAddDataFile fk) ncqStateUpdate ncq (ncqStateAddDataFile fk)
let fname = ncqGetFileName ncq (DataFile fk) let fname = ncqGetFileName ncq (DataFile fk)

View File

@ -15,10 +15,11 @@ import Data.HashMap.Strict qualified as HM
ncqLiveKeysSTM :: NCQStorage -> STM (HashSet FileKey) ncqLiveKeysSTM :: NCQStorage -> STM (HashSet FileKey)
ncqLiveKeysSTM NCQStorage{..} = do ncqLiveKeysSTM NCQStorage{..} = do
s0 <- readTVar ncqState s0 <- readTVar ncqState
merged <- readTVar ncqStateUse <&> (s0<>) . foldMap fst . HM.elems merged <- readTVar ncqStateUse <&> (s0<>) . foldMap fst . HM.elems
current <- readTVar ncqCurrentFossils
pure $ HS.fromList $ universeBi @_ @FileKey merged pure $ current <> HS.fromList (universeBi @_ @FileKey merged)
ncqLiveKeys :: forall m . MonadIO m => NCQStorage -> m (HashSet FileKey) ncqLiveKeys :: forall m . MonadIO m => NCQStorage -> m (HashSet FileKey)
ncqLiveKeys ncq = atomically $ ncqLiveKeysSTM ncq ncqLiveKeys ncq = atomically $ ncqLiveKeysSTM ncq

View File

@ -93,6 +93,7 @@ data NCQStorage =
, ncqState :: TVar NCQState , ncqState :: TVar NCQState
, ncqStateKey :: TVar FileKey , ncqStateKey :: TVar FileKey
, ncqStateUse :: TVar (HashMap FileKey (NCQState, TVar Int)) , ncqStateUse :: TVar (HashMap FileKey (NCQState, TVar Int))
, ncqCurrentFossils :: TVar (HashSet FileKey)
, ncqWrites :: TVar Int , ncqWrites :: TVar Int
, ncqWriteEMA :: TVar Double -- for writes-per-seconds , ncqWriteEMA :: TVar Double -- for writes-per-seconds
, ncqWriteQ :: TVar (Seq HashRef) , ncqWriteQ :: TVar (Seq HashRef)

View File

@ -0,0 +1,19 @@
test:root temp
test:dir:keep
set! w:getblk 100
set! w:storm 2
set! w:putblk 90
set! w:blk 65536
println "w:blk" w:blk
println "go"
; test:ncq3:endurance:inproc 200000
test:ncq3:endurance:inproc 300000