# Is it necessary for sleep to allocate?

**URL:** https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795
**Category:** Performance
**Tags:** multithreading
**Created:** [March 12, 2022, 3:32pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795 "2022-03-12T15:32:35Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)
#### Post date: [March 12, 2022, 3:32pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795/1 "2022-03-12T15:32:35Z")

</div>

I was optimizing a complex block of multithreaded code and discovered that sleep was allocating.

```julia
julia> @btime sleep(0)
  1.720 μs (5 allocations: 144 bytes)

```

I was pretty surprised, so checked the [source](https://github.com/JuliaLang/julia/blob/2ba3a22858938ecaf41bbe3e780df507556825c5/base/asyncevent.jl#L232) which is basically `wait(Timer(sec))`, so it’s allocating a mutable struct for that Timer. Is there a more efficient alternative to that to sleep for a very short time?

I found a [reference to usleep](https://discourse.julialang.org/t/accuracy-of-sleep/5546/3) but I’m on Windows so that’s not an option for me.

I need a thread to sleep briefly (milliseconds) waiting for more work to come in. I think using yield instead might work for me, but it would be nice to have an efficient sleep option (or improve my understanding if it’s not possible).

---

<div class="post-metadata">

### Author: ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)
#### Post date: [March 12, 2022, 3:55pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795/2 "2022-03-12T15:55:32Z")

</div>

If `sleep(0)` only takes 2 microseconds then sleeping for a millisecond (500x longer) should have negligible overhead.

---

<div class="post-metadata">

### Author: ![yashi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yashi/32/19448_2.png) [@yashi](https://discourse.julialang.org/u/yashi)
#### Post date: [March 12, 2022, 5:05pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795/3 "2022-03-12T17:05:39Z")

</div>

How about using `Libc.systemsleep()`?  
[https://docs.julialang.org/en/v1/base/libc/#Base.Libc.systemsleep](https://docs.julialang.org/en/v1/base/libc/#Base.Libc.systemsleep)

![image](https://global.discourse-cdn.com/julialang/original/3X/5/4/54bcfdf68b65c86d0e591631016939abc550d8b3.png)

This is on Windows.

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [March 12, 2022, 5:11pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795/4 "2022-03-12T17:11:27Z")

</div>

I confirmed `Libc.systemsleep()` works on Linux too, and neither allocates there. So I’m puzzled why `sleep()` just doesn’t call it.

Anyway what I was digging into, until I saw that answer:

> [@taotree](#):
>
> discovered that sleep was allocating.

I saw a reason for some of the allocations, and was thinking of making a PR to fix:

```julia
@edit Timer(1)
        timeout ≥ 0 || throw(ArgumentError("timer cannot have negative timeout of $timeout seconds"))
        interval ≥ 0 || throw(ArgumentError("timer cannot have negative repeat interval of $interval seconds"))
..
        this = new(Libc.malloc(_sizeof_uv_timer), ThreadSynchronizer(), true, false)

```

LazyString was added in Julia 1.8, so that you could change like this I believe:

```julia
timeout ≥ 0 || throw(ArgumentError(lazy"timer cannot have negative timeout of $timeout seconds"))

rather than:

timeout ≥ 0 || throw(ArgumentError(LazyString("timer cannot have negative timeout of $timeout seconds")))

```

It’s good to know about the LazyString, because untaken `throw` exceptions can allocate and slow down your code (when string interpolation is used).

I don’t have a fix for the malloc.

> <https://github.com/JuliaLang/julia/pull/33711>
>
> One common theme when looking at inference logs is that formatting error message…s
> tends to pull in the whole I/O and printing system which a) can take some time to
> infer and b) adds backedges if that stuff gets invalidated. Both seem wasteful.
> This is an attempt to try to improve the situation. For various error structs
> that used to contain a string, they now take either a String or a closure that
> will format the required string on demand when showing the error.
> 
> I have some tooling to count the total number of methods that inference looks
> at and went through and switched over all the error messages that are used
> by \*(::Matrix{Float64}, ::Matrix{Float64} to the new setup. Doing this
> reduces the total number of methods inference looks at by about 20%,
> which seems like a worthwhile improvement.
> 
> Obviously there are a lot of error sites that could potentially throw, but this approach is backwards compatible, so if we like the direction, we can merge it and then we can gradually go through and clean up the callsite (or somebody could write a femtocleaner pass to do it).

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [March 13, 2022, 1:50pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795/5 "2022-03-13T13:50:58Z")

</div>

What kind of `sleep` is `Libc.systemsleep`? The regular (allocating) version has the benefit of allowing other julia tasks to run in the background, since it’s yielding to the scheduler.

---

<div class="post-metadata">

### Author: ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)
#### Post date: [April 2, 2022, 8:39pm UTC](https://discourse.julialang.org/t/is-it-necessary-for-sleep-to-allocate/77795/6 "2022-04-02T20:39:30Z")

</div>

Thanks for the mention of Libc.systemsleep. Unfortunately, the doc states: “This function does not yield to Julia’s scheduler and therefore blocks the Julia thread that it is running on for the duration of the sleep time.” This sounds like it won’t be useful. I thought I would test it. I ran the code below and it does hang for 4 seconds (when running Julia with only one thread), so… it appears it won’t do what I need (if the test is correct). The output for duration seems a little odd to me, though.

```julia
start 1
end 1
start 1
end 1
duration: 0.004000186920166016

```

```julia
function slong()
  println("start $(Threads.threadid())")
  Libc.systemsleep(2.0)
  println("end $(Threads.threadid())") )
end

function run()
  t1 = time()
  Threads.@spawn slong()
  yield()
  Threads.@spawn slong()
  yield()
  t2 = time()
  println("duration: $(t2 - t1)")
end

```
