How can I ensure that a function takes a certain amount of time in Go?
<p>I am implementing EnScrypt for an SQRL client in Go. The function needs to run until it has used a minimum amount of CPU time. My Python code looks like this:</p>

<pre><code>def enscrypt_time(salt, password, seconds, n=9, r=256):
    N = 1 &lt;&lt; n
    start = time.process_time()
    end = start + seconds
    data = acc = scrypt.hash(password, salt, N, r, 1, 32)
    i = 1
    while time.process_time() &lt; end:
        data = scrypt.hash(password, data, N, r, 1, 32)
        acc = xor_bytes(acc, data)
        i += 1
    return i, time.process_time() - start, acc
</code></pre>

<p>Converting this to Go is pretty simple except for the <code>process_time</code> function.
I can't use <code>time.Time</code> / <code>Timer</code> because those measure wall-clock time (which is affected by everything else that may be running on the system). I need the CPU time actually used, ideally by the function, or at least by the thread or process it is running in.</p>

<p>What is the Go equivalent of <code>process_time</code>?</p>

<p><a href="https://docs.python.org/3/library/time.html#time.process_time" rel="nofollow">https://docs.python.org/3/library/time.html#time.process_time</a></p>

<p>You may use <a href="https://golang.org/pkg/runtime/#LockOSThread" rel="nofollow"><code>runtime.LockOSThread()</code></a> to wire the calling goroutine to its current OS thread. This will ensure that no other goroutines will be scheduled to this thread, so your goroutine will run and not get interrupted or put on hold. No other goroutines will interfere when thread is locked.</p>

<p>After this, you just need a loop until the given seconds have passed. You must call <a href="https://golang.org/pkg/runtime/#UnlockOSThread" rel="nofollow"><code>runtime.UnlockOSThread()</code></a> to "release" the thread and make it available for other goroutines for execution, best done as a <code>defer</code> statement.</p>

<p>See this example:</p>

<pre><code>func runUntil(end time.Time) {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    for time.Now().Before(end) {
    }
}
</code></pre>

<p>To make it wait for 2 seconds, it could look like this:</p>

<pre><code>start := time.Now()
end := start.Add(time.Second * 2)
runUntil(end)

fmt.Println("Verify:", time.Now().Sub(start))
</code></pre>

<p>This prints for example:</p>

<pre><code>Verify: 2.0004556s
</code></pre>

<p>Of course you can specify less than a second too, e.g. to wait for 100 ms:</p>

<pre><code>start := time.Now()
runUntil(start.Add(time.Millisecond * 100))
fmt.Println("Verify:", time.Now().Sub(start))
</code></pre>

<p>Output:</p>

<pre><code>Verify: 100.1278ms
</code></pre>

<p>You may use a different version of this function if that suits you better, one that takes the amount of time to "wait" as a value of <a href="https://golang.org/pkg/time/#Duration" rel="nofollow"><code>time.Duration</code></a>:</p>

<pre><code>func wait(d time.Duration) {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()

    for end := time.Now().Add(d); time.Now().Before(end); {
    }
}
</code></pre>

<p>Using this:</p>

<pre><code>start = time.Now()
wait(time.Millisecond * 200)
fmt.Println("Verify:", time.Now().Sub(start))
</code></pre>

<p>Output:</p>

<pre><code>Verify: 200.1546ms
</code></pre>

<p><strong>Note:</strong> Note that the loops in the above functions will use CPU relentlessly as there is no sleep or blocking IO in them, they will just query the current system time and compare it to the deadline.</p>

<p><strong>What if the attacker increases system load by multiple concurrent attempts?</strong></p>

<p>The Go runtime limits the system threads that can simultaneously execute goroutines. This is controlled by <a href="https://golang.org/pkg/runtime/#GOMAXPROCS" rel="nofollow"><code>runtime.GOMAXPROCS()</code></a>, so this is already a limitation. It defaults to the number of available CPU cores, and you can change it anytime. This also poses a bottleneck though, as by using <code>runtime.LockOSThread()</code>, if the number of locked threads equals to <code>GOMAXPROCS</code> at any given time, that would block execution of other goroutines until a thread is unlocked.</p>

<p>See related questions:</p>

<p><a href="http://stackoverflow.com/questions/39245660/number-of-threads-used-by-go-runtime">Number of threads used by Go runtime</a></p>

<p><a href="http://stackoverflow.com/questions/28186361/why-does-it-not-create-many-threads-when-many-goroutines-are-blocked-in-writing/28186656#28186656">Why does it not create many threads when many goroutines are blocked in writing file in golang?</a></p>

python go time sqrl