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

标签 python go time sqrl

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

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 时间,理想情况下是函数使用的时间,或者至少是运行它的线程或进程。

process_time 在 Go 中的等价物是什么?

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

最佳答案

您可以使用 runtime.LockOSThread() 将调用 goroutine 连接到其当前操作系统线程。这将确保不会有其他 goroutines 被调度到该线程,因此您的 goroutine 将运行并且不会被中断或暂停。当线程被锁定时,没有其他 goroutines 会干扰。

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

看这个例子:

func runUntil(end time.Time) {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    for time.Now().Before(end) {
    }
}

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

start := time.Now()
end := start.Add(time.Second * 2)
runUntil(end)

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

例如打印:

Verify: 2.0004556s

当然你也可以指定少于一秒,例如等待 100 毫秒:

start := time.Now()
runUntil(start.Add(time.Millisecond * 100))
fmt.Println("Verify:", time.Now().Sub(start))

输出:

Verify: 100.1278ms

如果更适合您,您可以使用此函数的不同版本,将“等待”的时间量作为 time.Duration 的值:

func wait(d time.Duration) {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()

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

使用这个:

start = time.Now()
wait(time.Millisecond * 200)
fmt.Println("Verify:", time.Now().Sub(start))

输出:

Verify: 200.1546ms

注意:请注意,上述函数中的循环将无休止地使用 CPU,因为其中没有 sleep 或阻塞 IO,它们只会查询当前系统时间并将其与截止日期进行比较。

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

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

查看相关问题:

Number of threads used by Go runtime

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

关于python - 如何确保函数在 Go 中花费一定的时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40063269/

相关文章:

python - 通过类型注释对 Python 中的类型构造函数进行抽象

go - 无法根据 Golang 中的条件将接口(interface)转换为结构

go - 如何在golang中编写一个函数来处理两种类型的输入数据

Golang 并发问题

python - 如何使用 python 以一种自然的人类可读的方式绘制与时间相关的信息?

c - 大小为 2^25 的数组

python - 使用 linux 或 python 查找 mp3 声音样本的时间戳

python - 将列表映射到霍夫曼树,同时保留相对顺序

python - Django 中间件 : Can't get urlredirect to work

php - 总小时数行