I am aware of the package ProgressMeter.jl which works for function which process things in loops. I am looking for something that works on functions that doesn’t necessarily have loop but just takes time to complete some complex calculation. Also, because there is no loop per se, so I am not expecting to display a progress meter, but simply a spinner would work just fine till the function is done executing.
See the ProgressMeter manual section on tasks with an unknown number of steps, which is precisely for your sort of problem, and includes spinner options.
Thanks @stevengj. This is precisely what I tried but for this to work I still need some sort of loop. My code looks something like this:
function slow_function()
sleep(10) #emulating complex calculation
end
function run()
# progress/spinner display
slow_function() #while this executes I display the spinner
return
end
run()
Here, I don’t have any loop (so the ProgressUnknown
function would still not work). Please let me know if I am missing something here and could somehow still use the ProgressMeter.jl package. Thanks!
Yes, that didn’t work. Again because there is no loop at all.
Yeah I realized it won’t work
Looking at stevengj’s link, the examples show a loop because the next!
call can occur gracefully at one point in each iteration, but you can also call next!
in several places in your method. Reading the rest of the README, it looks like next!
also works on progress types with a known number of steps, and this seems preferable because you manually determine how many times next!
is called.
I don’t think progress indication can occur independently of the method. The @showprogress
macro transforms expressions to include steps indicating the progress. Hypothetically you could run a timer totally independently of the method, but it cannot know where the method is when it reports a time, so it cannot serve as a progress indicator. I think it would have to look like:
function slow_progress()
p = Progress(2; dt=1.0) # only call 2 times
# do some stuff
next!(p)
# do more stuff
next!(p)
return
end
Ideally you space it out so you’re doing about the same amount of work between next!
calls, so the progress increments mostly smoothly; that occurs often in loops of course. The update!
function could be better if the amount of work varies quantifiably and can be worked into the increment.
This makes sense. The only problem is that slow_function
is imported from a different package and I have no control over it (in terms of modifying it). I assume there is no other way so far. But thanks for the reasoning behind next!
, I can at least use it in functions written by me. Thanks!
That’s unfortunate. Since the method doesn’t indicate its progress or some measure of how close it is to ending, the best you can do is log how long each call takes and report the statistics prior to the next calls. If runtime varies over input size in a predictable way (like a bigger file or more files), you could model it. Hopefully the model was accurate enough to be a good predictor with enough data. None of the timing statistics tells you about the progress, just like how progress can’t tell you how long any increment would take, but at least you have nonzero information about how long your lunchbreak can be.
That’s a nice workaround. Also, I am not really interested in showing the exact progress. I understand it can vary based on the input and difficult to track in this case. Hence, I am looking more at some sort of spinner
that can be displayed (may be rotate every one second) while the function runs and stops once the function is executed. I can use your idea of average statistics to display beside the rotating spinner. The whole idea is to not make the screen look as if it’s stuck and not doing anything.
Something like this should work:
using ProgressMeter
slow_function() = sleep(10)
p = ProgressUnknown(; spinner=true)
channel = Channel() do ch
while !isready(ch)
next!(p)
sleep(1)
end
end;
slow_function()
close(channel)
It just spawns a thread to spin the progress meter every second and then stops it (by closing the channel) once the function has returned.
This is great! Thanks. However the progress meter keeps running even after the close(channel)
.
Oops!
Try this instead:
using ProgressMeter
slow_function() = sleep(3)
p = ProgressUnknown(; spinner=true)
channel = Channel() do ch
while !isready(ch)
next!(p)
sleep(1)
end
take!(ch)
end;
slow_function()
put!(channel, 1)
Perfect! Thanks!