http://qs1969.pair.com?node_id=1090814

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Short question: can I get a more precise $^T, i.e. down to milli- or microsecond?

Replies are listed 'Best First'.
Re: Higher resolution $^T?
by tobyink (Canon) on Jun 22, 2014 at 10:06 UTC

    Interestingly, you can assign to $^T...

    perl -le'$^T=42;print($^T)'

    I've tested this in Perl 5.6.2, 5.8.9, and 5.20.0 with the same results. However, $^T is quite magic. You can assign a floating point number to it, but it will be rounded to an integer:

    perl -le'$^T=42.3;print($^T)'

    What's happening there? Well, the floating point number is actually stored correctly in Perl's SV structure. However any fetch will just get the integer instead.

    perl -MDevel::Peek -le'$^T=42.3;Dump($^T)'

    So even if you wrote a module to capture a more precise time, it couldn't be stored in $^T because that scalar is too magic.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

      So even if you wrote a module to capture a more precise time, it couldn't be stored in $^T because that scalar is too magic.

      If something were to replace $^T, it would also replace the magic.

      >perl -E"undef(*^T); $^T = 1400000000.123; say $^T;" 1400000000.123

      Well, the floating point number is actually stored correctly in Perl's SV structure.

      When assigning to a variable with set magic, the value is assigned as normal, then the magic handler is called.

      When fetching from a magical variable with get magic, the magic handler is called to replace the value of the variable, then the fetch happens as normal.

      This means you see the value assigned to the scalar in the scalar, but that value is meaningless because it gets clobbered when you read from the scalar.

      The magic behind $^T is equivalent to the following:

      use Variable::Magic qw( cast wizard ); # The C var $^T mirrors is named PL_basetime # An IV (signed integer) on all systems except OS/2 and VMS. my $PL_basetime; cast($^T, wizard( # Copies into $^T before fetching from it. get => sub { ${ $_[0] } = $PL_basetime; }, # Copies from $^T after assigning to it. set => sub { $PL_basetime = ${ $_[0] }; }, ));

        But now you also kill the magic of -M and friends:

        $ perl -wE'say $^T;say -M ".";sleep 1;say -M ".";$^T=time;say -M ".";u +ndef*^T;$^T=1400000000.123;say -M "."' 1403502321 0.450798611111111111 0.450798611111111111 0.450810185185185185 0.450810185185185185

        Note that the last -M uses what was last stored in $^T before it was undef'd and not the value you put in it.


        Enjoy, Have FUN! H.Merijn
Re: Higher resolution $^T?
by Anonymous Monk on Jun 22, 2014 at 08:45 UTC

    Short question: can I get a more precise $^T, i.e. down to milli- or microsecond?

    No, not without patching/recompiling perl so that $^T/basetime stops using time_t and switches to something like Time::HiRes uses, timeval ... not worth the effort IMHO

Re: Higher resolution $^T?
by ikegami (Patriarch) on Jun 23, 2014 at 02:35 UTC

    $^T mirrors a C variable named PL_basetime. PL_basetime is an IV (signed integer) on all systems except OS/2 and VMS where it is a floating point number. Presumably, those systems are able to obtain more precise information from the OS.

Re: Higher resolution $^T?
by sundialsvc4 (Abbot) on Jun 22, 2014 at 13:01 UTC

    I agree ... Time::HiRes, or something of its ilk, would be the most appropriate way to do it.   If the “easy way” is not enough, well, the harder ways are really not that much harder.

Re: Higher resolution $^T?
by ikegami (Patriarch) on Jun 23, 2014 at 02:19 UTC
    Why do you need this?