os.clock() does not return CPU time on Windows

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

os.clock() does not return CPU time on Windows

Egor Skriptunoff-2
Hi!

The Lua manual says:
  os.clock()
  Returns an approximation of the amount
  in seconds of CPU time used by the program.

But it appears that on Windows the C function clock()
returns wall-time instead of CPU-time:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/clock?view=vs-2019

As a result, in Lua on Windows, the function
os.clock() returns wall-clock time.
I've tested it on Lua built with both compilers
(Visual Studio and MinGW-w64).

It looks like it's Microsoft's fault
to incorrectly implement C run-time function.
But Lua should workaround this bug.
Or the Lua manual should be corrected.

Found here:
https://stackoverflow.com/questions/56995690/confused-over-precision-of-luas-os-clock/56995937#comment100526058_56995937
Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Roberto Ierusalimschy
> But it appears that on Windows the C function clock()
> returns wall-time instead of CPU-time:
> https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/clock?view=vs-2019
>
> [...]
>
> It looks like it's Microsoft's fault
> to incorrectly implement C run-time function.

"It looks like" is an euphemism. They explicitly say that the function
is incorrect:

  Note that this function does not strictly conform to ISO C, which
  specifies net CPU time as the return value.

("does not strictly conform" is another euphemism :-)

-- Roberto


Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Enrico Colombini
In reply to this post by Egor Skriptunoff-2
On 07-Nov-19 17:36, Egor Skriptunoff wrote:

> But it appears that on Windows the C function clock()
> returns wall-time instead of CPU-time:
> https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/clock?view=vs-2019
>
> As a result, in Lua on Windows, the function
> os.clock() returns wall-clock time.
> I've tested it on Lua built with both compilers
> (Visual Studio and MinGW-w64).
>
> It looks like it's Microsoft's fault
> to incorrectly implement C run-time function.
> But Lua should workaround this bug.
> Or the Lua manual should be corrected.

I would not venture on the time measuring minefield, of which I
unfortunately have some experience on Windows and Linux (if you need
precision and monotonicity it gets much worse, not counting OS version
compatibility).
It would be best to go for the second option, i.e. to simply state that
Lua returns time as measured by the underlying C system library call.

--
   Enrico

Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Rob Kendrick-2
In reply to this post by Roberto Ierusalimschy
On Thu, Nov 07, 2019 at 02:22:46PM -0300, Roberto Ierusalimschy wrote:

> > But it appears that on Windows the C function clock()
> > returns wall-time instead of CPU-time:
> > https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/clock?view=vs-2019
> >
> > [...]
> >
> > It looks like it's Microsoft's fault
> > to incorrectly implement C run-time function.
>
> "It looks like" is an euphemism. They explicitly say that the function
> is incorrect:
>
>   Note that this function does not strictly conform to ISO C, which
>   specifies net CPU time as the return value.

Does it give the rationale?  I have always assumed this is a backwards
compability issue (which Microsoft take very seriously): under DOS the
the wall clock time a program had been running was identical to its use
of the CPU, as it was a single-tasking environment.

B.

Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Egor Skriptunoff-2
On Fri, Nov 8, 2019 at 4:28 PM Rob Kendrick wrote:
under DOS the
the wall clock time a program had been running was identical to its use
of the CPU, as it was a single-tasking environment.


In the epoch of single-task environments,
in 1988 (before ISO C standard was published),
internal help of Borland's Turbo C for DOS
already claimed that it's the CPU time
that is returned by clock()
But this is Borland, not MS.
I don't have old Microsoft's C compiler's manual
at my disposal to see how clock() was described there.

Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Enrico Colombini
On 08-Nov-19 18:00, Egor Skriptunoff wrote:

> In the epoch of single-task environments,
> in 1988 (before ISO C standard was published),
> internal help of Borland's Turbo C for DOS
> already claimed that it's the CPU time
> that is returned by clock()
>
> The screenshot:
> https://i.imgur.com/6AF00J8.png
>
> But this is Borland, not MS.
> I don't have old Microsoft's C compiler's manual
> at my disposal to see how clock() was described there.

I seem to have misplaced the library volume of Microsoft Quick C,
assuming there was one.
But, if I remember correctly, in both Microsoft and Borland compilers
clock() returned a system-wide tick count value, a value that was
incremented by the real-time clock interrupt routine (INT 08H). I wrote
portable C code and I don't remember handling clock() differently for
each system.

Of course, in plain MS-DOS, the sole CPU was almost fully owned by the
sole running program, so no subtle differences were made.

A curiosity: date/time were read from the hardware clock chip only at
startup, then maintained by counting clock ticks (i.e. the
aforementioned interrupts). If the user changed date/time, the tick
count did not change, so remaining monotonic (up to the next
wrap-around...).

Date/time shown could be different from those stored into the
(battery-backed) real-time clock chip.
For example, when I hijacked the timer generating INT 08H to play
recorded sounds with the internal speaker, date/time paused while a
sound was played, because ticks were lost.

--
   Enrico

Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Viacheslav Usov
On Fri, Nov 8, 2019 at 10:23 PM Enrico Colombini <[hidden email]> wrote:

> But, if I remember correctly, in both Microsoft and Borland compilers clock() returned a system-wide tick count value, a value that was incremented by the real-time clock interrupt routine (INT 08H)

The clock() function debuted in Microsoft C v5.1 (1988). I can see that its return value changes by either 50 or 60 18-19 times per second, which means it is indeed in sync with the PC timer interrupt and it reports milliseconds.

Its description in the various pieces of documentation is confusing. What it actually does is settled in a KnowledgeBase article:

(begin quote)

Product Version(s): 5.10   |  5.10
Operating System:   MS-DOS |  OS/2
Flags: ENDUSER | S_QuickC S_QuickAsm docsup
Last Modified: 17-JUL-1990    ArticleIdent: Q49729

The clock function is documented as telling how much processor time
has been used by the calling process. This definition is misleading.

The clock function returns a clock_t (long) value, which is the
difference between the time field (for seconds) and millitm field (for
milliseconds) in the structure that is returned from two calls to the
ftime function. The first call to ftime is made within the start-up
code of the executing program, and the second call is made when the
clock function is explicitly called in your code.

This means that the value returned by clock is the number of CLK_TCKs
(milliseconds) elapsed since the start-up code was executed, or -1 if
the function was unsuccessful.

(end quote)

I guess we can say that clock() was working more or less correctly in MS DOS, and already in 1990 Microsoft knew it would not work correctly in a multi-tasking environment such as OS/2 they were developing with IBM, and judging from the confused documentation they could not quite decide (then) how they would like to proceed. At some later point they apparently decided MS DOS compatibility was more important.

Cheers,
V.

Reply | Threaded
Open this post in threaded view
|

Re: os.clock() does not return CPU time on Windows

Tim Hill


> On Nov 9, 2019, at 10:16 AM, Viacheslav Usov <[hidden email]> wrote:
>
>
> (begin quote)
>
> Product Version(s): 5.10   |  5.10
> Operating System:   MS-DOS |  OS/2
> Flags: ENDUSER | S_QuickC S_QuickAsm docsup
> Last Modified: 17-JUL-1990    ArticleIdent: Q49729
>
> The clock function is documented as telling how much processor time
> has been used by the calling process. This definition is misleading.
>
> The clock function returns a clock_t (long) value, which is the
> difference between the time field (for seconds) and millitm field (for
> milliseconds) in the structure that is returned from two calls to the
> ftime function. The first call to ftime is made within the start-up
> code of the executing program, and the second call is made when the
> clock function is explicitly called in your code.
>
> This means that the value returned by clock is the number of CLK_TCKs
> (milliseconds) elapsed since the start-up code was executed, or -1 if
> the function was unsuccessful.
>
> (end quote)
>

To be fair to Microsoft (yes, it sticks in my throat to say that), the clock() function has to be one of the worst named APIs around. Though some of the other time functions are up there as well. For example, back in mainframe days one OS (GEORGE III) used to name elapsed processor time the “mill time” (in a deliberate nod to Charles Babbage).

—Tim