programing

하루 중에 얻는 시간과 동등한 속도로 더 빠른 속도

codeshow 2023. 9. 24. 13:13
반응형

하루 중에 얻는 시간과 동등한 속도로 더 빠른 속도

각 메시지에 시간 필드가 있는 초당 100개의 메시지를 전송해야 하는 매우 지연 시간에 민감한 애플리케이션을 구축하기 위해 우리는 하루 중 수신 시간을 최적화하는 것을 고려하고 싶었습니다.은 였습니다.rdtsc기반 최적화 있어요?무슨 생각 있어요?다른 포인터가 있습니까? 반환되는 시간 값의 필요한 정확도는 밀리초 단위이지만, 값이 수신기와 1-2밀리초 동안 동기화되지 않는 경우가 있다면 큰 문제가 되지 않습니다.보다 더 62가 걸립니다.

포식스 시계

POSIX 클럭 소스에 대한 벤치마크를 작성했습니다.

  • 시간(s) => 3주기
  • ftime(ms) => 54주기
  • get time of day (us) => 42 cycle
  • clock_gettime(ns) => 9주기(CLOCK_MONOTONIC_COARS)
  • clock_getTime(ns) => 9주기 (CLOCK_REALTIME_COARS)
  • clock_gettime(ns) => 42주기 (CLOCK_MONOTONIC)
  • clock_gettime(ns) => 42주기 (CLOCK_REALTIME)
  • clock_gettime(ns) => 173주기 (CLOCK_MONOTONIC_RAW)
  • clock_gettime(ns) => 179주기(CLOCK_BOOTTIME)
  • clock_gettime(ns) => 349 사이클 (CLOCK_THREAD_CPUTIME_ID)
  • clock_gettime(ns) => 370 사이클 (CLOCK_PROCESS_CPUTIME_ID)
  • rdtsc (cycles) => 24주기

이 숫자는 Linux 4.0의 Intel Core i7-4771 CPU @ 3.50GHz에서 가져온 것입니다.이러한 측정은 TSC 레지스터를 사용하여 각 클럭 방법을 수천 번 실행하고 최소 비용 값을 취했습니다.

하드웨어 및 커널 버전에 따라 구현 방법이 다르기 때문에 실행하려는 시스템에서 테스트를 수행해야 합니다.코드는 여기서 찾을 수 있습니다.사이클 카운팅은 TSC 레지스터에 의존하며, 이 레지스터는 동일한 레포(tsc.h)에 있습니다.

TSC

TSC(프로세서 타임스탬프 카운터)에 액세스하는 것이 가장 정확하고 저렴한 시간 측정 방법입니다.일반적으로, 이것은 커널 자체가 사용하는 것입니다.또한 TSC가 코어 간에 동기화되고 주파수 확장에 영향을 받지 않기 때문에 최신 인텔 칩에서는 매우 간단합니다.따라서 단순한 글로벌 시간 소스를 제공합니다.여기에 어셈블리 코드에 대한 설명과 함께 사용하는 예를 볼 수 있습니다.

휴대성을 제외한 주요 문제는 사이클에서 나노초로 전환할 수 있는 좋은 방법이 없는 것 같다는 것입니다.제가 알기로는 인텔 문서에는 TSC가 고정된 주파수로 실행되지만 이 주파수는 프로세서에 명시된 주파수와 다를 수 있다고 나와 있습니다.인텔은 TSC 주파수를 파악할 수 있는 확실한 방법을 제공하지 않는 것 같습니다.Linux 커널은 두 하드웨어 타이머 사이에 얼마나 많은 TSC 사이클이 발생하는지 테스트함으로써 이 문제를 해결하는 것으로 보입니다(여기 참조).

Memcached

Memcached bothers to do the cache method. It may simply be to make sure the performance is more predictable across platforms, or scale better with multiple cores. It may also no be a worthwhile optimization.

실제로 벤치마크를 해보신 적이 있습니까?gettimeofday너무 느리다고요?

At the rate of 100 messages a second, you have 10ms of CPU time per message. If you have multiple cores, assuming it can be fully parallelized, you can easily increase that by 4-6x - that's 40-60ms per message! The cost of gettimeofday is unlikely to be anywhere near 10ms - I'd suspect it to be more like 1-10 microseconds (on my system, microbenchmarking it gives about 1 microsecond per call - try it for yourself). Your optimization efforts would be better spent elsewhere.

TSC를 사용하는 것이 합리적인 생각이지만, 현대 Linux에는 사용자 공간 TSC 기반 get time of day가 이미 있습니다. 가능한 경우 vdso는 오프셋(공유 커널-사용자 메모리 세그먼트에서 읽기)을 적용하는 get time of day의 구현을 시작합니다.rdtsc의 값, 따라서 커널을 입력하지 않고 하루 중 시간을 계산합니다.그러나 일부 CPU 모델에는 서로 다른 코어 또는 패키지 간에 동기화된 TSC가 없으므로 이 기능이 비활성화될 수 있습니다.고성능 타이밍을 원하는 경우 먼저 동기화된 TSC가 있는 CPU 모델을 찾는 것이 좋습니다.

That said, if you're willing to sacrifice a significant amount of resolution (your timing will only be accurate to the last tick, meaning it could be off by tens of milliseconds), you could use CLOCK_MONOTONIC_COARSE or CLOCK_REALTIME_COARSE with clock_gettime. This is also implemented with the vdso as well, and guaranteed not to call into the kernel (for recent kernels and glibc).

bdonian 말대로 초당 수백개의 메시지만 보낸다면,gettimeofday충분히 빠를 겁니다

However, if you were sending millions of messages per second, it might be different (but you should still measure that it is a bottleneck). In that case, you might want to consider something like this:

  • 원하는 정확도에 현재 타임스탬프를 제공하는 전역 변수가 있습니다.
  • 타임스탬프를 업데이트하는 것 외에는 아무것도 수행하지 않는 전용 백그라운드 스레드가 있습니다(타임스탬프가 T 단위의 시간마다 업데이트되어야 하는 경우, 스레드가 T의 일부를 슬립시킨 다음 타임스탬프를 업데이트합니다. 필요한 경우 실시간 기능을 사용합니다.)
  • 다른 모든 스레드(또는 스레드를 사용하지 않는 경우 주 프로세스)는 전역 변수만 읽습니다.

이 C 보다 클이 값을 수 .sig_atomic_t 잠금장치를 이용해서 처리할 수도 있지만, 잠금장치는 무겁습니다.대신에, 당신은 a를 사용할 수 있습니다.volatile sig_atomic_t: 한 다음index.typed variable:다. 백그라운드 스레드는 배열의 다음 요소를 업데이트한 다음 인덱스를 업데이트합니다.다른 스레드는 인덱스를 읽은 다음 배열을 읽습니다. 아주 조금 오래된 타임스탬프를 얻을 수 있지만(다음 번에는 정확한 타임스탬프를 얻을 수 있습니다), 타임스탬프가 업데이트되는 동시에 타임스탬프를 읽는 문제에 부딪히지 않고 이전 값의 바이트와 새 값의 일부를 얻을 수 있습니다.

하지만 이 모든 것은 초당 수백 개의 메시지를 보내기에는 너무 과도한 것입니다.

아래는 벤치마크입니다.30ns 정도 보입니다. rashad에서 시간()을 인쇄합니다. C++에서 현재 시간과 날짜를 가져오는 방법은 무엇입니까?

#include <string>
#include <iostream>
#include <sys/time.h>
using namespace std;

void printTime(time_t now)
{
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
    cout << buf << endl;
}

int main()
{
   timeval tv;
   time_t tm;

   gettimeofday(&tv,NULL);
   printTime((time_t)tv.tv_sec);
   for(int i=0; i<100000000; i++)
        gettimeofday(&tv,NULL);
   gettimeofday(&tv,NULL);
   printTime((time_t)tv.tv_sec);

   printTime(time(NULL));
   for(int i=0; i<100000000; i++)
        tm=time(NULL);
   printTime(time(NULL));

   return 0;
}

100,000,000 통화 또는 30ns에 대해 3초;

2014-03-20.09:23:35
2014-03-20.09:23:38
2014-03-20.09:23:38
2014-03-20.09:23:41

밀리초의 정밀도가 필요하십니까? 않다면, 당신은면을 할 수 .time()유닉스 타임스탬프를 처리합니다.

언급URL : https://stackoverflow.com/questions/6498972/faster-equivalent-of-gettimeofday

반응형