[Haskell-cafe] binary IO

Bulat Ziganshin bulatz at HotPOP.com
Tue Dec 27 11:52:49 EST 2005


Hello Joel,

Tuesday, December 27, 2005, 6:24:56 PM, you wrote:

>> no problem. my library handle about 10-15mb/s, and i think that
>> speed can  be doubled by using unboxed ints

JR> Would you like to present your version of the timeleak code plus  
JR> statistics from a test run?

do it yourself. i can help you if you want to try

JR> Please make sure that you have bots reading from the file all at the
JR> _at the same time_, not sequentially.

you must decide what is your problem - unpickling, multithreading,
someone else. are you waiting what i can do it for you? :)

>> these delays says nothing about speed. you are mixing two things -
>> your end goal is to make delays short, but your instrument - speeds of
>> different processes and to decide what you need to optimize you must
>> calc these speeds separately. without it, your "optimization" is just
>> random game

JR> I need to reduce the overall delay. Individual delays do me no good.  
JR> Show me a 1-2s delay in the "timeleak" unstuff code then I will be  
JR> convinced.

if, for example, the game work too slow on your computer, you must
decide what is a problem - CPU, graphics card, lack of memory or
something else and upgrade this detail first. you can, for example,
buy the graphics card for $1000 but still have just memory swapping as
main problem. believe you or not, but the same holds true in
programming - the key to right optimization is to find "bottlenecks",
not optimizing everything you can. spending several weeks to random
optimization is like buying a gold computer case trying to speed up
the game :)

sorry, but your negative results say more about you than about GHC or
Haskell. you are working 3 months but still don't know what is a
bottleneck in your program!

>> JR> Each bot is given 5, 15 or 35 seconds to respond by the poker  
>> server
>>
>> so you don't need to create complex timer thread machinery, just use 3
>> threads which proceed requests in FIFO order

JR> Socket read is a blocking operation. An easy way to handle a blocking  
JR> read is to launch a thread that reads from a socket and posts packets  
JR> somewhere once they are retrieved. I cannot handle large numbers of  
JR> bots if I block on a socket read.

i say about timer thread. you created complex design using Map to find
first event to complete, but instead you can use just 3 timer threads,
each one serving a fixed timing interval. each thread will serve
requests just in the order they arrive

>> i think that you will get just the same problems as with Haskell and
>> forced to switch back because it's easier to low-level optimize in
>> Haskell than in Erlang

JR> Absolutely not. I wrote a poker server in Erlang (see the openpoker/

it's strange what your pocker server don't required the same pickler
library as client. this 50k structure is constructed on the server
end, i'm right?

JR> Because I have 150 records with a lot of fields and writing separate
JR> code for pickling and unpickling is a nightmare?

these concrete definitions are nightmare? :)  let's compare them with
that clear and obvious code:

puTableInfo :: PU TableInfo
puTableInfo = 
    sequ ti_1 endian64
         (\a -> sequ ti_2 endian16
          (\b -> sequ ti_3 endian16
           (\c -> sequ ti_4 byte
            (\d -> sequ ti_5 wstring
             (\e -> sequ ti_6 endian32
              (\f -> sequ ti_7 (enum endian16 :: PU GameType)
              ........
                            (\w -> lift $!
                                   TableInfo a b c d e f g
                                             h i j k l m n 
                                               o p q r v w
                               ))))))))))))))))))))


>> for example, one of these solutions looks like this:
>>
>> instance Binary TableInfo where
>>   put_ bh (TableInfo a b c d) = put_ bh (a,b,c,d)
>>   get bh = do (a,b,c,d) <- get bh; return (TableInfo a b c d)
>>
>> instance Binary GameType where
>>   put_ bh = putWord16 bh . fromEnum
>>   get = liftM toEnum . getWord16

JR> This gets tedious very quickly.

no, type classes allow code economy comparing to combinators you use.
you need to define only one time how to process each type. just one
definition for all lists, one for all Word16, one for all GameType and
so on. all the records defined by the easy code like this one for
TableInfo

-- 
Best regards,
 Bulat                            mailto:bulatz at HotPOP.com





More information about the Haskell-Cafe mailing list