mirror of
https://github.com/urbit/shrub.git
synced 2024-12-20 01:01:37 +03:00
king: psqueue lane cache; enhance FromNoun TH SCCs
This commit is contained in:
parent
ae0f5f0242
commit
0c96d9d6e8
@ -2,31 +2,53 @@ module Urbit.Vere.Ames.LaneCache (cache) where
|
|||||||
|
|
||||||
import Urbit.Prelude
|
import Urbit.Prelude
|
||||||
|
|
||||||
|
import qualified Data.HashPSQ as P
|
||||||
|
|
||||||
import Urbit.Noun.Time
|
import Urbit.Noun.Time
|
||||||
|
|
||||||
expiry :: Gap
|
expiry :: Gap
|
||||||
expiry = (2 * 60) ^. from secs
|
expiry = (2 * 60) ^. from secs
|
||||||
|
|
||||||
|
-- | An "upside down" time for use as a priority.
|
||||||
|
newtype New = New Wen
|
||||||
|
deriving newtype (Eq, Ord)
|
||||||
|
|
||||||
|
new = New . negate
|
||||||
|
wen (New w) = negate w
|
||||||
|
|
||||||
|
-- | Given a new, find an older new corresponding to `expiry` ago.
|
||||||
|
lag :: New -> New
|
||||||
|
lag n = new (addGap (wen n) expiry)
|
||||||
|
|
||||||
cache :: forall a b m n
|
cache :: forall a b m n
|
||||||
. (Ord a, MonadIO m, MonadIO n)
|
. (Ord a, Hashable a, MonadIO m, MonadIO n)
|
||||||
=> (a -> m b)
|
=> (a -> m b)
|
||||||
-> n (a -> m b)
|
-> n (a -> m b)
|
||||||
cache act = do
|
cache act = do
|
||||||
cas <- newTVarIO (mempty :: Map a (Wen, b))
|
cas <- newTVarIO (P.empty :: P.HashPSQ a New b)
|
||||||
|
|
||||||
let fun x = lookup x <$> readTVarIO cas >>= \case
|
let fun x = P.lookup x <$> readTVarIO cas >>= \case
|
||||||
Nothing -> thru
|
Nothing -> thru
|
||||||
Just (t, v) -> do
|
Just (n, v) -> do
|
||||||
|
let t = wen n
|
||||||
t' <- io now
|
t' <- io now
|
||||||
if gap t' t > expiry
|
if gap t' t > expiry
|
||||||
then thru
|
then thru
|
||||||
else pure v
|
else pure v
|
||||||
where
|
where
|
||||||
|
-- Insert a key into the map, simultaneously removing *all* stale
|
||||||
|
-- entries. Since insertion is linear in the size of the map,
|
||||||
|
-- presumably it's not horrible to do it this way. The alternative
|
||||||
|
-- would be to have a thread doing a purge every 10s or something, and
|
||||||
|
-- then we'd have to be in RAcquire.
|
||||||
|
up :: a -> New -> b -> P.HashPSQ a New b -> P.HashPSQ a New b
|
||||||
|
up k n v ps = P.insert k n v
|
||||||
|
$ snd $ P.atMostView (lag n) ps
|
||||||
thru :: m b
|
thru :: m b
|
||||||
thru = do
|
thru = do
|
||||||
t <- io now
|
n <- new <$> io now
|
||||||
v <- act x
|
v <- act x
|
||||||
atomically $ modifyTVar' cas (insertMap x (t, v))
|
atomically $ modifyTVar' cas $ up x n v
|
||||||
pure v
|
pure v
|
||||||
|
|
||||||
pure fun
|
pure fun
|
||||||
|
@ -79,6 +79,7 @@ dependencies:
|
|||||||
- pretty-show
|
- pretty-show
|
||||||
- primitive
|
- primitive
|
||||||
- process
|
- process
|
||||||
|
- psqueues
|
||||||
- QuickCheck
|
- QuickCheck
|
||||||
- racquire
|
- racquire
|
||||||
- random
|
- random
|
||||||
|
@ -30,6 +30,7 @@ newtype Parser a = Parser {
|
|||||||
runParser :: forall r. ParseStack -> Failure r -> Success a r -> r
|
runParser :: forall r. ParseStack -> Failure r -> Success a r -> r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{-# INLINE named #-} -- keep out of the cost centers
|
||||||
named :: Text -> Parser a -> Parser a
|
named :: Text -> Parser a -> Parser a
|
||||||
named nm (Parser cb) =
|
named nm (Parser cb) =
|
||||||
Parser $ \path kf ks -> cb (nm:path) kf ks
|
Parser $ \path kf ks -> cb (nm:path) kf ks
|
||||||
|
@ -105,9 +105,14 @@ deriveToNoun tyName = do
|
|||||||
|
|
||||||
addErrTag :: String -> Exp -> Exp
|
addErrTag :: String -> Exp -> Exp
|
||||||
addErrTag tag exp =
|
addErrTag tag exp =
|
||||||
InfixE (Just $ AppE (VarE 'named) str) (VarE (mkName ".")) (Just exp)
|
-- This spurious let is inserted so we can get better cost center data
|
||||||
|
-- during heap profiling.
|
||||||
|
LetE [ValD (VarP nom) (NormalB bod) []] (VarE nom)
|
||||||
where
|
where
|
||||||
|
-- XX arguably we should use newName rather than mkName here
|
||||||
|
nom = mkName $ "named_" ++ filter C.isAlphaNum tag
|
||||||
str = LitE $ StringL tag
|
str = LitE $ StringL tag
|
||||||
|
bod = InfixE (Just $ AppE (VarE 'named) str) (VarE (mkName ".")) (Just exp)
|
||||||
|
|
||||||
deriveFromNoun :: Name -> Q [Dec]
|
deriveFromNoun :: Name -> Q [Dec]
|
||||||
deriveFromNoun tyName = do
|
deriveFromNoun tyName = do
|
||||||
|
@ -31,7 +31,7 @@ import Urbit.Noun.Convert
|
|||||||
import Urbit.Noun.Core
|
import Urbit.Noun.Core
|
||||||
import Urbit.Noun.TH
|
import Urbit.Noun.TH
|
||||||
|
|
||||||
import Data.LargeWord (LargeKey, Word128, Word256)
|
import Data.LargeWord (LargeKey(..), Word128, Word256)
|
||||||
import GHC.Exts (chr#, isTrue#, leWord#, word2Int#)
|
import GHC.Exts (chr#, isTrue#, leWord#, word2Int#)
|
||||||
import GHC.Natural (Natural)
|
import GHC.Natural (Natural)
|
||||||
import GHC.Types (Char(C#))
|
import GHC.Types (Char(C#))
|
||||||
@ -602,6 +602,9 @@ newtype Ship = Ship Word128 -- @p
|
|||||||
instance Show Ship where
|
instance Show Ship where
|
||||||
show = show . patp . fromIntegral
|
show = show . patp . fromIntegral
|
||||||
|
|
||||||
|
instance Hashable Ship where
|
||||||
|
hashWithSalt s (Ship (LargeKey a b)) = s `hashWithSalt` a `hashWithSalt` b
|
||||||
|
|
||||||
|
|
||||||
-- Path ------------------------------------------------------------------------
|
-- Path ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user