Question: Recently me and my friends were benchmarking different programming languages. As I'm learning Haskell lately, I wanted to show that a functional language will perform nearly as good as C with simpler code. But the code I pasted below, compiled with GHC's -O3 option, was executing about 1.6 s on my machine. Equivalent scripts in Python and Ruby executed faster (it was a simple for loop).

```
import System.IO

saveLine fh x = hPutStrLn fh $ show x ++ "\t" ++ show (x^2)

main = do
    fh <- openFile "haskell.txt" WriteMode
    mapM (saveLine fh) [1..999999]
    hClose fh

```

You can check out [codes in other languages here](http://pastebin.com/7T5hpXCq) (I wrote only the ones in Python and Ruby).

The question is - how to make it run faster?

Answer: 
First off, benchmarks where you perform some simple calculation and write each result to a file are *only useful to test the IO system*. They say nothing at all about computation efficiency, because most of the time is spent with file accesses. If you want to compare how fast languages are for calculating things, you need to do something processor-intensive (e.g. summing all those square values) and then output only that single result.

If you actually want to compare file-output performance, the main problem in Haskell is its `String` type. It's a simple list of characters, handy for doing simple text manipulations by hand but with ridiculous overhead for standard tasks. For faster performance, use [bytestrings](http://hackage.haskell.org/package/bytestring) or [`Text`](http://hackage.haskell.org/package/text). Specifically, you need a faster alternative to `show`. Check out the [text-format package](http://hackage.haskell.org/package/text-format).
First, you should avoid using **-O3**, because it could sometimes break your code ( even in gcc ). Just stick to **-O2**.

---

Second, **Haskell Strings are [really slow](https://honza.ca/2012/10/haskell-strings)**.

**But, [there are faster alternatives](https://wiki.haskell.org/Performance/Strings)** - and for me, the easiest one is to use is Data.ByteString ( [little and old tutorial](http://agentzh.blogspot.com/2008/06/optimizing-haskell-code-from-string-to.html) ).

---

Third, if you don't need Maybe results from mapM [use mapM\_](https://stackoverflow.com/questions/27609062/what-is-the-difference-between-mapm-and-mapm-in-haskell) - it's **much faster**!

---

Finally, here is my version of your code, using Data.ByteString:

```
{-# LANGUAGE OverloadedStrings #-}
--  that line is so You could use "\t" instead of T.pack "\t"

import System.IO
import qualified Data.ByteString.Char8 as T

helperFun x = T.concat [y, "\t", z]
          where
            y = T.pack $ show x
            z = T.pack $ show $ x^2

saveLine fh x = T.hPutStrLn fh $ helperFun x

main = do
    fh <- openFile "haskell.txt" WriteMode
    mapM_ (saveLine fh) [1..999999]
    hClose fh

```

---

**Edit:**
*user5402* said in comments it's not so "much faster" then Strings version.

You should keep in mind that this code is still using Strings, and had additional overhead ( packing Strings into ByteString ) with only `concat` and `hPutStrLn` used from ByteString.