dougaimian1143 2013-06-20 08:26
浏览 7
已采纳

在以下情况下,为什么Go程序的性能比预期的要差得多? [关闭]

I was solving a simple question in C, Go, and Python and comparing the results. The solution is simply supposed to have two equations inside an if-else block. The following are the code for my solution in:

C

python

go

I was comparing the way the three languages deal with floating point results and hence made this script to generate the test cases and this to compare the results, two at a time.

The weird thing is the time it takes to run the first 3 scripts. The C program obviously runs within a couple of seconds. Python takes around 2.5-3 seconds. However, Go is taking around 24-25 seconds to run the program on the test cases generated by the generate_test_cases.py script.

I thought Go would be somewhere between C and Python as far as running time is concerned. Am I doing something inefficiently with my Go code, and if so, what?

P.S. I also ran the above three programs without the file handling operations, and still the same result, i.e., Go takes an extraordinarily long time compared to the other two.

  • 写回答

2条回答 默认 最新

  • dtlab08822 2013-06-20 09:07
    关注

    Like Max, my strong suspicion was that the slowness in Go was related to poor I/O performance. I tested this hypothesis:

    package main
    
    import "fmt"
    import "os"
    import "time"
    
    func main(){
        now := time.Now()
        input,_ := os.Open("testing/test_cases.txt")
        defer input.Close()
        output,_ := os.Create("testing/Goutput.txt")
        defer output.Close()
    
        var ncases int
        var p float64
        fmt.Fscanf(input,"%d",&ncases)
    
        fmt.Println("Opened files in ", time.Since(now), "seconds")
        now = time.Now()
    
        cases := make([]float64, ncases)
        fmt.Println("Made array in ", time.Since(now), "seconds")
        now = time.Now()
    
        for i := 0; i < ncases; i++ {
            fmt.Fscanf(input,"%f",&cases[i])
        }
    
        fmt.Println("Read data in ", time.Since(now), "seconds")
        now = time.Now()
    
        for i := 0; i < ncases; i++ {
            p = cases[i]
            if p >= 0.5 {
                cases[i] = 10000 * (1-p) * (2*p-1) + 10000
            } else {
                cases[i] = p*(1-2*p)*10000 + 10000
            }
        }
    
        fmt.Println("Processed data in ", time.Since(now), "seconds")
        now = time.Now()
    
        for i := 0; i < ncases; i++ {
            fmt.Fprintln(output, cases[i])
        }
    
        fmt.Println("Output processed data in ", time.Since(now), "seconds")
    }
    

    Running it produced this output:

    Opened files in  2.011228ms seconds
    Made array in  109.904us seconds
    Read data in  4.524544608s seconds
    Processed data in  10.083329ms seconds
    Output processed data in  1.703542918s seconds
    

    So it appears that on my machine, all of the math occurs in about 10ms, but the I/O is slow, confirming the hypothesis. As pointed out by Janne in the comments, there are likely faster options than fmt.

    Update: For example, wrapping input and output with bufio's Readers and Writers:

    binput := bufio.NewReader(input)
    boutput := bufio.NewWriter(output)
    

    and using binput and boutput for buffered I/O, your original version runs in 2.1 seconds on my machine, somewhat faster than Python's 2.7.

    Update 2: I noticed that I was getting different results by just switching to buffered I/O.

    1. It turns out that you also need to adjust your format strings to include the , as you do in the C version. I think this is actually more correct either way, but it looks like you can get away with it while unbuffered.

    2. It's also important to Flush() your buffered output, which I did but didn't mention before.

    Here's my complete buffered solution:

    package main
    
    import "fmt"
    import "os"
    import "bufio"
    import "time"
    
    func main(){
        now := time.Now()
    
        nbinput, _ := os.Open("testing/test_cases.txt")
        defer nbinput.Close()
    
        nboutput, _ := os.Create("testing/Goutput.txt")
        defer nboutput.Close()
    
        binput := bufio.NewReader(nbinput)
        boutput := bufio.NewWriter(nboutput)
    
        var ncases int
        var gain, p float64
        fmt.Fscanf(binput,"%d
    ",&ncases)
    
        for i := 0; i < ncases; i++ {
            fmt.Fscanf(binput, "%f
    ", &p)
            if p >= 0.5 {
                gain = 10000 * (1-p) * (2*p -1)
            } else {
                gain = p*(1-2*p)*10000
            }
            fmt.Fprintln(boutput, gain+10000)
        }
        boutput.Flush()
        fmt.Println("Took ", time.Since(now), "seconds")
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用