超时没有解雇

时间:2015-07-26 23:56:53

标签: go timeout

我在Go中实现了一些排序算法,现在我想在随机整数上测试它们的性能。所以我写了以下程序。我按照类似的格式:https://gobyexample.com/timeouts

但是,似乎超时没有正常启动。以下是我的代码:

package main

import (
    "allanpinkerton.com/algorithms/sorting"
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "time"
)

// Prints out the time elapsed since start
func timeExecution(startTime time.Time, functionName string, inputSize int) string {
    executionTime := time.Since(startTime)
    return fmt.Sprintf("%-20s took %10.4fms to sort %d elements\n", functionName, float64(executionTime.Nanoseconds())/1000000, inputSize)
}

// Generates file with n random ints named integerArray + n
func generateRandomIntegers(n int, filename string) {
    arr := make([]int, n)
    for i := 0; i < n; i++ {
        arr[i] = rand.Int()
    }
    f, _ := os.Create(filename)
    defer f.Close()
    for _, num := range arr {
        f.WriteString(strconv.Itoa(num) + " ")
    }
    f.WriteString("\n")
    f.Sync()
    fmt.Printf("Generated " + filename + " with " + strconv.Itoa(n) + " elements.\n")
}


func checkError(err error) {
    if err != nil {
        panic(err)
    }
}

func main() {

    sortingFunctions := map[string]interface{}{
        "InsertionSort":        sorting.InsertionSort,
        "QuickSortLastElement": sorting.QuickSortLastElement,
        "QuickSortRandom":      sorting.QuickSortRandom,
    }
    if len(os.Args) != 2 {
        fmt.Printf("No size specified.\n")
        return
    }
    size := os.Args[1]
    sizeInt, err := strconv.Atoi(size)
    checkError(err)

    arr := make([]int, sizeInt)
    for i := 0; i < sizeInt; i++ {
        arr[i] = rand.Int()
    }
    fmt.Println("Generated " + size + " integers.")

    mainChannel := make(chan string)
    for k, v := range sortingFunctions {
        newArr := make([]int, len(arr))
        copy(newArr, arr)
        go func(name string, v interface{}) {
            start := time.Now()
            v.(func([]int))(newArr)
            result := timeExecution(start, name, len(newArr))
            mainChannel <- result
        }(k, v)
    }

    for _ = range sortingFunctions {
        select {
        case result := <-mainChannel:
            fmt.Printf(result)
        case <-time.After(time.Second):
            fmt.Println("Timeout")
        }
    }

    return
}

顶部只是一堆助手,但主要功能还有一些有趣的事情。我跑了go install并对抗了150,000个元素,得到了以下答案:

Generated 150000 integers.
QuickSortLastElement took    15.0037ms to sort 150000 elements
InsertionSort        took  7599.5884ms to sort 150000 elements
QuickSortRandom      took    15.1697ms to sort 150000 elements

显然,插入排序超过7秒,但超时应在1秒后触发。超时是否有任何理由不发射?

所以我尝试通过将sortingFuncs map更改为:

,从sort包中切换出sort.Ints函数的自定义排序程序。
sortingFunctions := map[string]func([]int){
    "InsertionSort":        sort.Ints,
    "QuickSortLastElement": sort.Ints,
    "QuickSortRandom":      sort.Ints,
}

问题解决了。所以这是我的自定义排序函数,可防止超时被触发。我是否需要添加一些功能才能使它们并行运行?

这是一个连接版本,包含操场上的所有代码。 https://play.golang.org/p/SBgDTGyUyp

2 个答案:

答案 0 :(得分:0)

由于您在最终循环中使用time.After(time.Second),因此每次结果到达时都会重置超时。相反,尝试

timeoutChannel := time.After(time.Second)
for _ = range sortingFunctions {
    select {
    case result := <-mainChannel:
        fmt.Printf(result)
    case <-timeoutChannel:
        fmt.Println("Timeout")
    }
}

上面的代码现在可以正确捕获超时。它仍然没有按预期工作,因为循环的内容总是执行三次(因为sortingFunctions有三个元素),并且任何超时都计入这三次迭代。使用来自go playground的代码我现在得到以下输出:

Generated 90000 integers.
QuickSortRandom      took     9.4268ms to sort 90000 elements
Timeout
QuickSortLastElement took     8.6096ms to sort 90000 elements

答案 1 :(得分:0)

您在Go操场上发布的代码提供了以下输出:

Generated 90000 integers.
InsertionSort        took  4465.6230ms to sort 90000 elements
QuickSortLastElement took    11.2758ms to sort 90000 elements
QuickSortRandom      took    11.6547ms to sort 90000 elements

我怀疑您没有看到调用超时的事实是由于InsertionSort确实进行了任何函数调用,因此does not allow调度程序在goroutine之间切换。由于Go默认只使用一个线程,因此其他所有内容都要等到InsertionSort完成。

为了测试这个假设,我尝试用GOMAXPROCS = 4调用程序(允许Go调度程序使用4个操作系统线程):在这种情况下,我得到输出

Generated 90000 integers.
QuickSortRandom      took    21.1900ms to sort 90000 elements
QuickSortLastElement took    11.4538ms to sort 90000 elements
Timeout

正如所料。 (奇怪的是,对于GOMAXPROCS = 2,行为不是确定性的,有时超时触发,有时则没有。我没有试图找出为什么2个线程在这里并不总是足够。)