Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(661)

Side by Side Diff: src/base/platform/time.cc

Issue 1977983003: [base] Implement CPU time on Windows. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/base/platform/time.h ('k') | src/base/win32-headers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/base/platform/time.h" 5 #include "src/base/platform/time.h"
6 6
7 #if V8_OS_POSIX 7 #if V8_OS_POSIX
8 #include <fcntl.h> // for O_RDONLY 8 #include <fcntl.h> // for O_RDONLY
9 #include <sys/time.h> 9 #include <sys/time.h>
10 #include <unistd.h> 10 #include <unistd.h>
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 return 0; 60 return 0;
61 } 61 }
62 v8::base::internal::CheckedNumeric<int64_t> result(ts.tv_sec); 62 v8::base::internal::CheckedNumeric<int64_t> result(ts.tv_sec);
63 result *= v8::base::Time::kMicrosecondsPerSecond; 63 result *= v8::base::Time::kMicrosecondsPerSecond;
64 result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond); 64 result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
65 return result.ValueOrDie(); 65 return result.ValueOrDie();
66 #else // Monotonic clock not supported. 66 #else // Monotonic clock not supported.
67 return 0; 67 return 0;
68 #endif 68 #endif
69 } 69 }
70 #elif V8_OS_WIN
71 bool IsBuggyAthlon(const v8::base::CPU& cpu) {
72 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable.
73 return strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15;
noordhuis 2016/05/15 09:06:46 I commented on this in the other CL but I think it
lpy 2016/05/24 22:21:46 I will leave this as it is for now, since we are u
74 }
75
76 // Returns the current value of the performance counter.
77 uint64_t QPCNowRaw() {
fmeawad 2016/05/14 01:04:07 If I am reading the correctly, we do not use QPC f
lpy 2016/05/24 22:21:46 It depends. V8 may fall back to low resolution tim
78 LARGE_INTEGER perf_counter_now = {};
79 // According to the MSDN documentation for QueryPerformanceCounter(), this
80 // will never fail on systems that run XP or later.
81 // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
82 ::QueryPerformanceCounter(&perf_counter_now);
83 return perf_counter_now.QuadPart;
84 }
70 #endif // V8_OS_MACOSX 85 #endif // V8_OS_MACOSX
71 86
72 87
73 } // namespace 88 } // namespace
74 89
75 namespace v8 { 90 namespace v8 {
76 namespace base { 91 namespace base {
77 92
78 TimeDelta TimeDelta::FromDays(int days) { 93 TimeDelta TimeDelta::FromDays(int days) {
79 return TimeDelta(days * Time::kMicrosecondsPerDay); 94 return TimeDelta(days * Time::kMicrosecondsPerDay);
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 #endif 629 #endif
615 } 630 }
616 631
617 632
618 ThreadTicks ThreadTicks::Now() { 633 ThreadTicks ThreadTicks::Now() {
619 #if V8_OS_MACOSX 634 #if V8_OS_MACOSX
620 return ThreadTicks(ComputeThreadTicks()); 635 return ThreadTicks(ComputeThreadTicks());
621 #elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ 636 #elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
622 defined(V8_OS_ANDROID) 637 defined(V8_OS_ANDROID)
623 return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID)); 638 return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
639 #elif V8_OS_WIN
640 return ThreadTicks::GetForThread(::GetCurrentThread());
624 #else 641 #else
625 UNREACHABLE(); 642 UNREACHABLE();
626 return ThreadTicks(); 643 return ThreadTicks();
627 #endif 644 #endif
628 } 645 }
629 646
647
648 #if V8_OS_WIN
649 ThreadTicks ThreadTicks::GetForThread(const HANDLE& thread_handle) {
650 DCHECK(IsSupported());
651
652 // Get the number of TSC ticks used by the current thread.
653 ULONG64 thread_cycle_time = 0;
654 ::QueryThreadCycleTime(thread_handle, &thread_cycle_time);
655
656 // Get the frequency of the TSC.
657 double tsc_ticks_per_second = TSCTicksPerSecond();
658 if (tsc_ticks_per_second == 0)
659 return ThreadTicks();
660
661 // Return the CPU time of the current thread.
662 double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
663 return ThreadTicks(
664 static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond));
665 }
666
667 // static
668 bool ThreadTicks::IsSupportedWin() {
669 static bool is_supported = base::CPU().has_non_stop_time_stamp_counter() &&
670 !IsBuggyAthlon(base::CPU());
671 return is_supported;
672 }
673
674 // static
675 void ThreadTicks::WaitUntilInitializedWin() {
676 while (TSCTicksPerSecond() == 0)
677 ::Sleep(10);
678 }
679
680 double ThreadTicks::TSCTicksPerSecond() {
681 DCHECK(IsSupported());
682
683 // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
684 // frequency, because there is no guarantee that the TSC frequency is equal to
685 // the performance counter frequency.
686
687 // The TSC frequency is cached in a static variable because it takes some time
688 // to compute it.
689 static double tsc_ticks_per_second = 0;
690 if (tsc_ticks_per_second != 0)
691 return tsc_ticks_per_second;
692
693 // Increase the thread priority to reduces the chances of having a context
694 // switch during a reading of the TSC and the performance counter.
695 int previous_priority = ::GetThreadPriority(::GetCurrentThread());
696 ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
697
698 // The first time that this function is called, make an initial reading of the
699 // TSC and the performance counter.
700 static const uint64_t tsc_initial = __rdtsc();
701 static const uint64_t perf_counter_initial = QPCNowRaw();
702
703 // Make a another reading of the TSC and the performance counter every time
704 // that this function is called.
705 uint64_t tsc_now = __rdtsc();
706 uint64_t perf_counter_now = QPCNowRaw();
707
708 // Reset the thread priority.
709 ::SetThreadPriority(::GetCurrentThread(), previous_priority);
710
711 // Make sure that at least 50 ms elapsed between the 2 readings. The first
712 // time that this function is called, we don't expect this to be the case.
713 // Note: The longer the elapsed time between the 2 readings is, the more
714 // accurate the computed TSC frequency will be. The 50 ms value was
715 // chosen because local benchmarks show that it allows us to get a
716 // stddev of less than 1 tick/us between multiple runs.
717 // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
718 // this will never fail on systems that run XP or later.
719 // https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
720 LARGE_INTEGER perf_counter_frequency = {};
721 ::QueryPerformanceFrequency(&perf_counter_frequency);
722 DCHECK_GE(perf_counter_now, perf_counter_initial);
723 uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
724 double elapsed_time_seconds =
725 perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
726
727 const double kMinimumEvaluationPeriodSeconds = 0.05;
728 if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
729 return 0;
730
731 // Compute the frequency of the TSC.
732 DCHECK_GE(tsc_now, tsc_initial);
733 uint64_t tsc_ticks = tsc_now - tsc_initial;
734 tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
735
736 return tsc_ticks_per_second;
737 }
738 #endif // V8_OS_WIN
739
630 } // namespace base 740 } // namespace base
631 } // namespace v8 741 } // namespace v8
OLDNEW
« no previous file with comments | « src/base/platform/time.h ('k') | src/base/win32-headers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698