6

I started to do programming contests in go (just to learn the language) and to my surprise found that

var T int
fmt.Scanf("%d", &T)

is unimaginably slow. How slow? To read 10^5 integers it take me 2.5 seconds (in comparison python does it in 0.8 secs).

So why is it so slow and how should I properly read int, uint64 and float64?

Community
  • 1
  • 1
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
  • 2
    Do you use `bufio`? Why `fmt.Scanf` and not just `strconv.Atoi`? Post the code, there's not enough info. – Ainar-G May 01 '15 at 08:08
  • 1
    @Ainar-G what code are you looking for. All I do reading a bunch of integers from stdin. And I clearly stated how I have done it (with `fmt.Scanf` which means that no, I have not used `bufio`). Why not just `strconv.Atoi` because I found how to read an integer in the answer on stackoverflow and it was telling to use scanf. I think it is more than enough info to understand what I am talking about. – Salvador Dali May 01 '15 at 08:12
  • @Salvador Dali Just curious, how you provide 10^5 integers to stdin? Can you do that at 2.5 seconds? – Uvelichitel May 01 '15 at 10:19
  • @Uvelichitel as I wrote, I am using Go to solve programming competitions. In all of them you receive input on `stdin` and have to write your answer in `stdout` – Salvador Dali May 01 '15 at 18:44

1 Answers1

5

If you have only the integer as input, this should be faster (not tested though)

package main

import (
    "io/ioutil"
    "log"
    "os"
    "strconv"
)

func read() (int64, error) {
    b, err := ioutil.ReadAll(os.Stdin)
    if err != nil {
        return 0, err
    }

    // use strconv.ParseUint and strconv.ParseFloat in a similar way
    return strconv.ParseInt(string(b[:len(b)-1]), 10, 0)
}

func main() {
    i, err := read()
    if err != nil {
        log.Fatal(err)
    }

    println(i)
}

run it like this

echo 123 | go run main.go

for interactive input, you might want to use bufio.NewReader, see How to read input from console line?

Community
  • 1
  • 1
metakeule
  • 3,724
  • 2
  • 23
  • 29
  • 1
    do you have any idea why scanf is so slow (it is kind of strange to have a function which does something super inefficient when there is an efficient approach to do something. P.S. thanks, I will try your answer – Salvador Dali May 01 '15 at 08:42
  • 1
    Well my code assumes that input is an integer. Scanf has multiple placeholders and is more flexible. This flexibility should come at a performance cost (more branches). – metakeule May 01 '15 at 08:44
  • 5
    if you look at the source code http://golang.org/src/fmt/scan.go?s=3461:3523#L74, and go through the function calls, the critical inner function seems to be scanOne (line 930) which has lots of case branches – metakeule May 01 '15 at 08:51
  • 1
    @metakeule To see output why `Ctrl + D` has to be pressed ? – ameyCU Aug 08 '16 at 16:03