programing

System.nanoTime()은 전혀 쓸모가 없습니까?

shortcode 2022. 7. 19. 22:10
반응형

System.nanoTime()은 전혀 쓸모가 없습니까?

블로그 투고System.nanoTime(Java 의 주의」)에 기재되어 있듯이, x86 시스템에서는, Java 의 System.nanoTime() 는 CPU 고유의 카운터를 사용해 시간치를 반환합니다.다음으로 콜의 시간을 측정하기 위해 사용하는 예를 나타냅니다.

long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;

멀티코어 시스템에서는 time1을 측정한 후 스레드가 이전 CPU의 카운터보다 작은 다른 프로세서로 스케줄 되어 있을 수 있습니다.따라서 time1보다 작은 time2의 값을 얻을 수 있습니다.따라서 timeSpent에서 음의 값을 얻을 수 있습니다.

이 경우 System.nanotime은 현재로선 거의 쓸모가 없는 것 아닌가요?

시스템 시간을 변경하는 것은 나노타임에 영향을 주지 않는다는 것을 알고 있습니다.그것은 내가 위에서 설명한 문제가 아니다.문제는 CPU가 켜진 이후 각 CPU에 다른 카운터가 유지된다는 것입니다.이 카운터는 첫 번째 CPU보다 두 번째 CPU에서 더 낮을 수 있습니다. OS에서 time1을 얻은 후 두 번째 CPU로 스레드를 스케줄링할 수 있기 때문에 timeSpent 값이 잘못되어 음수일 수도 있습니다.

이 답변은 2011년 당시의 Sun JDK가 당시의 운영 체제에서 실제로 실행한 작업을 고려하여 작성되었습니다.그건 오래 전 일이야!Leventov의 답변은 보다 최신의 관점을 제공합니다.

그 게시물은 잘못되어 있습니다.nanoTime안전합니다.이 게시물에는 Sun의 실시간 동시 실행 남성인 David Holmes의 블로그 게시물에 링크된 코멘트가 있습니다.다음과 같이 되어 있습니다.

System.nanoTime()은 QueryPerformanceCounter/QueryPerformanceFrequency API [...]를 사용하여 구현됩니다.QPC에서 사용되는 기본 메커니즘은 하드웨어뿐만 아니라 OS 버전에도 적용됩니다.예를 들어 Windows XP Service Pack 2에서는 TSC가 SMP 시스템의 다른 프로세서에서 동기화되지 않는 문제 및 주파수가 변화할 수 있기 때문에 (따라서 경과시간에 대한 관계가) 전원 관리에 따라 프로세서의 타임스탬프 카운터(TSC)가 아닌 전원 관리 타이머(PMTimer)를 사용하도록 변경되었습니다.설정을 지정합니다.

Windows 에서는, 이것은 WinXP SP2까지는 문제가 있었지만, 현재는 문제가 아닙니다.

다른 플랫폼에 대해 설명하는 파트 II(또는 그 이상)는 찾을 수 없지만, 그 기사에는 Linux가 동일한 방법으로 동일한 문제를 해결하고 있다는 코멘트가 포함되어 있습니다.또, 다음과 같은 내용의 clock_gettime(CLOCK_REALTIME)에 대한 FAQ 링크도 포함되어 있습니다.

  1. clock_gettime(CLOCK_REALTIME)은 모든 프로세서/코어에서 일관성이 있습니까? (아치는 중요합니까? ppc, arm, x86, amd64, sparc 등)

그렇지 않으면 버그로 간주됩니다.

그러나 x86/x86_64에서는 동기화되지 않은 TSC 또는 가변 Freq TSC로 인해 시간 불일치가 발생할 수 있습니다. 2.4 커널은 실제로 이에 대한 보호 기능이 없었고 초기 2.6 커널도 여기서 그다지 잘 수행되지 않았습니다.2.6.18 이후로는 이것을 검출하기 위한 논리가 더 좋기 때문에 보통 안전한 클럭소스로 돌아갑니다

ppc는 항상 동기화된 타임베이스를 가지고 있기 때문에 문제가 되지 않습니다.

그래서 홈즈의 연결고리가 다음과 같은 의미로 해석될 수 있다면nanoTimeclock_gettime(CLOCK_REALTIME)x86 및 PowerPC에서는 커널 2.6.18부터 안전합니다(IBM과 Motorola는 실제로 마이크로프로세서를 설계하는 방법을 알고 있기 때문입니다).

유감스럽게도 SPARC나 Solaris에 대한 언급은 없습니다.물론 IBM JVM이 어떤 역할을 하는지 알 수 없습니다.그러나 최신 Windows 및 Linux의 Sun JVM은 이 점을 잘 알고 있습니다.

편집: 이 답변은 인용된 출처를 기반으로 합니다.하지만 나는 여전히 그것이 완전히 잘못되었을까 봐 걱정된다.좀 더 최신 정보를 제공하는 것이 매우 유용할 것입니다.Linux 의 클럭에 관한 4년간의 최신 기사에 대한 링크를 우연히 발견했습니다.

내가 좀 찾아봤더니, 만약 누군가가 현학적인 행동을 한다면, 그건 쓸모없는 것으로 여겨질지도 모른다는 것을 알게 되었다.특정 상황에서...요구가 얼마나 시간에 민감한지에 따라...

Java Sun 사이트에서 다음 견적을 확인하십시오.

실시간 클럭과 System.nanoTime()은 모두 같은 시스템콜을 기반으로 하기 때문에 같은 클럭을 기반으로 합니다.

Java RTS에서는 모든 시간 기반 API(타이머, 정기 스레드, 기한 모니터링 등)가 고해상도 타이머에 기반합니다.또한 실시간 우선 순위와 함께 실시간 제약에 대해 적절한 코드가 적시에 실행되도록 보장할 수 있습니다.반면 일반 Java SE API는 고해상도 시간을 처리할 수 있는 몇 가지 메서드만 제공하며 특정 시간에 실행된다는 보장은 없습니다.코드 내의 다양한 포인트 간에 System.nanoTime()을 사용하여 경과시간을 측정할 때는 항상 정확해야 합니다.

Java에는 nanoTime() 메서드에 대한 경고도 있습니다.

이 방법은 경과 시간을 측정하는 데만 사용할 수 있으며 시스템 또는 벽시계의 다른 개념과는 관련이 없습니다.반환되는 값은 일정하지만 임의의 시간(아마도 미래에는 음의 값이 될 수 있음) 이후 나노초를 나타냅니다.이 방법은 나노초의 정밀도를 제공하지만 반드시 나노초의 정밀도는 아닙니다.값이 얼마나 자주 변경되는지에 대해서는 보장되지 않습니다.약 292.3년(2나노초)보다63 긴 연속 콜의 차이는 수치 오버플로에 의해 경과시간을 정확하게 계산하지 않습니다.

nano Time()을 정확한 값으로 신뢰할 수 없다는 결론밖에 도출할 수 없는 것 같습니다.따라서 나노초 간격으로 시간을 측정할 필요가 없다면 반환된 값이 음수인 경우에도 이 방법으로 충분합니다.단, 보다 정밀도가 필요한 경우에는 JAVA RTS 사용을 권장하는 것으로 보입니다.

그래서 당신의 질문에 대답하자면 nano Time()은 쓸모없는 것이 아닙니다. 단지 모든 상황에서 사용하는 가장 신중한 방법은 아닙니다.

Java 7부터는 JDK 사양에 의해 안전성이 보증됩니다.의 Javadoc은 JVM 내에서 관찰된 모든 호출(즉, 모든 스레드)이 단조롭다는 것을 명확히 합니다System.nanoTime().

반환되는 값은 일정하지만 임의의 발신 시간(아마도 미래에는 음의 값이 될 수 있음) 이후 나노초를 나타냅니다.Java 가상 시스템의 인스턴스에서 이 메서드를 호출할 때 모두 동일한 원본이 사용됩니다. 다른 가상 시스템 인스턴스는 다른 원본이 사용될 수 있습니다.

JVM/JDK 구현은 기본 OS 유틸리티가 호출되었을 때 발생할 수 있는 불일치(예를 들어 Tom Anderson의 답변에 언급된 불일치)를 해결하는 역할을 합니다.

이 질문에 대한 다른 오래된 답변(2009-2012년 작성)의 대부분은 Java 5 또는 Java 6과 관련이 있을 수 있지만 Java의 최신 버전과는 관련이 없는 FUD를 나타냅니다.

단, JDK의 보증에도 불구하고nanoTime()의 안전성에 대해서는 OpenJDK에 몇 가지 버그가 있어 특정 플랫폼 또는 특정 상황에서 이 보증이 적용되지 않습니다(예: JDK-8040140, JDK-8184271).OpenJDK wrt에 열려 있는(기존의) 버그가 없다.nanoTime()현시점에서는 이러한 버그가 새롭게 발견되거나 OpenJDK의 새로운 릴리스에서 퇴보하는 것이 발견되어도 그 누구에게도 충격을 주지 않을 것입니다.

이 점을 염두에 두고, 가 타임 블록, 인터벌 대기, 타임 아웃 등에 사용하는 코드는, 슬로우 예외가 아니고, 음의 시차(타임 아웃)를 제로로 취급하는 것이 바람직합니다.이 프랙티스는 또한 모든 클래스의 모든 시간 대기 방법의 동작과 일치하기 때문에 바람직하다.java.util.concurrent.*예를 들어,Lock.tryLock(), , 등

그래도nanoTime()타임아웃, 인터벌웨이팅, 타임아웃 등을 실장하기 위해서는 계속 권장해야 합니다.currentTimeMillis()후자는 "시간 후진" 현상(예: 서버 시간 보정)의 대상이기 때문에, 즉 시간 간격을 측정하는 데 전혀 적합하지 않습니다.상세한 것에 대하여는, 회답을 참조해 주세요.

사용하는 대신nanoTime()코드 실행 시간을 직접 측정할 경우 JMH비동기 프로파일링 모드 등 특수한 벤치마크 프레임워크와 프로파일러를 사용하는 것이 좋습니다.

논쟁할 필요 없이 출처를 이용하세요.Linux용 SE 6에서는 다음과 같은 결론을 내립니다.

jlong os::javaTimeMillis() {
  timeval time;
  int status = gettimeofday(&time, NULL);
  assert(status != -1, "linux error");
  return jlong(time.tv_sec) * 1000  +  jlong(time.tv_usec / 1000);
}


jlong os::javaTimeNanos() {
  if (Linux::supports_monotonic_clock()) {
    struct timespec tp;
    int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
    assert(status == 0, "gettime error");
    jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
    return result;
  } else {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);
    return 1000 * usecs;
  }
}

Linux는 CPU 간의 불일치를 수정하지만 Windows는 수정하지 않습니다.System.nanoTime()은 1마이크로초 정도밖에 정확하지 않다고 가정해 주십시오.보다 긴 타이밍을 얻는 간단한 방법은 foo()를 1000회 이상 호출하여 시간을 1000으로 나누는 것입니다.

전혀 쓸모없지는 않다.타이밍 애호가들은 멀티코어 문제를 정확하게 지적하지만 실제 워드 어플리케이션에서는 현재 TimeMillis()보다 훨씬 나은 경우가 많습니다.

프레임 내의 그래픽 위치를 계산할 때 nanoTime()은 프로그램에서 MUCH의 부드러운 움직임을 가져옵니다.

멀티코어 머신에서만 테스트합니다.

System.nanoTime()을 사용한 결과, 의 경과시간이 보고되었습니다.명확하게 하기 위해, 문제의 코드는 다음과 같습니다.

    long startNanos = System.nanoTime();

    Object returnValue = joinPoint.proceed();

    long elapsedNanos = System.nanoTime() - startNanos;

변수 'elapsedNanos'는 음수 값을 가집니다.(중간 통화도 293년 미만이 걸렸을 것으로 확신합니다.이것은 롱에 저장되어 있는 나노의 오버플로 포인트입니다).

이 문제는 AIX를 실행하는 IBM P690(멀티 코어) 하드웨어에서 IBM v1.5 JRE 64비트를 사용하여 발생했습니다.이 에러는 한 번밖에 본 적이 없기 때문에 매우 드문 것 같습니다.원인을 알 수 없습니다.하드웨어 고유의 문제인지, JVM의 결함인지 알 수 없습니다.nano Time()의 정확성에 대한 일반적인 의미도 모릅니다.

첫 번째 질문에 답하자면, nano Time이 쓸모없다고는 생각하지 않습니다.밀리초 미만의 타이밍을 제공하지만 이론적인 것뿐만 아니라 실제로 정확하지 않을 위험이 있습니다.이것을 고려해야 합니다.

Windows XP 및 JRE 1.5.0_06을 실행하고 있는 Core 2 Duo에서는 이 문제가 발생하지 않는 것 같습니다.

스레드가 3개인 테스트에서는 System.nanoTime()이 뒤로 가지 않습니다.프로세서는 둘 다 비지 상태이며 스레드가 sleep 상태가 되어 움직이는 스레드를 자극하는 경우가 있습니다.

[EDIT] 물리적으로 다른 프로세서에서만 발생합니다.즉, 카운터가 같은 다이 상의 여러 코어에 대해 동기화됩니다.

아니, 그건...CPU에 따라 처리 방법이 달라지는 이유에 대해서는 High Precision Event Timer(고정밀도는 CPU에 따라 다릅니다.

기본적으로 Java의 소스를 읽고 사용 중인 버전이 이 함수에 대해 무엇을 하는지, 그리고 CPU에 대해 작동하는지 확인합니다.

IBM은 성능 벤치마킹(2008년 게시물, 업데이트됨)에도 사용할 을 권장합니다.

나는 피터 로레이가 좋은 답을 제공하고 있는 것과 본질적으로 같은 토론이 무엇인지를 연결시키고 있다.System.nanoTime()을 사용하여 음의 경과시간을 얻을 수 있는 이유는 무엇입니까?

Java System.nanoTime()에서는 음의 시간이 반환될 수 있다고 많은 사람들이 언급했습니다.다른 사람이 한 말을 반복해서 죄송합니다.

  1. nano Time()은 클럭이 아니라 CPU 사이클카운터입니다.
  2. 반환값은 주파수로 나누어 시간처럼 보입니다.
  3. CPU 주파수가 변동할 수 있습니다.
  4. 스레드가 다른 CPU로 스케줄 되어 있는 경우, nano Time()을 취득할 가능성이 있습니다.그 결과, 마이너스의 차이가 발생합니다.일리가 있네요.CPU 전체의 카운터는 동기화되지 않습니다.
  5. In many cases, you could get quite misleading results but you wouldn't be able to tell because delta is not negative. Think about it.
  6. (unconfirmed) I think you may get a negative result even on the same CPU if instructions are reordered. To prevent that, you'd have to invoke a memory barrier serializing your instructions.

It'd be cool if System.nanoTime() returned coreID where it executed.

Java is crossplatform, and nanoTime is platform-dependent. If you use Java - when don't use nanoTime. I found real bugs across different jvm implementations with this function.

The Java 5 documentation also recommends using this method for the same purpose.

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time.

Java 5 API Doc

Also, System.currentTimeMillies() changes when you change your systems clock, while System.nanoTime() doesn't, so the latter is safer to measure durations.

nanoTime is extremely insecure for timing. I tried it out on my basic primality testing algorithms and it gave answers which were literally one second apart for the same input. Don't use that ridiculous method. I need something that is more accurate and precise than get time millis, but not as bad as nanoTime.

ReferenceURL : https://stackoverflow.com/questions/510462/is-system-nanotime-completely-useless

반응형