'ของจริง' 'ผู้ใช้' และ 'sys' หมายถึงอะไรในผลลัพธ์ของเวลา (1)


1746
$ time foo
real        0m0.003s
user        0m0.000s
sys         0m0.004s
$

'ของจริง', 'ผู้ใช้' และ 'sys' หมายถึงอะไรในผลลัพธ์ของเวลา

ตัวเลือกใดที่มีความหมายเมื่อทำการเปรียบเทียบแอพของฉัน


2
ฉันจะเข้าถึงหนึ่งในนั้นได้อย่างไร เช่นเวลาจริง
Mojtaba Ahmadi

1
@ConcernedOfTunbridgeWells
Mojtaba Ahmadi


7
หากโปรแกรมของคุณออกมาเร็วขนาดนั้นไม่มีโปรแกรมใดที่มีความหมายนั่นเป็นเพียงการเริ่มต้นค่าใช้จ่าย หากคุณต้องการวัดโปรแกรมทั้งหมดด้วยtimeให้ทำสิ่งที่ใช้เวลาอย่างน้อยหนึ่งวินาที
Peter Cordes

5
เป็นสิ่งสำคัญจริงๆที่จะต้องทราบว่าtimeเป็นคำหลักทุบตี ดังนั้นการพิมพ์man timeจะไม่ให้คุณมีหน้าคนสำหรับทุบตีค่อนข้างจะให้หน้าคนสำหรับtime /usr/bin/timeนี่ทำให้ฉันสะดุด
irritable_phd_syndrom

คำตอบ:


2059

สถิติเวลาดำเนินการจริงผู้ใช้และ Sys

หนึ่งในสิ่งเหล่านี้ไม่เหมือนกัน จริงหมายถึงเวลาที่ผ่านไปจริง ผู้ใช้และ Sys อ้างถึงเวลา CPU ที่ใช้โดยกระบวนการเท่านั้น

  • แบบเรียลไทม์เป็นนาฬิกาแขวนเวลา - เวลาตั้งแต่ต้นจนจบการโทร นี่เป็นเวลาที่ผ่านไปทั้งหมดรวมถึงตัวแบ่งเวลาที่ใช้โดยกระบวนการอื่นและเวลาที่กระบวนการใช้บล็อก (ตัวอย่างเช่นถ้ารอ I / O ให้เสร็จ)

  • ผู้ใช้คือจำนวนเวลา CPU ที่ใช้ในรหัสโหมดผู้ใช้ (นอกเคอร์เนล) ภายในกระบวนการ นี่เป็นเวลา CPU จริงที่ใช้ในการดำเนินการตามกระบวนการเท่านั้น กระบวนการและเวลาอื่น ๆ ที่กระบวนการใช้ไปจะไม่ถูกนับรวมในรูปนี้

  • Sysคือจำนวนเวลา CPU ที่ใช้ในเคอร์เนลภายในกระบวนการ นี่หมายถึงการประมวลผลเวลา CPU ที่ใช้ในการเรียกใช้ระบบภายในเคอร์เนลซึ่งตรงข้ามกับรหัสห้องสมุดซึ่งยังคงทำงานในพื้นที่ผู้ใช้ เช่นเดียวกับ 'ผู้ใช้' นี่เป็นเพียงเวลา CPU ที่กระบวนการใช้ ดูคำอธิบายสั้น ๆ ของโหมดเคอร์เนล (เรียกอีกอย่างว่าโหมด 'ผู้ควบคุม') และกลไกการเรียกระบบ

User+Sysจะบอกคุณว่า CPU ของคุณใช้เวลาในการประมวลผลเท่าใด โปรดทราบว่าสิ่งนี้อยู่ในซีพียูทั้งหมดดังนั้นหากกระบวนการมีหลายเธรด (และกระบวนการนี้ทำงานบนคอมพิวเตอร์ที่มีโปรเซสเซอร์มากกว่าหนึ่งตัว) อาจเกินเวลานาฬิกาแขวนที่รายงานโดยReal(ซึ่งมักจะเกิดขึ้น) โปรดทราบว่าในผลลัพธ์ตัวเลขเหล่านี้รวมถึงUserและSysเวลาของกระบวนการลูกทั้งหมด (และลูกหลานของพวกเขา) เช่นกันเมื่อพวกเขาสามารถรวบรวมได้เช่นโดยwait(2)หรือwaitpid(2)แม้ว่าการเรียกระบบพื้นฐานจะส่งคืนสถิติสำหรับกระบวนการและลูกแยกต่างหาก

ต้นกำเนิดของสถิติที่รายงานโดย time (1)

สถิติที่รายงานโดยtimeรวบรวมจากการเรียกใช้ระบบต่างๆ 'ผู้ใช้' และ 'Sys' มาจากwait (2)( POSIX ) หรือtimes (2)( POSIX ) ขึ้นอยู่กับระบบเฉพาะ 'ของจริง' คำนวณจากเวลาเริ่มต้นและเวลาสิ้นสุดที่รวบรวมจากการgettimeofday (2)โทร ขึ้นอยู่กับรุ่นของระบบสถิติอื่น ๆ เช่นจำนวนของสวิทช์บริบทอาจถูกรวบรวมโดยtimeเช่นจำนวนของสวิทช์บริบทอาจจะถูกรวบรวมโดย

บนเครื่องที่มีตัวประมวลผลหลายตัวกระบวนการแบบมัลติเธรดหรือกระบวนการฟอร์กกิ้งเด็กอาจมีเวลาที่ผ่านไปน้อยกว่าเวลา CPU ทั้งหมด - เนื่องจากเธรดหรือกระบวนการต่าง ๆ อาจทำงานแบบขนาน นอกจากนี้สถิติเวลาที่รายงานมาจากแหล่งกำเนิดที่แตกต่างกันดังนั้นเวลาที่บันทึกไว้สำหรับงานที่ทำงานสั้นมากอาจมีข้อผิดพลาดในการปัดเศษตามตัวอย่างที่โปสเตอร์ต้นฉบับแสดง

ไพรเมอร์แบบย่อใน Kernel vs. โหมดผู้ใช้

ใน Unix หรือระบบปฏิบัติการหน่วยความจำที่ได้รับการป้องกันโหมด'Kernel' หรือ 'Supervisor'หมายถึงโหมดสิทธิพิเศษที่ CPU สามารถใช้งานได้การดำเนินการพิเศษที่อาจส่งผลต่อความปลอดภัยหรือเสถียรภาพนั้นสามารถทำได้เมื่อ CPU ทำงานใน โหมดนี้; การกระทำเหล่านี้ไม่สามารถใช้ได้กับรหัสแอปพลิเคชัน ตัวอย่างของการกระทำดังกล่าวอาจเป็นการจัดการMMUเพื่อเข้าถึงพื้นที่ที่อยู่ของกระบวนการอื่น โดยทั่วไปรหัสโหมดผู้ใช้ไม่สามารถทำได้ (ด้วยเหตุผลที่ดี) แม้ว่าจะสามารถขอหน่วยความจำที่ใช้ร่วมกันได้จากเคอร์เนลได้สามารถอ่านหรือเขียนได้มากกว่าหนึ่งกระบวนการ ในกรณีนี้หน่วยความจำที่ใช้ร่วมกันจะถูกร้องขออย่างชัดเจนจากเคอร์เนลผ่านกลไกที่ปลอดภัยและกระบวนการทั้งสองจะต้องแนบกับมันอย่างชัดเจนเพื่อที่จะใช้มัน

โหมดสิทธิพิเศษมักจะถูกเรียกว่าโหมด 'เคอร์เนล' เนื่องจากเคอร์เนลถูกเรียกใช้งานโดย CPU ที่ทำงานในโหมดนี้ ในการเปลี่ยนไปใช้โหมดเคอร์เนลคุณต้องออกคำสั่งเฉพาะ (มักเรียกว่ากับดัก ) ที่เปลี่ยน CPU ให้ทำงานในโหมดเคอร์เนลและเรียกใช้รหัสจากตำแหน่งเฉพาะที่จัดขึ้นในตารางการกระโดด เพื่อเหตุผลด้านความปลอดภัยคุณไม่สามารถเปลี่ยนไปใช้โหมดเคอร์เนลและเรียกใช้รหัสโดยพลการ - กับดักถูกจัดการผ่านตารางที่อยู่ที่ไม่สามารถเขียนได้เว้นแต่ว่า CPU กำลังทำงานในโหมดผู้ดูแล คุณดักจับด้วยหมายเลขกับดักที่ชัดเจนและที่อยู่จะถูกค้นหาในตารางกระโดด เคอร์เนลมีจำนวนจุดเข้าควบคุมที่ จำกัด

การเรียก 'system' ในไลบรารี C (โดยเฉพาะที่อธิบายไว้ในส่วนที่ 2 ของ man page) มีองค์ประกอบโหมดผู้ใช้ซึ่งเป็นสิ่งที่คุณเรียกจากโปรแกรม C ของคุณ เบื้องหลังพวกเขาอาจออกระบบอย่างน้อยหนึ่งการเรียกไปยังเคอร์เนลเพื่อทำบริการเฉพาะเช่น I / O แต่พวกเขายังคงมีรหัสที่ทำงานอยู่ในโหมดผู้ใช้ นอกจากนี้ยังเป็นไปได้ค่อนข้างมากที่จะออกกับดักไปยังโหมดเคอร์เนลโดยตรงจากรหัสพื้นที่ผู้ใช้หากต้องการแม้ว่าคุณอาจจำเป็นต้องเขียนตัวอย่างของภาษาแอสเซมบลีเพื่อตั้งค่าการลงทะเบียนอย่างถูกต้องสำหรับการโทร

เพิ่มเติมเกี่ยวกับ 'sys'

มีสิ่งต่าง ๆ ที่รหัสของคุณไม่สามารถทำได้จากโหมดผู้ใช้ - สิ่งต่าง ๆ เช่นการจัดสรรหน่วยความจำหรือการเข้าถึงฮาร์ดแวร์ (HDD, เครือข่าย ฯลฯ ) สิ่งเหล่านี้อยู่ภายใต้การดูแลของเคอร์เนลและสามารถทำได้โดยลำพัง การดำเนินการบางอย่างเช่นmallocหรือfread/ fwriteจะเรียกใช้ฟังก์ชันเคอร์เนลเหล่านี้และจากนั้นจะนับเป็นเวลา 'sys' น่าเสียดายที่มันไม่ง่ายเหมือน "การเรียกไปที่ malloc ทุกครั้งจะถูกนับในเวลา 'sys'" การเรียกเพื่อmallocจะทำการประมวลผลของตัวเอง (ยังนับในเวลา 'ผู้ใช้') และจากนั้นบางแห่งตามทางที่มันอาจเรียกใช้ฟังก์ชันในเคอร์เนล (นับในเวลา 'sys') หลังจากกลับมาจากการเรียกเคอร์เนลจะมีเวลามากขึ้นใน 'ผู้ใช้' แล้วmallocจะกลับไปที่รหัสของคุณ สำหรับเมื่อสวิตช์เกิดขึ้นและใช้ไปเท่าใดในโหมดเคอร์เนล ... คุณไม่สามารถพูดได้ มันขึ้นอยู่กับการใช้งานของห้องสมุด นอกจากนี้ฟังก์ชั่นไร้เดียงสาอื่น ๆ ที่ดูเหมือนว่าอาจจะใช้mallocและไม่ชอบในพื้นหลังซึ่งจะมีเวลาอีกครั้งใน 'sys' แล้ว


15
เวลาที่ใช้ในกระบวนการเด็กนับเป็นจริง / sys หรือไม่?
รอน

1
@ron - ตามหน้า man Linux มันรวมเวลา 'c' กับเวลาของกระบวนการดังนั้นฉันคิดว่ามันไม่ แม้ว่าเวลาหลักและเวลาลูกจะแยกจากการโทรครั้ง (2) ฉันเดาว่ารุ่น Solaris / SysV (1) ทำอะไรที่คล้ายกัน
ConcOfOfTunbridgeWells

3
User + Sys ช่วยให้คุณวัดการใช้งาน CPU ของกระบวนการ คุณสามารถใช้มันเพื่อวัดประสิทธิภาพ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับโค้ดแบบมัลติเธรดที่มีแกน CPU มากกว่าหนึ่งแกนอาจทำงานกับการคำนวณ
เกี่ยวข้องกับอุโมงค์ทันบริดจ์

1
ไม่แม่นยำในหัวข้อ แต่การรัน "\ time <cmd>" นั้นน่าสนใจ - ให้รายละเอียดเพิ่มเติม: (ให้อภัยการจัดรูปแบบไม่ดีในความคิดเห็น): $ time ps PID TTY TIME CMD 9437 pts / 19 00:00:00 bash 11459 pts / 19 00:00:00 ps ผู้ใช้จริง 0m0.025s 0m0.004s sys 0m0.018s $ \ time ps PID TTY TIME CMD 9437 แต้ม / 19 00:00:00 bash 11461 pts / 19 00:00:00 เวลา 11462 pts / 19 00:00:00 ps 0.00 ผู้ใช้ 0.01 ระบบ 0: 00.02 ที่ผ่านมา 95% ซีพียู (0avgtext + 0avgdata 2160maxresident) k 0 อินพุท + 0 เอาท์พุท (0 เมเจอร์ + 103 นาที) หน้าค่าเริ่มต้น 0swaps $
kaiwan

1
(วิ่งออกมาจากตัวอักษรในความคิดเห็นก่อนหน้าดังนั้น): รายละเอียดเพิ่มเติม? ใช้ perf [1], [2] [1] perf.wiki.kernel.org/index.php/Main_Page [2] brendangregg.com/perf.html
kaiwan

285

เพื่อขยายบน คำตอบที่ได้รับการยอมรับ , ฉันแค่อยากจะให้เหตุผลว่าทำไมreal≠ +usersys

โปรดทราบว่าrealหมายถึงเวลาที่ผ่านไปจริงขณะที่userและsysค่าจะแทนเวลาดำเนินการของ CPU ดังนั้นในระบบมัลติคอร์นั้นuserและ / หรือsysเวลา (รวมถึงผลรวม) อาจเกินเวลาจริงได้ ตัวอย่างเช่นในแอป Java ที่ฉันใช้สำหรับชั้นเรียนฉันได้รับชุดของค่านี้:

real    1m47.363s
user    2m41.318s
sys     0m4.013s

11
ฉันมักจะสงสัยเกี่ยวกับเรื่องนี้ เนื่องจากฉันรู้ว่าโปรแกรมของฉันเป็นเธรดเดี่ยวความแตกต่างระหว่างผู้ใช้และเรียลไทม์จะต้องเป็นโอเวอร์เฮดของ VM ถูกต้องหรือไม่
Quantum7

9
ไม่จำเป็น; Sun JVM บนเครื่อง Solaris รวมถึง JVM ของ Apple บน Mac OS X สามารถใช้งานมากกว่าหนึ่งคอร์แม้ในแอพแบบเธรดเดียว ถ้าคุณทำตัวอย่างของกระบวนการจาวาคุณจะเห็นว่าสิ่งต่าง ๆ เช่นการรวบรวมขยะทำงานบนเธรดแยกกัน ฉันไม่รู้ว่าคุณต้องการจะใช้คำว่า "VM overhead" หรือไม่
lensovet

4
ฉันเดาว่าจำนวนโหวตมากขึ้นทำให้คุณมีชื่อเสียงมากในตอนนี้: D. แล้วคุณคิดยังไงกับสิ่งที่realเกินuserและsysทั้งหมด? OS ค่าใช้จ่ายเช่นการเปลี่ยนบริบทของเธรดอาจเป็นอย่างไร
มูฮัมหมัด Gelbana

19
ปัญหาที่อาจเป็นไปได้อีกอย่างคือ I / O: หากใบสมัครของคุณใช้เวลาพอสมควรในการรอรับไฟล์หรือสตรีมแน่นอนว่าเวลาจริงจะเกินเวลาผู้ใช้ / sys อย่างมากเนื่องจากไม่มีการใช้เวลา CPU ขณะรอการเข้าถึง ไฟล์หรือสิ่งที่คล้ายกัน
lensovet

1
@MuhammadGelbana - สิ่งนี้สามารถเกิดขึ้นได้หากแอปพลิเคชันถูกบล็อกไม่ให้ทำงานด้วยเหตุผลใดก็ตาม ตัวอย่างเช่นหากกำลังรอ I / O, การเชื่อมต่อ IPC หรือซ็อกเก็ตมันจะไม่ทำงานและไม่มีเวลา CPU จนกว่าจะมีการปิดกั้นการโทรกลับ
ConcernedOfTunbridgeWells

41

จริง : เวลาจริงที่ใช้ในการเรียกใช้กระบวนการตั้งแต่ต้นจนจบราวกับว่ามันถูกวัดโดยมนุษย์ที่มีนาฬิกาจับเวลา

ผู้ใช้ : เวลาสะสมของ CPU ทั้งหมดที่ใช้ในระหว่างการคำนวณ

sys : เวลาสะสมที่ใช้โดย CPU ทั้งหมดระหว่างงานที่เกี่ยวข้องกับระบบเช่นการจัดสรรหน่วยความจำ

โปรดสังเกตว่าบางครั้ง user + sys อาจมากกว่าของจริงเนื่องจากโปรเซสเซอร์หลายตัวอาจทำงานพร้อมกัน


sysเป็น CPU-เวลาที่ใช้ในการเรียกระบบ (และไสหน้าผิด?)
ปีเตอร์ Cordes

1
realมักจะอธิบายว่าเป็น "นาฬิกาแขวน" เวลา
Peter Cordes

30

ตัวอย่าง POSIX C ที่รันได้น้อยที่สุด

เพื่อทำให้สิ่งต่าง ๆ เป็นรูปธรรมมากขึ้นฉันต้องการยกตัวอย่างกรณีที่รุนแรงที่สุดtimeด้วยโปรแกรมทดสอบ C ขั้นต่ำ

โปรแกรมทั้งหมดสามารถรวบรวมและรันด้วย:

gcc -ggdb3 -o main.out -pthread -std=c99 -pedantic-errors -Wall -Wextra main.c
time ./main.out

และได้รับการทดสอบใน Ubuntu 18.10, GCC 8.2.0, glibc 2.28, เคอร์เนล Linux 4.18, แล็ปท็อป ThinkPad P51, Intel Core i7-7820HQ CPU (4 คอร์ / 8 เธรด), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB)

นอน

การนอนไม่ยุ่งไม่นับรวมในuserหรืออย่างsysเดียวเท่านั้นrealเพียง

ตัวอย่างเช่นโปรแกรมที่สลีปหนึ่งวินาที:

#define _XOPEN_SOURCE 700
#include <stdlib.h>
#include <unistd.h>

int main(void) {
    sleep(1);
    return EXIT_SUCCESS;
}

GitHub ต้นน้ำต้นน้ำ

แสดงผลดังนี้:

real    0m1.003s
user    0m0.001s
sys     0m0.003s

การพักตัวเดียวกันสำหรับโปรแกรมที่ถูกบล็อกเมื่อ IO พร้อมใช้งาน

ตัวอย่างเช่นโปรแกรมต่อไปนี้รอให้ผู้ใช้ป้อนอักขระและกด Enter:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("%c\n", getchar());
    return EXIT_SUCCESS;
}

GitHub ต้นน้ำ

และถ้าคุณรอประมาณหนึ่งวินาทีมันจะออกมาเหมือนตัวอย่างการนอนหลับ:

real    0m1.003s
user    0m0.001s
sys     0m0.003s

ด้วยเหตุผลนี้timeสามารถช่วยคุณแยกแยะความแตกต่างระหว่าง CPU และโปรแกรมที่เชื่อมโยงกับ IO: คำว่า "CPU bound" และ "I / O bound" หมายถึงอะไร?

หลายกระทู้

ตัวอย่างต่อไปนี้ทำการnitersวนซ้ำของ CPU-bound ที่ไม่ได้ใช้งานบนnthreadsเธรด:

#define _XOPEN_SOURCE 700
#include <assert.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

uint64_t niters;

void* my_thread(void *arg) {
    uint64_t *argument, i, result;
    argument = (uint64_t *)arg;
    result = *argument;
    for (i = 0; i < niters; ++i) {
        result = (result * result) - (3 * result) + 1;
    }
    *argument = result;
    return NULL;
}

int main(int argc, char **argv) {
    size_t nthreads;
    pthread_t *threads;
    uint64_t rc, i, *thread_args;

    /* CLI args. */
    if (argc > 1) {
        niters = strtoll(argv[1], NULL, 0);
    } else {
        niters = 1000000000;
    }
    if (argc > 2) {
        nthreads = strtoll(argv[2], NULL, 0);
    } else {
        nthreads = 1;
    }
    threads = malloc(nthreads * sizeof(*threads));
    thread_args = malloc(nthreads * sizeof(*thread_args));

    /* Create all threads */
    for (i = 0; i < nthreads; ++i) {
        thread_args[i] = i;
        rc = pthread_create(
            &threads[i],
            NULL,
            my_thread,
            (void*)&thread_args[i]
        );
        assert(rc == 0);
    }

    /* Wait for all threads to complete */
    for (i = 0; i < nthreads; ++i) {
        rc = pthread_join(threads[i], NULL);
        assert(rc == 0);
        printf("%" PRIu64 " %" PRIu64 "\n", i, thread_args[i]);
    }

    free(threads);
    free(thread_args);
    return EXIT_SUCCESS;
}

GitHub รหัสพล็อตต้นน้ำ

จากนั้นเราพล็อตวอลล์ผู้ใช้และ sys เป็นฟังก์ชันของจำนวนเธรดสำหรับการทำซ้ำ 10 ^ 10 บนซีพียูไฮเปอร์เธรด 8 ของฉัน:

ป้อนคำอธิบายรูปภาพที่นี่

ข้อมูลที่พล็อต

จากกราฟเราจะเห็นว่า:

  • สำหรับแอพพลิเคชั่นที่ใช้ซีพียูแบบ Single Core แบบ Wall และผู้ใช้ก็เหมือนกัน

  • สำหรับ 2 คอร์ผู้ใช้อยู่ที่ 2x wall ซึ่งหมายความว่าเวลาของผู้ใช้จะถูกนับในทุกเธรด

    ผู้ใช้เพิ่มเป็นสองเท่าโดยทั่วไปและในขณะที่กำแพงยังคงเหมือนเดิม

  • สิ่งนี้ดำเนินต่อไปถึง 8 เธรดซึ่งตรงกับจำนวนไฮเปอร์เธรดในคอมพิวเตอร์ของฉัน

    หลังจาก 8 กำแพงก็เริ่มเพิ่มขึ้นเช่นกันเพราะเราไม่มีซีพียูพิเศษใด ๆ ที่จะเพิ่มการทำงานในเวลาที่กำหนด!

    อัตราส่วนจะมีอยู่ ณ จุดนี้

โปรดทราบว่ากราฟนี้เป็นเพียงเพื่อให้ง่ายและชัดเจนเพราะการทำงานเป็นอย่างหมดจด CPU-bound: ถ้ามันถูกหน่วยความจำที่ถูกผูกไว้แล้วเราจะได้รับการตกอยู่ในการปฏิบัติงานมากก่อนหน้านี้มีแกนน้อยลงเพราะการเข้าถึงหน่วยความจำจะเป็นคอขวดตามที่แสดงอะไร คำว่า "CPU bound" และ "I / O bound" หมายถึงอะไร

Sys ทำงานหนักกับ sendfile

ภาระงานที่หนักที่สุดที่ฉันจะได้รับคือการใช้งานsendfileซึ่งจะทำการคัดลอกไฟล์ในพื้นที่เคอร์เนล:คัดลอกไฟล์ด้วยวิธีที่ปลอดภัยและมีประสิทธิภาพ

ดังนั้นฉันจึงจินตนาการว่า in-kernel memcpyนี้จะเป็นการทำงานที่ใช้ CPU มาก

ก่อนอื่นฉันเริ่มต้นไฟล์สุ่มขนาดใหญ่ 10GiB ด้วย:

dd if=/dev/urandom of=sendfile.in.tmp bs=1K count=10M

จากนั้นเรียกใช้รหัส:

#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv) {
    char *source_path, *dest_path;
    int source, dest;
    struct stat stat_source;
    if (argc > 1) {
        source_path = argv[1];
    } else {
        source_path = "sendfile.in.tmp";
    }
    if (argc > 2) {
        dest_path = argv[2];
    } else {
        dest_path = "sendfile.out.tmp";
    }
    source = open(source_path, O_RDONLY);
    assert(source != -1);
    dest = open(dest_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    assert(dest != -1);
    assert(fstat(source, &stat_source) != -1);
    assert(sendfile(dest, source, 0, stat_source.st_size) != -1);
    assert(close(source) != -1);
    assert(close(dest) != -1);
    return EXIT_SUCCESS;
}

GitHub ต้นน้ำ

ซึ่งให้เวลาระบบโดยทั่วไปส่วนใหญ่เป็นไปตามที่คาดไว้:

real    0m2.175s
user    0m0.001s
sys     0m1.476s

ฉันยังอยากรู้ว่าtimeจะแยกแยะระหว่าง syscalls ของกระบวนการที่แตกต่างกันหรือไม่ดังนั้นฉันจึงลอง:

time ./sendfile.out sendfile.in1.tmp sendfile.out1.tmp &
time ./sendfile.out sendfile.in2.tmp sendfile.out2.tmp &

และผลที่ได้คือ:

real    0m3.651s
user    0m0.000s
sys     0m1.516s

real    0m4.948s
user    0m0.000s
sys     0m1.562s

เวลา sys มีค่าเท่ากันสำหรับทั้งกระบวนการเดียว แต่เวลาผนังใหญ่ขึ้นเนื่องจากกระบวนการแข่งขันกันเพื่อเข้าถึงการอ่านดิสก์

ดังนั้นดูเหมือนว่าในความเป็นจริงบัญชีที่กระบวนการเริ่มต้นทำงานเคอร์เนลที่กำหนด

รหัสแหล่งทุบตี

เมื่อคุณทำtime <cmd>บน Ubuntu เพียงใช้คำหลัก Bash ดังที่เห็นได้จาก:

type time

ผลลัพธ์ใด:

time is a shell keyword

ดังนั้นเราจึง grep แหล่งที่มาในรหัสที่มา Bash 4.19 สำหรับสตริงออก:

git grep '"user\b'

ซึ่งทำให้เรามีฟังก์ชันexecute_cmd.ctime_commandซึ่งใช้:

  • gettimeofday()และgetrusage()ถ้าทั้งสองมีอยู่
  • times() มิฉะนั้น

ซึ่งทั้งหมดเป็นลินุกซ์สายระบบและฟังก์ชั่น POSIX

Coreutils ซอร์สโค้ด GNU

ถ้าเราเรียกมันว่า:

/usr/bin/time

จากนั้นจะใช้การดำเนินการ GNU Coreutils

อันนี้ซับซ้อนกว่าเล็กน้อย แต่แหล่งข้อมูลที่เกี่ยวข้องดูเหมือนจะเป็นresuse.cและมันจะ:

  • การเรียกที่ไม่ใช่ POSIX BSD wait3หากมีให้
  • timesและgettimeofdayอื่น ๆ

14

Real แสดงเวลาหมุนเวียนทั้งหมดสำหรับกระบวนการ ในขณะที่ผู้ใช้แสดงเวลาดำเนินการสำหรับคำแนะนำที่ผู้ใช้กำหนดและ Sys ใช้สำหรับดำเนินการเรียกระบบ!

เวลาจริงรวมถึงเวลาที่รอด้วย (เวลารอ I / O เป็นต้น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.