$ time foo real 0m0.003s user 0m0.000s sys 0m0.004s $
시간 출력에서 '실제', '사용자' 및 '시스템'은 무엇을 의미합니까?
내 앱을 벤치마킹할 때 어떤 것이 의미가 있습니까?
질문자 :Iraimbilanja
$ time foo real 0m0.003s user 0m0.000s sys 0m0.004s $
시간 출력에서 '실제', '사용자' 및 '시스템'은 무엇을 의미합니까?
내 앱을 벤치마킹할 때 어떤 것이 의미가 있습니까?
실제, 사용자 및 시스템 프로세스 시간 통계
이 중 하나는 다른 것과 같지 않습니다. 실제는 실제 경과 시간을 나타냅니다. User 및 Sys는 해당 프로세스에서만 사용하는 CPU 시간을 나타냅니다.
실제 는 벽시계 시간입니다. 통화 시작부터 종료까지의 시간입니다. 이것은 다른 프로세스에서 사용하는 시간 조각과 프로세스가 차단된 시간을 포함하여 모두 경과된 시간입니다(예: I/O가 완료되기를 기다리는 경우).
사용자 는 프로세스 내 에서 사용자 모드 코드(커널 외부)에서 소비한 CPU 시간입니다. 이것은 프로세스 실행에 사용된 실제 CPU 시간일 뿐입니다. 다른 프로세스와 프로세스가 차단된 시간은 이 수치에 포함되지 않습니다.
Sys 는 프로세스 내에서 커널에서 소비한 CPU 시간입니다. 이것은 여전히 사용자 공간에서 실행되는 라이브러리 코드와 달리 커널 내 에서 시스템 호출에 소비된 CPU 시간을 실행한다는 것을 의미합니다. 'user'와 마찬가지로 프로세스에서 사용하는 CPU 시간일 뿐입니다. 커널 모드('감독자' 모드라고도 함) 및 시스템 호출 메커니즘에 대한 간략한 설명은 아래를 참조하십시오.
User+Sys
는 프로세스가 사용한 실제 CPU 시간을 알려줍니다. 이것은 모든 CPU에 걸쳐 있으므로 프로세스에 여러 스레드가 있고 이 프로세스가 둘 이상의 프로세서가 있는 컴퓨터에서 실행 중인 경우 잠재적으로 Real
보고한 벽시계 시간(일반적으로 발생)을 초과할 수 있습니다. 참고 출력에이 수치는 포함하는 것이 User
및 Sys
에 의해 예를 들면 모든 자식 프로세스 (및 그들의 후손)의 시간뿐만 아니라 그들이 수집 한 수, wait(2)
또는 waitpid(2)
기본 시스템 호출이를 반환하지만, 프로세스 및 해당 하위에 대한 통계를 별도로 제공합니다.
시간별로 보고되는 통계의 기원 time (1)
time
로 보고되는 통계는 다양한 시스템 호출에서 수집됩니다. 'User' 및 'Sys'는 특정 시스템에 따라 wait (2)
( POSIX ) 또는 times (2)
( POSIX )에서 나옵니다. gettimeofday (2)
호출에서 수집된 시작 및 종료 시간에서 계산됩니다. 시스템 버전에 따라 컨텍스트 스위치 수와 같은 다양한 기타 통계도 time
로 수집될 수 있습니다.
다중 프로세서 시스템에서 다중 스레드 프로세스 또는 자식 분기 프로세스의 경과 시간은 총 CPU 시간보다 작을 수 있습니다. 다른 스레드나 프로세스가 병렬로 실행될 수 있기 때문입니다. 또한 보고된 시간 통계는 서로 다른 출처에서 왔으므로 매우 짧은 실행 작업에 대해 기록된 시간은 원본 포스터에서 볼 수 있는 것처럼 반올림 오류가 발생할 수 있습니다.
커널 대 사용자 모드에 대한 간략한 입문서
Unix 또는 보호된 메모리 운영 체제에서 '커널' 또는 '수퍼바이저' 모드는 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'에서 시간을 갖게 됩니다.
허용된 답변 을 확장 real
≠ user
+ sys
또 다른 이유를 제공하고 싶었습니다.
real
은 실제 경과 시간을 나타내고 user
및 sys
값은 CPU 실행 시간을 나타냅니다. 결과적으로 멀티코어 시스템에서 user
및/또는 sys
시간(및 그 합)은 실제로 실제 시간을 초과할 수 있습니다. 예를 들어, 클래스에 대해 실행 중인 Java 앱에서 다음 값 세트를 얻습니다.
real 1m47.363s user 2m41.318s sys 0m4.013s
• real : 마치 사람이 스톱워치로 측정한 것처럼 처음부터 끝까지 프로세스를 실행하는 데 소요된 실제 시간
• user : 계산하는 동안 모든 CPU가 소비한 누적 시간
• sys : 메모리 할당과 같은 시스템 관련 작업 동안 모든 CPU가 소비한 누적 시간.
여러 프로세서가 병렬로 작동할 수 있으므로 때때로 user + sys가 실제보다 클 수 있습니다.
실행 가능한 최소 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)에서 테스트되었습니다.
sleep
호출
sleep
syscall 에 의해 수행되는 비바쁨 절전 real
user
또는 sys
에는 계산되지 않습니다.
예를 들어 1초 동안 잠자는 프로그램은 다음과 같습니다.
#define _XOPEN_SOURCE 700 #include <stdlib.h> #include <unistd.h> int main(void) { sleep(1); return EXIT_SUCCESS; }
다음과 같이 출력합니다.
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; }
그리고 약 1초 동안 기다리면 다음과 같은 sleep 예제와 같이 출력됩니다.
real 0m1.003s user 0m0.001s sys 0m0.003s
이러한 이유로 time
은 CPU와 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; }
그런 다음 8개의 하이퍼스레드 CPU에서 고정 10^10 반복에 대한 스레드 수의 함수로 wall, user 및 sys를 플로팅합니다.
플롯 데이터 .
그래프에서 다음을 알 수 있습니다.
CPU 집약적인 단일 코어 애플리케이션의 경우 벽과 사용자는 거의 동일합니다.
2코어의 경우 사용자는 벽의 약 2배이며, 이는 사용자 시간이 모든 스레드에서 계산된다는 것을 의미합니다.
사용자는 기본적으로 두 배로 늘었고 벽은 그대로 유지되었습니다.
이것은 내 컴퓨터의 하이퍼 스레드 수와 일치하는 최대 8 스레드까지 계속됩니다.
8 이후에는 주어진 시간에 더 많은 작업을 수행할 추가 CPU가 없기 때문에 벽도 증가하기 시작합니다!
비율은 이 시점에서 정체됩니다.
이 메모리가 결합 된 경우에서와 같이 메모리 액세스가 병목이 될 것이기 때문에, 우리는 훨씬 이전에 적은 코어의 성능 하락을 얻을 것입니다 : 작업이 순수하게 CPU 바인딩 때문에이 그래프는 매우 명확하고 간단합니다 무엇 "CPU 바운드" 및 "I/O 바운드"라는 용어는 무엇을 의미합니까?
wall < user 를 빠르게 확인하는 것은 프로그램이 멀티스레드인지 판별하는 간단한 방법이며, 그 비율이 코어 수에 가까울수록 병렬화가 더 효과적입니다. 예:
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; }
기본적으로 예상대로 대부분 시스템 시간을 제공합니다.
real 0m2.175s user 0m0.001s sys 0m1.476s
나는 또한 time
이 다른 프로세스의 시스템 호출을 구별하는지 알고 싶었기 때문에 다음을 시도했습니다.
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
시스템 시간은 단일 프로세스와 거의 동일하지만 프로세스가 디스크 읽기 액세스를 놓고 경쟁하기 때문에 벽 시간이 더 큽니다.
따라서 실제로 어떤 프로세스가 주어진 커널 작업을 시작했는지 설명하는 것 같습니다.
배시 소스 코드
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()
모두 Linux 시스템 호출 과 POSIX 함수 입니다.
GNU Coreutils 소스 코드
우리가 그것을 다음과 같이 부르면 :
/usr/bin/time
그런 다음 GNU Coreutils 구현을 사용합니다.
이것은 조금 더 복잡하지만 관련 소스는 resuse.c 에 있는 것 같으며 다음과 같습니다.
사용 가능한 경우 비 POSIX BSD wait3
times
및 gettimeofday
그렇지 않으면
1 : https://i.stack.imgur.com/qAfEe.png** 최소 실행 가능한 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
에만 포함됩니다.
예를 들어 1초 동안 잠자는 프로그램은 다음과 같습니다.
#define _XOPEN_SOURCE 700 #include <stdlib.h> #include <unistd.h> int main(void) { sleep(1); return EXIT_SUCCESS; }
다음과 같이 출력합니다.
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; }
그리고 약 1초 동안 기다리면 다음과 같은 sleep 예제와 같이 출력됩니다.
real 0m1.003s user 0m0.001s sys 0m0.003s
이러한 이유로 time
은 CPU와 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; }
그런 다음 8개의 하이퍼스레드 CPU에서 고정 10^10 반복에 대한 스레드 수의 함수로 wall, user 및 sys를 플로팅합니다.
플롯 데이터 .
그래프에서 다음을 알 수 있습니다.
CPU 집약적인 단일 코어 애플리케이션의 경우 벽과 사용자는 거의 동일합니다.
2코어의 경우 사용자는 벽의 약 2배이며, 이는 사용자 시간이 모든 스레드에서 계산된다는 것을 의미합니다.
사용자는 기본적으로 두 배로 늘었고 벽은 그대로 유지되었습니다.
이것은 내 컴퓨터의 하이퍼 스레드 수와 일치하는 최대 8 스레드까지 계속됩니다.
8 이후에는 주어진 시간에 더 많은 작업을 수행할 추가 CPU가 없기 때문에 벽도 증가하기 시작합니다!
비율은 이 시점에서 정체됩니다.
이 메모리가 결합 된 경우에서와 같이 메모리 액세스가 병목이 될 것이기 때문에, 우리는 훨씬 이전에 적은 코어의 성능 하락을 얻을 것입니다 : 작업이 순수하게 CPU 바인딩 때문에이 그래프는 매우 명확하고 간단합니다 무엇 "CPU 바운드" 및 "I/O 바운드"라는 용어는 무엇을 의미합니까?
wall < user 를 빠르게 확인하는 것은 프로그램이 멀티스레드인지 판별하는 간단한 방법이며, 그 비율이 코어 수에 가까울수록 병렬화가 더 효과적입니다. 예:
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; }
기본적으로 예상대로 대부분 시스템 시간을 제공합니다.
real 0m2.175s user 0m0.001s sys 0m1.476s
나는 또한 time
이 다른 프로세스의 시스템 호출을 구별하는지 알고 싶었기 때문에 다음을 시도했습니다.
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
시스템 시간은 단일 프로세스와 거의 동일하지만 프로세스가 디스크 읽기 액세스를 놓고 경쟁하기 때문에 벽 시간이 더 큽니다.
따라서 실제로 어떤 프로세스가 주어진 커널 작업을 시작했는지 설명하는 것 같습니다.
배시 소스 코드
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()
모두 Linux 시스템 호출 과 POSIX 함수 입니다.
GNU Coreutils 소스 코드
우리가 그것을 다음과 같이 부르면 :
/usr/bin/time
그런 다음 GNU Coreutils 구현을 사용합니다.
이것은 조금 더 복잡하지만 관련 소스는 resuse.c 에 있는 것 같으며 다음과 같습니다.
wait3
times
및 gettimeofday
그렇지 않으면Real은 프로세스의 총 소요 시간을 보여줍니다. 사용자는 사용자 정의 명령의 실행 시간을 표시하고 Sys는 시스템 호출을 실행하는 시간입니다!
실시간에는 대기 시간(I/O 등의 대기 시간)도 포함됩니다.
실시간이 user + sys보다 훨씬 클 때 다른 시나리오를 언급하고 싶습니다. 오랜만에 응답하는 간단한 서버를 만들었습니다.
real 4.784 user 0.01s sys 0.01s
문제는 이 시나리오에서 프로세스가 사용자 사이트나 시스템에 없는 응답을 기다립니다.
find
명령을 실행할 때도 비슷한 일이 발생합니다. 이 경우 대부분의 시간은 SSD에 요청하고 응답을 받는 데 소비됩니다.
아주 간단한 용어로 저는 다음과 같이 생각하고 싶습니다.
real
은 명령을 실행하는 데 걸린 실제 시간입니다(스톱워치로 시간을 재는 것처럼).
user
와 sys
CPU
가 명령을 실행하기 위해 수행해야 하는 '작업'입니다. 이 '작업'은 시간 단위로 표현됩니다.
일반적으로 말하면:
user
는 명령 코드를 실행하기 위해 CPU
가 실행한 작업의 양입니다.sys
는 CPU
가 '시스템 오버헤드' 유형 작업(예: 메모리 할당, 파일 I/O 등)을 처리하기 위해 수행해야 했던 작업량입니다.이 마지막 두 번은 완료된 '작업'을 계산하기 때문에 스레드가 대기하는 데 소비한 시간(예: 다른 프로세스 또는 디스크 I/O가 완료되기를 기다리는 시간)은 포함되지 않습니다.
real
은 '작업'이 아닌 실제 런타임의 측정값이므로 대기하는 데 소요된 시간 이 포함됩니다.
적어도 내 AMD Ryzen CPU에서 user
-O3
컴파일된 단일 스레드 프로그램)에서 real
보다 크다는 점을 언급해야 합니다.
예를 들어
real 0m5.815s user 0m8.213s sys 0m0.473s
출처 : http:www.stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1
Git으로 특정 태그 다운로드 (0) | 2021.12.06 |
---|---|
싱글톤 패턴의 단점은 무엇입니까? [닫은] (0) | 2021.12.06 |
forEach 루프와 함께 async/await 사용 (0) | 2021.12.06 |
목록의 요소 수를 얻으려면 어떻게 해야 합니까? (0) | 2021.12.06 |
템플릿이 헤더 파일에서만 구현될 수 있는 이유는 무엇입니까? (0) | 2021.12.06 |