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 שיוצר עובדים:
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 של בלוק עבודה, לא כולל sleeps של שעון־קיר או המתנות 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;
הקשר סקלר כאשר רק זמן המשתמש חשוב - לדוגמה הדפסת self-profiling מהירה:
printf STDERR "[%.2f] reached checkpoint\n", scalar times;
מקרי קצה#
ללא ארגומנטים, אין prototype לדאוג ממנו.
timesהוא built-in ללא ארגומנטים;times()ו־timesמתפענחים בצורה זהה. הוא אינו אופרטור התעתוק - זהtr///(כינויy///), שהוא טוקן נפרד.הקשר סקלר לעומת הקשר רשימה נושא־עומס. כתיבת
my $t = times;קושרת את$userל־$t, ומשליכה את שלושת הערכים האחרים בשקט. השתמשו ב־my ($u,$s,$cu,$cs) = times;כאשר אתם רוצים את כולם.ילדים שלא נאספו אינם נספרים. ראו את כלל ה־״הסתיים״ למעלה. קריאת
timesלפניwaitנותנת$cuser == $csystem == 0גם כאשר הילד שורף CPU גלוי ב־top.Threads כן נספרים. ב־Linux, עבודה ב־kernel-threads בתהליך הנוכחי מופיעה ב־
$user/$systemבדיוק כמו עבודה ב־single-thread. Threads בתהליך נפרד לא, עד שאותו תהליך יוצא ונאסף.השעון מונוטוני־בתוך־תהליך, לא שעון־קיר.
timesאף פעם אינו הולך אחורה לאורך חיי תהליך יחיד, אך קריאותtimesעוקבות אינן ניתנות להשוואה ישירה בין הורה לילד - כל חשבונאותgetrusageהיא מקומית.רזולוציה. Linux מדווח על ticks ברזולוציית מיקרו־שנייה דרך
getrusage, ולכן מדידות קצרות (תת־מילישנייה) רועשות אך לא אפס. לתזמון שעון־קיר בדיוק גבוה, השתמשו ב־Time::HiRes::time, לא ב־times.גלישה. הערכים הם floats; הם יכולים עקרונית לאבד דיוק תת־מיקרו־שנייה לאחר ריצות ארוכות מאוד (שנים של CPU), אך זה אינו דאגה לתוכניות רגילות.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
time- שניות שעון־קיר מאז ה־epoch; השתמשו בו כאשר אתם רוצים זמן ממשי שחלף, לא זמן CPUTime::HiRes::time- זמן שעון־קיר ברזולוציה גבוהה, השותף הרגיל לחשבונאות CPUPOSIX::times- עטיפה של POSIX המחזירה ערך נוסף של ״clock ticks since boot״ בזמן ממשי; השתמשו בו כאשר אתם זקוקים לשדה החלף שה־built-in משמיטwait- אספו ילד כך שה־CPU שלו יתחיל להיספר ב־$cuser/$csystemwaitpid- אספו ילד ספציפי מאותה סיבה, ללא חסימה על ילדים לא־קשוריםfork- הפעולה שעלותה מופיעה בעמודות הילד ברגע שהילד נאסף