Thread overview
Progress printing with threads?
Jul 01, 2020
AB
Jul 01, 2020
Stanislav Blinov
Jul 01, 2020
Simen Kjærås
July 01, 2020
Hello. I am unsure how to proceed about printing progress in my program.

Suppose the program is processing a very big file and is iterating the file's bytes using a for loop. The processing takes several minutes and I want a progress percentage be printed every 2 seconds in this manner:

Progress: 0.40%
Progress: 3.20%
Progress: 5.73%

Is it a good idea to std.concurrency.spawn a new thread and pass to it
    cast(float)i * 100 / fileSize
somehow? If not, what's a better way to do this?

This example code shows my situation:

    MmFile  input       = new MmFile(/* ... */);
    ulong   fileSize    = input.length;

    for (ulong i = 0; i < fileSize; ++i)
    {
        // ...
    }

Thanks in advance.

July 01, 2020
On Wednesday, 1 July 2020 at 07:52:28 UTC, AB wrote:
> Hello. I am unsure how to proceed about printing progress in my program.
> Is it a good idea to std.concurrency.spawn a new thread?..
> This example code shows my situation:
>
>     MmFile  input       = new MmFile(/* ... */);
>     ulong   fileSize    = input.length;
>
>     for (ulong i = 0; i < fileSize; ++i)
>     {
>         // ...
>     }

If you can only update the progress between iterations I don't see why you would use threads here. A timer should suffice:

import std.datetime.stopwatch;

MmFile  input       = new MmFile(/* ... */);
ulong   fileSize    = input.length;
auto    sw          = StopWatch(AutoStart.yes);

for (ulong i = 0; i < fileSize; ++i)
{
      // ...
      if (sw.peek >= 2.seconds)
      {
          writefln("Progress: %5.2f%%", i*100.0/fileSize);
          sw.reset;
      }
}

July 01, 2020
On Wednesday, 1 July 2020 at 07:52:28 UTC, AB wrote:
> Hello. I am unsure how to proceed about printing progress in my program.
>
> Suppose the program is processing a very big file and is iterating the file's bytes using a for loop. The processing takes several minutes and I want a progress percentage be printed every 2 seconds in this manner:
>
> Progress: 0.40%
> Progress: 3.20%
> Progress: 5.73%
>
> Is it a good idea to std.concurrency.spawn a new thread and pass to it
>     cast(float)i * 100 / fileSize
> somehow? If not, what's a better way to do this?
>
> This example code shows my situation:
>
>     MmFile  input       = new MmFile(/* ... */);
>     ulong   fileSize    = input.length;
>
>     for (ulong i = 0; i < fileSize; ++i)
>     {
>         // ...
>     }
>
> Thanks in advance.

If doing the update in the same thread that does the processing is somehow not an option, this works for me:

import std.concurrency;
import std.stdio;
import core.thread;
import core.time;

void main() {
    ulong filesize = 1234;
    ulong i = 0;
    Tid progress = spawn((shared const(ulong)* p, ulong f){
            while (!receiveTimeout(2000.msecs, (int i){ })) {
                writeln(*p, "/", f, ": ", *p*100.0/f, "%");
            }
        }, cast(shared)&i, filesize);
    for (; i < filesize; ++i) {
        // Process
    }
    progress.send(0); // Stop
}

There's a cast to shared there which may be suboptimal, but since the progress thread is only reading it, I would say it's ok.

--
  Simen