How can I improve the performance of creating a string for output in Haskell

I have a program that I'm trying to do faster, mainly in order to speed up learning Haskell. For comparison, I wrote the same C program and improved the speed 4 times. I expected faster with C, but such a difference makes me think that something is wrong with me.

So, I have profiled Haskell code, and more than 50% of the time is spent formatting Stringfor output. So only this section takes up more than my entire program in C. The function is similar to this function:

display :: POSIXTime -> [(Int, Centi)] -> IO()
display t l = putStrLn $ t_str ++ " " ++ l_str
    where
        t_str = show . timeToTimeOfDay . unsafeCoerce $ (t `mod` posixDayLength)
        l_str = intercalate " " $ map displayPair l
        displayPair (a,b) = show a ++ " " ++ show b

Notes on the code: unsafeCoerceconsists in converting NominalDiffTimeto DiffTimewhich are of the same type, but it is faster than the toRational . fromRationalone I used.

Centidefined in Data.Fixedand is a two decimal place

TimeOfDay such as you would expect only a few hours, minutes and seconds (accurate to a picosecond).

`mod` posixDayLength is that we just get the time of day, ignoring what day (because that's all I care about ... it's from a timestamp, and I know that it should be today - I just don't care what time today!).

I tried to use ShowS (String -> String)to concatenate the results, and this happens much faster.

I tried using Data.Text, but it makes the code slower (presumably spending too much time packing).

I used putStrLnin a separate function, but it is faster here (less thanks is built in, but why?).

Haskell, ?

+4
1

String ByteString, Text. Builder. [ByteString] .

:

import Data.Monoid
display :: POSIXTime -> [(Int, Centi)] -> IO()
display t l = hPutBuilder stdout $ t_str <> space <> l_str
    where
        space = (byteString . pack) " "
        t_str = (byteString . pack . show . timeToTimeOfDay . unsafeCoerce) $ (t `mod` posixDayLength)
        l_str = foldr <> space $ map displayPair l
        displayPair (a,b) = intDec a <> space <> (byteString . pack . show) b

, O (1) . , . , , ... , , ( ?).

0

Source: https://habr.com/ru/post/1540357/


All Articles