times#
Αναφέρει τον χρόνο CPU που κατανάλωσε αυτή η διεργασία και τα τερματισμένα παιδιά της.
times asks the kernel how many seconds of user-mode and kernel-mode CPU have been charged to the current process, and - separately - to children that have already been reaped. The return is four floating-point seconds: user, system, child-user, child-system. It answers «how much CPU have I burned?», not «how much wall-clock time has passed?» - for that, see time.
Σύνοψη#
my ($user, $system, $cuser, $csystem) = times;
my $user_only = times; # scalar context
Τι επιστρέφεται#
Σε περιβάλλον λίστας, τέσσερις τιμές:
$user- χρόνος CPU που δαπανήθηκε σε κώδικα σε λειτουργία χρήστη αυτής της διεργασίας.$system- χρόνος CPU που δαπανήθηκε στον πυρήνα εκ μέρους αυτής της διεργασίας.$cuser- χρόνος CPU σε λειτουργία χρήστη τερματισμένων θυγατρικών διεργασιών.$csystem- χρόνος CPU σε λειτουργία πυρήνα τερματισμένων θυγατρικών διεργασιών.
Και τα τέσσερα είναι δευτερόλεπτα ως floats διπλής ακρίβειας· η ανάλυση είναι σε μικροδευτερόλεπτα σε Linux (προέρχεται από την getrusage).
Σε βαθμωτό περιβάλλον, η times επιστρέφει μόνο το $user.
Η times δεν δέχεται ορίσματα και δεν μπορεί να αποτύχει με τρόπο ορατό στον καλούντα.
Χρόνοι των παιδιών - ο κανόνας «τερματισμένα»#
Τα $cuser και $csystem αθροίζουν CPU μόνο από παιδιά που έχουν συγκομιστεί - δηλαδή μια wait ή waitpid έχει επιτυχώς συλλέξει την κατάσταση εξόδου τους, ή συγκομίστηκαν αυτόματα επειδή το $SIG{CHLD} είχε τεθεί σε 'IGNORE'. Παιδί που εξακολουθεί να εκτελείται, ή έχει εξέλθει αλλά δεν έχει ακόμη συγκομιστεί (zombie), δεν συνεισφέρει τίποτα.
Αυτό έχει σημασία όταν μετράτε μια pipeline που δημιουργεί workers:
my $pid = fork;
if ($pid == 0) { do_work(); exit }
# (busy child runs here)
my ($u0, $s0, $cu0, $cs0) = times; # $cu0, $cs0 still 0
waitpid($pid, 0);
my ($u1, $s1, $cu1, $cs1) = times; # now $cu1, $cs1 reflect child
Μέχρι να επιστρέψει η waitpid, η CPU του παιδιού δεν εμφανίζεται στους χρόνους times του γονέα.
Παραδείγματα#
Μετρήστε το κόστος CPU ενός μπλοκ εργασιών, εξαιρώντας τους ύπνους πραγματικού χρόνου ή τις αναμονές I/O:
my ($u0, $s0) = times;
compute_heavy();
my ($u1, $s1) = times;
printf "compute used %.3f s user + %.3f s system\n",
$u1 - $u0, $s1 - $s0;
Συγκρίνετε τον χρόνο CPU με τον πραγματικό χρόνο - χαμηλή αναλογία σημαίνει ότι η διεργασία ήταν κυρίως σε αναμονή αντί να υπολογίζει:
use Time::HiRes qw(time);
my $t0 = time;
my ($u0, $s0) = times;
do_mixed_io_and_compute();
my $wall = time - $t0;
my ($u1, $s1) = times;
printf "cpu/wall = %.2f\n", ($u1 - $u0 + $s1 - $s0) / $wall;
Αποδώστε έναν παράλληλο φόρτο εργασίας στα παιδιά του. Συγκομίστε κάθε παιδί πριν διαβάσετε τους χρόνους times:
my @pids = map { my $p = fork; $p == 0 ? (worker($_), exit) : $p } 1..4;
waitpid($_, 0) for @pids;
my (undef, undef, $cu, $cs) = times;
printf "workers used %.2f s user + %.2f s system\n", $cu, $cs;
Βαθμωτό περιβάλλον όταν μόνο ο user time έχει σημασία - π.χ. μια γρήγορη εκτύπωση αυτο-προφίλ:
printf STDERR "[%.2f] reached checkpoint\n", scalar times;
Οριακές περιπτώσεις#
Χωρίς ορίσματα, χωρίς πρωτότυπο για να ανησυχήσετε. Η
timesείναι ενσωματωμένη χωρίς ορίσματα· ταtimes()καιtimesαναλύονται ταυτόσημα. Δεν είναι ο τελεστής μεταγραμματισμού - αυτός είναι ηtr///(ψευδώνυμοy///), που είναι ξεχωριστό διακριτικό.Το βαθμωτό περιβάλλον έναντι περιβάλλοντος λίστας είναι κρίσιμο. Το να γράψετε
my $t = times;συνδέει το$userμε το$t, απορρίπτοντας τις άλλες τρεις τιμές σιωπηρά. Χρησιμοποιήστεmy ($u,$s,$cu,$cs) = times;όταν τις θέλετε όλες.Τα μη συγκομισμένα παιδιά δεν μετράνε. Δείτε τον κανόνα «τερματισμένα» παραπάνω. Η ανάγνωση των
timesπριν τηνwaitδίνει$cuser == $csystem == 0ακόμη και όταν το παιδί καίει ορατά CPU στοtop.Τα threads μετράνε. Σε Linux, εργασία σε threads πυρήνα στην τρέχουσα διεργασία εμφανίζεται στα
$user/$systemόπως η εργασία ενός μόνο thread. Τα threads σε χωριστή διεργασία δεν εμφανίζονται, μέχρι αυτή η διεργασία να εξέλθει και να συγκομιστεί.Το ρολόι είναι μονότονο εντός διεργασίας, όχι πραγματικού χρόνου. Η
timesδεν πηγαίνει ποτέ προς τα πίσω στη διάρκεια ζωής μιας διεργασίας, αλλά διαδοχικές κλήσειςtimesδεν είναι άμεσα συγκρίσιμες μεταξύ γονέα και παιδιού - η κάθε λογιστικήgetrusageείναι τοπική.Ανάλυση. Το Linux αναφέρει χτύπους ανάλυσης μικροδευτερολέπτου μέσω
getrusage, οπότε σύντομες μετρήσεις (κάτω από millisecond) είναι θορυβώδεις αλλά όχι μηδέν. Για χρονομέτρηση πραγματικού χρόνου υψηλής ακρίβειας, χρησιμοποιήστε τηνTime::HiRes::time, όχι τηνtimes.Υπερχείλιση. Οι τιμές είναι floats· μπορούν καταρχήν να χάσουν ακρίβεια κάτω από το μικροδευτερόλεπτο μετά από πολύ μεγάλες εκτελέσεις (χρόνια CPU), αλλά αυτό δεν είναι ζήτημα για κανονικά προγράμματα.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
time- δευτερόλεπτα πραγματικού χρόνου από την epoch· χρησιμοποιήστε την όταν θέλετε χρόνο πραγματικού χρόνου που πέρασε, όχι χρόνο CPUTime::HiRes::time- πραγματικός χρόνος υψηλής ανάλυσης, ο συνηθισμένος εταίρος για λογιστική CPUPOSIX::times- περιτύλιγμα POSIX που επιστρέφει επιπλέον τιμή πραγματικού χρόνου «χτύποι ρολογιού από την εκκίνηση»· χρησιμοποιήστε το όταν χρειάζεστε το πεδίο που πέρασε το οποίο η ενσωματωμένη παραλείπειwait- συγκομιδή παιδιού ώστε η CPU του να αρχίσει να μετράει στα$cuser/$csystemwaitpid- συγκομιδή συγκεκριμένου παιδιού για τον ίδιο λόγο, χωρίς μπλοκάρισμα σε άσχεταfork- η λειτουργία της οποίας το κόστος εμφανίζεται στις στήλες παιδιού μόλις συγκομιστεί το παιδί