시간 (1)의 출력에서 ​​'실제', '사용자'및 'sys'는 무엇을 의미합니까?


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

'실제', '사용자'및 'sys'는 시간의 출력에서 ​​무엇을 의미합니까?

내 앱을 벤치마킹 할 때 어떤 의미가 있습니까?


2
그 중 하나에 만 어떻게 액세스 할 수 있습니까? 예를 들어 실시간?
Mojtaba Ahmadi

1
@ConcernedOfTunbridgeWells
Ahmadi


7
프로그램이 그렇게 빨리 종료되면 아무런 의미가 없으면 시작 오버 헤드 일뿐입니다. 로 전체 프로그램을 측정하려면 time적어도 1 초 정도 걸리는 작업을 수행하십시오.
Peter Cordes

5
그것이 timebash 키워드라는 점을 명심해야 합니다. 따라서 입력이 man time되어 있지 bash는 당신에게 사람 페이지를 제공 time, 오히려 man 페이지를주고있다 /usr/bin/time. 이것은 나를 트립했다.
irritable_phd_syndrom

답변:


2059

실제, 사용자 및 Sys 프로세스 시간 통계

이 중 하나는 다른 것과 다릅니다. 실제는 실제 경과 시간을 나타냅니다. 사용자 및 Sys 는 프로세스에서만 사용되는 CPU 시간을 나타 냅니다.

  • 실제 벽 시계 시간은 - 전화의 처음부터 끝까지 시간입니다. 다른 프로세스에서 사용한 시간 조각과 프로세스가 차단 된 시간 (예 : I / O가 완료되기를 기다리는 경우)을 포함하여 모두 경과 된 시간입니다.

  • User 는 프로세스 에서 사용자 모드 코드 (커널 외부)에 소비 된 CPU 시간 입니다. 이것은 프로세스 실행에 사용 된 실제 CPU 시간입니다. 프로세스가 차단 한 다른 프로세스와 시간은이 수치에 포함되지 않습니다.

  • Sys 는 프로세스 내 커널에서 소비 한 CPU 시간입니다. 이것은 여전히 사용자 공간에서 실행되는 라이브러리 코드와 달리 커널 내의 시스템 호출에 소비 된 CPU 시간을 실행하는 것을 의미 합니다. 'user'와 마찬가지로 프로세스에서 사용하는 CPU 시간입니다. 커널 모드 ( '감독자'모드라고도 함) 및 시스템 호출 메커니즘에 대한 간략한 설명은 아래를 참조하십시오.

User+Sys프로세스에서 사용한 실제 CPU 시간을 알려줍니다. 이는 모든 CPU에 적용되므로 프로세스에 여러 스레드가 있고 (이 프로세스가 둘 이상의 프로세서가있는 컴퓨터에서 실행중인 Real경우) 일반적으로 발생하는 벽시계 시간을 초과 할 수 있습니다 . 출력에 이러한 수치에는 모든 하위 프로세스 (및 하위 항목)의 시간 UserSys시간뿐만 아니라 예를 들어 wait(2)또는 waitpid(2)에 의해 수집 될 수있는 시간 도 포함 됩니다 ( 기본 시스템 호출은 프로세스 및 하위 프로세스에 대한 통계를 개별적으로 리턴 함).

에 의해보고 된 통계의 기원 time (1)

보고 된 통계는 time다양한 시스템 호출에서 수집됩니다. 'User'및 'Sys' 는 특정 시스템에 따라 wait (2)( POSIX ) 또는 times (2)( POSIX )에서 가져옵니다. '실제'는 gettimeofday (2)통화 에서 수집 된 시작 및 종료 시간으로 계산됩니다 . 시스템 버전에 따라 컨텍스트 스위치 수와 같은 다양한 기타 통계도 수집 할 수 있습니다 time.

다중 프로세서 시스템에서 다중 스레드 프로세스 또는 하위 프로세스를 처리하는 프로세스는 다른 스레드 또는 프로세스가 병렬로 실행될 수 있으므로 전체 CPU 시간보다 경과 시간이 더 짧을 수 있습니다. 또한보고 된 시간 통계는 서로 다른 출처에서 왔으므로 매우 짧은 실행 작업에 대해 기록 된 시간에는 원래 포스터에서 제공 한 예와 같이 반올림 오류가 발생할 수 있습니다.

커널 대 사용자 모드에 대한 간단한 입문서

Unix 또는 모든 보호 메모리 운영 체제에서 'Kernel'또는 'Supervisor' 모드는 CPU가 작동 할 수 있는 권한 모드 를 나타냅니다 . 보안 또는 안정성에 영향을 줄 수있는 특정 권한 동작은 CPU가 작동 할 때만 수행 할 수 있습니다. 이 모드; 이러한 조치는 애플리케이션 코드에서 사용할 수 없습니다. 이러한 조치의 예는 다른 프로세스의 주소 공간에 액세스하기 위해 MMU 를 조작하는 것입니다 . 일반적으로 사용자 모드 코드는 커널에서 공유 메모리 를 요청할 수 있지만 (이유가있는 경우)이를 수행 할 수 없습니다.여러 프로세스에서 읽거나 쓸 수 있습니다. 이 경우 공유 메커니즘은 보안 메커니즘을 통해 커널에서 명시 적으로 요청되며이를 사용하려면 두 프로세스 모두 명시 적으로 연결해야합니다.

특권 모드는 커널이이 모드에서 실행되는 CPU에 의해 실행되므로 일반적으로 '커널'모드라고합니다. 커널 모드로 전환하려면 CPU를 커널 모드에서 실행으로 전환 하고 점프 테이블에있는 특정 위치에서 코드 를 실행 하는 특정 명령 (종종 트랩 ) 을 발행해야 합니다. 보안상의 이유로 커널 모드로 전환하고 임의 코드를 실행할 수 없습니다. 트랩은 CPU가 감독자 모드에서 실행되고 있지 않으면 쓸 수없는 주소 테이블을 통해 관리됩니다. 명시적인 트랩 번호로 트랩하면 주소가 점프 테이블에서 조회됩니다. 커널에는 유한 한 수의 제어 된 진입 점이 있습니다.

C 라이브러리의 '시스템'호출 (특히 매뉴얼 페이지의 섹션 2에 설명 된 호출)에는 실제로 C 프로그램에서 호출하는 사용자 모드 구성 요소가 있습니다. 뒤에서, I / O와 같은 특정 서비스를 수행하기 위해 커널에 하나 이상의 시스템 호출을 발행 할 수 있지만 여전히 사용자 모드에서 실행되는 코드가 있습니다. 원하는 경우 사용자 공간 코드에서 커널 모드로 트랩을 직접 발행하는 것도 가능하지만 호출에 대한 레지스터를 올바르게 설정하기 위해 어셈블리 언어 스 니펫을 작성해야 할 수도 있습니다.

'sys'에 대한 추가 정보

메모리 할당 또는 하드웨어 액세스 (HDD, 네트워크 등)와 같이 사용자 모드에서 코드가 수행 할 수없는 작업이 있습니다. 이것들은 커널의 감독하에 있으며 혼자서도 할 수 있습니다. malloc또는 fread/ 와 같은 일부 작업 fwrite은 이러한 커널 기능을 호출 한 다음 'sys'시간으로 계산됩니다. 불행히도 "모든 malloc 호출은 'sys'시간으로 계산됩니다"만큼 간단하지 않습니다. 호출 malloc은 자체 처리 (여전히 '사용자'시간으로 계산)를 수행 한 다음 커널에서 함수를 호출 할 수있는 방식 ( 'sys'시간으로 계산)을 수행합니다. 커널 호출에서 돌아온 후 'user'에 시간이 더 있습니다.malloc코드로 돌아갑니다. 스위치가 언제 발생하고 커널 모드에서 소비되는 양은 말할 수 없습니다. 라이브러리 구현에 따라 다릅니다. 또한 다른 겉보기에 무해한 기능도 malloc백그라운드에서 사용할 수 있으며 'sys'에 시간이 다시 걸립니다.


15
자식 프로세스가 보낸 시간이 실제 / 시스템으로 계산됩니까?
ron

1
@ron-Linux 매뉴얼 페이지에 따르면 프로세스 시간과 'c'시간을 집계하므로 그렇게 생각합니다. 그러나 부모 시간과 자식 시간은 times (2) 호출과 별도로 사용할 수 있습니다. 시간 (1)의 Solaris / SysV 버전이 비슷한 것을 수행한다고 생각합니다.
ConcernedOfTunbridgeWells

3
User + Sys를 사용하면 프로세스의 CPU 사용량을 측정 할 수 있습니다. 이를 사용하여 성능을 벤치마킹 할 수 있습니다. 이 기능은 하나 이상의 CPU 코어가 계산 작업을 수행 할 수있는 다중 스레드 코드에 특히 유용합니다.
ConcernedOfTunbridgeWells

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 시간 CMD 9437 pts / 19 00:00:00 bash 11461 pts / 19 00:00:00 시간 11462 PTS / 19 0시 0분 0초 추신 0.00user 0.01system 0 : 95 % 00.02elapsed CPU (0avgtext 0avgdata 2160maxresident +)의 K + 0inputs 0outputs (0major + 103minor) pagefaults 0swaps $
kaiwan

1
(이전 주석에서 문자가 부족한 경우) : 자세한 내용은? perf [1], [2]를 사용하십시오. [1] perf.wiki.kernel.org/index.php/Main_Page [2] brendangregg.com/perf.html
kaiwan

285

허용 된 답변 을 확장 하기 위해 realuser+ 이유를 제공하고 싶었습니다 sys.

염두에 유지 real하면서, 실제 경과 시간을 표시 user하고 sys값이 CPU의 실행 시간을 나타낸다. 결과적으로 멀티 코어 시스템에서 user및 / 또는 sys시간 ( 및 합계)은 실제로 실시간을 초과 할 수 있습니다 . 예를 들어, Java 응용 프로그램에서 클래스에 대해 실행중인 경우 다음 값 세트를 얻습니다.

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

11
나는 항상 이것에 대해 궁금했다. 내 프로그램이 단일 스레드임을 알고 있으므로 사용자와 실시간의 차이는 VM 오버 헤드 여야합니다. 맞습니까?
Quantum7

9
반드시 그런 것은 아닙니다. Solaris 시스템의 Sun JVM 및 Mac OS X의 Apple JVM은 단일 스레드 응용 프로그램에서도 둘 이상의 코어를 사용하도록 관리합니다. Java 프로세스의 샘플을 수행하면 가비지 수집과 같은 항목이 별도의 스레드에서 실행되는 것을 볼 수 있습니다 (내 머리 꼭대기에서 기억하지 못하는 다른 것들도 있음). 그래도 "VM 오버 헤드"라는 용어를 사용하고 싶은지 모르겠습니다.
lensovet

4
나는 많은 투표권이 당신에게 충분한 평판을 주었다고 생각합니다 : D. 그래서 당신은 real초과 usersys총 에 대해 어떻게 생각 하십니까? 스레드 컨텍스트 전환과 같은 OS 오버 헤드는?
Muhammad Gelbana

19
또 다른 잠재적 인 문제는 I / O 일 수 있습니다. 응용 프로그램이 파일이나 스트림을 수신하기 위해 많은 시간을 소비하는 경우 액세스를 기다리는 동안 CPU 시간이 사용되지 않기 때문에 실제 시간이 사용자 / 시스템 시간을 크게 초과합니다. 파일 또는 유사한 것으로.
lensovet

1
@MuhammadGelbana-응용 프로그램이 어떤 이유로 실행되지 않도록 차단 된 경우 발생할 수 있습니다. 예를 들어, I / O, IPC 또는 소켓 연결을 기다리는 경우 유휴 상태가되어 차단 호출이 반환 될 때까지 CPU 시간이 누적되지 않습니다.
ConcernedOfTunbridgeWells

41

real : 초시계를 가진 사람이 측정 한 것처럼 프로세스를 처음부터 끝까지 실행하는 데 소요 된 실제 시간

user : 계산 중 모든 CPU에서 소비 한 누적 시간

sys : 메모리 할당과 같은 시스템 관련 작업 중에 모든 CPU에서 소비 한 누적 시간입니다.

여러 프로세서가 동시에 작동 할 수 있기 때문에 때때로 user + sys가 실제보다 클 수 있습니다.


sysCPU 시간이 시스템 호출 (및 페이지 오류 처리기)에 소비됩니까?
Peter 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의 상류 .

그리고 약 1 초 정도 기다리면 수면 예제와 같이 다음과 같이 출력됩니다.

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

이러한 이유로 timeCPU와 IO 바운드 프로그램을 구별 할 수 있습니다. "CPU 바운드"및 "I / O 바운드"라는 용어는 무엇을 의미합니까?

여러 스레드

다음 예제는 스레드 niters에서 쓸모없는 순수한 CPU 바운드 작업의 반복을 수행 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 업스트림 + 플롯 코드 .

그런 다음 8 하이퍼 스레드 CPU에서 고정 10 ^ 10 반복에 대한 스레드 수의 함수로 wall, user 및 sys를 플로팅합니다.

여기에 이미지 설명을 입력하십시오

데이터를 플롯합니다 .

그래프에서 우리는 다음을 볼 수 있습니다.

  • CPU를 많이 사용하는 단일 코어 애플리케이션의 경우 월과 사용자는 거의 같습니다

  • 2 코어의 경우 사용자는 벽의 약 2 배이므로 모든 스레드에서 사용자 시간이 계산됩니다.

    사용자는 기본적으로 두 배가되었고 벽은 동일하게 유지되었습니다.

  • 이것은 최대 8 개의 스레드까지 계속되며, 이는 컴퓨터의 여러 하이퍼 스레드와 일치합니다.

    8 시간이 지나면 주어진 시간에 더 많은 작업을 할 CPU가 없기 때문에 벽도 증가하기 시작합니다!

    이 시점의 비율은 정점입니다.

이 메모리가 결합 된 경우에서와 같이 메모리 액세스가 병목이 될 것이기 때문에, 우리는 훨씬 이전에 적은 코어의 성능 하락을 얻을 것입니다 : 작업이 순수하게 CPU 바인딩 때문에이 그래프는 매우 명확하고 간단합니다 무엇 "CPU bound"및 "I / O bound"라는 용어는 무엇을 의미합니까?

Sys의 중작 업 sendfile

가장 무거운 SYS 내가를 사용하는 것이었다 가지고 올 수있는 워크로드 sendfile파일 복사 커널 공간에서 작업을 수행하는 : 복사 온전한에서 파일을 안전하고 효율적인 방법

그래서이 커널 내부 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다른 프로세스의 syscall을 구분할 수 있는지 궁금해서 시도했습니다.

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>우분투에서 할 때 다음 과 같이 Bash 키워드를 사용합니다.

type time

어떤 출력 :

time is a shell keyword

따라서 출력 문자열에 대한 Bash 4.19 소스 코드에서 소스를 grep하십시오.

git grep '"user\b'

이를 통해 우리는 execute_cmd.c 함수 time_command를 사용합니다.

  • gettimeofday()그리고 getrusage()두 경우 사용할 수 있습니다
  • times() 그렇지 않으면

이것들은 모두 리눅스 시스템 호출POSIX 함수 입니다.

GNU Coreutils 소스 코드

우리가 다음과 같이 부르면 :

/usr/bin/time

그런 다음 GNU Coreutils 구현을 사용합니다.

이것은 조금 더 복잡하지만 관련 소스는 resuse.c 에있는 것 같습니다 .

  • POSIX가 아닌 BSD wait3호출
  • timesgettimeofday달리

14

Real은 프로세스의 총 처리 시간을 보여줍니다. User는 사용자 정의 명령어의 실행 시간을 표시하고 Sys는 시스템 호출을 실행하는 시간입니다!

실시간에는 대기 시간도 포함됩니다 (I / O 대기 시간 등).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.