超时未触发

为了好玩,我在 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()

    }



问题就解决了。所以是我的自定义排序函数阻止了超时被触发。有什么我必须添加到这些函数中才能使它们并行运行的吗?


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


守着星空守着你
浏览 173回答 2
2回答

莫回无

由于您time.After(time.Second)在最终循环内使用,因此每次结果到达时都会重置超时。相反,尝试timeoutChannel := time.After(time.Second)for _ = range sortingFunctions {&nbsp; &nbsp; select {&nbsp; &nbsp; case result := <-mainChannel:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf(result)&nbsp; &nbsp; case <-timeoutChannel:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Timeout")&nbsp; &nbsp; }}上面的代码现在可以正确捕获超时。它仍然没有按预期工作,因为循环的内容总是执行三次(因为sortingFunctions有三个元素),并且任何超时都计入这三次迭代。使用 go playground 中的代码,我现在得到以下输出:Generated 90000 integers.QuickSortRandom&nbsp; &nbsp; &nbsp; took&nbsp; &nbsp; &nbsp;9.4268ms to sort 90000 elementsTimeoutQuickSortLastElement took&nbsp; &nbsp; &nbsp;8.6096ms to sort 90000 elements

慕森卡

您在 Go playground 上发布的代码给出了以下输出:Generated 90000 integers.InsertionSort&nbsp; &nbsp; &nbsp; &nbsp; took&nbsp; 4465.6230ms to sort 90000 elementsQuickSortLastElement took&nbsp; &nbsp; 11.2758ms to sort 90000 elementsQuickSortRandom&nbsp; &nbsp; &nbsp; took&nbsp; &nbsp; 11.6547ms to sort 90000 elements我怀疑您没有看到超时被调用的事实是由于InsertionSort确实进行了任何函数调用,因此不允许调度程序在 goroutines 之间切换。由于 Go 默认只使用一个线程,所以其他一切都必须等到InsertionSort完成。为了验证这个假设,我尝试使用 GOMAXPROCS=4 调用程序(允许 Go 调度程序使用 4 个操作系统线程):在这种情况下,我得到了输出Generated 90000 integers.QuickSortRandom&nbsp; &nbsp; &nbsp; took&nbsp; &nbsp; 21.1900ms to sort 90000 elementsQuickSortLastElement took&nbsp; &nbsp; 11.4538ms to sort 90000 elementsTimeout正如预期的那样。(奇怪的是,对于 GOMAXPROCS=2,行为不是确定性的,有时会触发超时,有时不会。我没有试图找出为什么 2 个线程在这里并不总是足够的。)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go