[Haskell-cafe] Battling laziness

Simon Marlow simonmar at microsoft.com
Fri Dec 16 06:53:49 EST 2005


What does ordinary heap profiling (-hc, -hd, -hy) tell you about what's
in the heap?  These options should work fine with STM.

Cheers,
	Simon

On 16 December 2005 11:44, Joel Reymont wrote:

> 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



More information about the Haskell-Cafe mailing list