首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何确保一个函数在Go中花费一定的时间?

如何确保一个函数在Go中花费一定的时间?
EN

Stack Overflow用户
提问于 2016-10-16 03:21:08
回答 1查看 289关注 0票数 5

我正在为Go中的一个SQRL客户端实现EnScrypt。该函数需要运行,直到它使用了最少的CPU时间。我的Python代码如下所示:

代码语言:javascript
复制
def enscrypt_time(salt, password, seconds, n=9, r=256):
    N = 1 << n
    start = time.process_time()
    end = start + seconds
    data = acc = scrypt.hash(password, salt, N, r, 1, 32)
    i = 1
    while time.process_time() < end:
        data = scrypt.hash(password, data, N, r, 1, 32)
        acc = xor_bytes(acc, data)
        i += 1
    return i, time.process_time() - start, acc

除了process_time函数之外,将其转换为Go非常简单。我不能使用time.Time / Timer,因为它们测量的是挂钟时间(它会受到系统上运行的其他所有东西的影响)。我需要实际使用的CPU时间,理想情况下是由函数使用的,或者至少是由运行它的线程或进程使用的。

Go中与process_time等效的是什么

https://docs.python.org/3/library/time.html#time.process_time

EN

回答 1

Stack Overflow用户

发布于 2016-10-16 12:54:42

您可以使用runtime.LockOSThread()将调用的goroutine连接到其当前的OS线程。这将确保不会将其他goroutine调度到此线程,因此您的goroutine将会运行,并且不会被中断或挂起。当线程被锁定时,其他goroutines将不会干扰。

在此之后,您只需要一个循环,直到给定的秒数过去。您必须调用runtime.UnlockOSThread()来“释放”线程,并使其可供其他goroutines执行,最好作为defer语句来完成。

请参阅此示例:

代码语言:javascript
复制
func runUntil(end time.Time) {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    for time.Now().Before(end) {
    }
}

为了让它等待2秒,它可能看起来像这样:

代码语言:javascript
复制
start := time.Now()
end := start.Add(time.Second * 2)
runUntil(end)

fmt.Println("Verify:", time.Now().Sub(start))

例如,打印以下内容:

代码语言:javascript
复制
Verify: 2.0004556s

当然,您也可以指定少于一秒的时间,例如等待100毫秒:

代码语言:javascript
复制
start := time.Now()
runUntil(start.Add(time.Millisecond * 100))
fmt.Println("Verify:", time.Now().Sub(start))

输出:

代码语言:javascript
复制
Verify: 100.1278ms

如果这个函数更适合您,您可以使用该函数的另一个版本,该函数需要将等待时间作为time.Duration的值

代码语言:javascript
复制
func wait(d time.Duration) {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()

    for end := time.Now().Add(d); time.Now().Before(end); {
    }
}

使用以下命令:

代码语言:javascript
复制
start = time.Now()
wait(time.Millisecond * 200)
fmt.Println("Verify:", time.Now().Sub(start))

输出:

代码语言:javascript
复制
Verify: 200.1546ms

注意:注意,上述函数中的循环将持续使用CPU,因为其中没有休眠或阻塞IO,它们将仅查询当前系统时间并将其与截止时间进行比较。

如果攻击者通过多次并发尝试增加系统负载怎么办?

Go运行时限制了可以同时执行goroutines的系统线程。这是由runtime.GOMAXPROCS()控制的,所以这已经是一个限制。默认为可用CPU核心数,您可以随时更改。但是,这也造成了一个瓶颈,就像使用runtime.LockOSThread()一样,如果锁定线程的数量在任何给定时间等于GOMAXPROCS,则会阻塞其他goroutine的执行,直到某个线程解锁。

查看相关问题:

Number of threads used by Go runtime

Why does it not create many threads when many goroutines are blocked in writing file in golang?

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40063269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档