[Haskell-cafe] Battling laziness

Joel Reymont joelr1 at gmail.com
Fri Dec 16 06:44:00 EST 2005


Folks,

I have a huge space leak someplace and I suspect this code. The  
SrvServerInfo data structure is something like 50K compressed or  
uncompressed byte data before unpickling. My thousands of bots issue  
this request at least once and I almost run out of memory with 100  
bots on a 1Gb machine on FreeBSD. Do I need deepSeq somewhere below?

This is the read.

read :: Handle -> (SSL, BIO, BIO) -> IO Command
read h _ =
     do sa <- emptyByteArray 4
        hGetArray h sa 4
        (size', _) <- unpickle endian32 sa 0
        let size = fromIntegral $ size' - 4
        packet <- emptyByteArray size
        hGetArray h packet size
        unstuff packet 0

I suspect that I need to deepSeq cmd'' instead of return $! cmd''

unstuff :: MutByteArray -> Index -> IO Command
unstuff array ix =
     do (kind, ix1) <- unpickle puCmdType array ix
        (cmd', _) <- unpickle (puCommand kind) array ix1
        case cmd' of
          InvalidCommand -> do fail $ "unstuff: Cannot parse " ++  
show array
          SrvCompressedCommands sz bytes ->
              do bytes' <- uncompress bytes (fromIntegral sz)
                 cmd'' <- unstuff bytes' 4
                 return $! cmd''
          _ -> return cmd'

This is where the list of active tables is converted to a table id  
list of [Word32].

pickTable _ filters (Cmd cmd@(SrvServerInfo {})) =
     do let tables = filter (tableMatches filters) $ activeTables cmd
            ids = map tiTableID tables
        case tables of
          [] -> fail $ "pickTable: No tables found: " ++ show filters
          _ ->
              do pop
                 stoptimer "pickTable"
                 return $! Eat $! Just $! Custom $! Tables $! ids

This is where the table id list of [Word32] is consumed.

takeEmptySeat _ aff_id _ (Custom (Tables ids@(table:rest))) =
     do trace 85 $ "takeEmptySeat: " ++ show (length ids)
                  ++ " tables found"
        trace 100 $ "takeEmptySeat: tables: " ++ showTables ids
        trace 85 $ "takeEmptySeat: trying table# " ++ show table
        w <- get
        put_ $ w { tables_to_try = rest }
        push "goToTable" $ goToTable table aff_id
        -- kick off goToTable
        return $ Eat $ Just Go

This is the SrvServerInfo structure.

     | SrvServerInfo
       {
        activeTables :: ![TableInfo], -- Word16/
        removedTables :: ![Word32], -- Word16/
        version :: !Int32
       }

And this is the table info itself.

data TableInfo = TableInfo
     {
      tiAvgPot :: !Word64,
      tiNumPlayers :: !Word16,
      tiWaiting :: !Word16,
      tiPlayersFlop :: !Word8,
      tiTableName :: !String,
      tiTableID :: !Word32,
      tiGameType :: !GameType,
      tiInfoMaxPlayers :: !Word16,
      tiIsRealMoneyTable :: !Bool,
      tiLowBet :: !Word64,
      tiHighBet :: !Word64,
      tiMinStartMoney :: !Word64,
      tiMaxStartMoney :: !Word64,
      tiGamesPerHour :: !Word16,
      tiTourType :: !TourType,
      tiTourID :: !Word32,
      tiBetType :: !BetType,
      tiCantReturnLess :: !Word32,
      tiAffiliateID :: ![Word8],
      tiLangID :: !Word32
     }  deriving (Show, Typeable)

	Thanks, Joel

--
http://wagerlabs.com/







More information about the Haskell-Cafe mailing list