]> Cypherpunks repositories - gostls13.git/commitdiff
internal/trace: skip clock snapshot checks on Windows in stress mode
authorMichael Anthony Knyszek <mknyszek@google.com>
Wed, 21 May 2025 17:50:15 +0000 (17:50 +0000)
committerMichael Knyszek <mknyszek@google.com>
Wed, 21 May 2025 19:03:26 +0000 (12:03 -0700)
Windows' monotonic and wall clock granularity is just too coarse to get
reasonable values out of stress mode, which is creating new trace
generations constantly.

Fixes #73813.

Change-Id: Id9cb2fed9775ce8d78a736d0164daa7bf45075e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/675096
Reviewed-by: Felix Geisendörfer <felix.geisendoerfer@datadoghq.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/internal/trace/reader_test.go
src/internal/trace/testtrace/validation.go
src/internal/trace/trace_test.go

index 222d2dfa820d06d9d698860e6b514e49bd713c11..691cda6688d577d6579ee2b598d31e9a73183210 100644 (file)
@@ -42,7 +42,9 @@ func TestReaderGolden(t *testing.T) {
                        if err != nil {
                                t.Fatalf("failed to parse test file at %s: %v", testPath, err)
                        }
-                       testReader(t, tr, ver, exp)
+                       v := testtrace.NewValidator()
+                       v.GoVersion = ver
+                       testReader(t, tr, v, exp)
                })
        }
 }
@@ -94,7 +96,7 @@ func FuzzReader(f *testing.F) {
        })
 }
 
-func testReader(t *testing.T, tr io.Reader, ver version.Version, exp *testtrace.Expectation) {
+func testReader(t *testing.T, tr io.Reader, v *testtrace.Validator, exp *testtrace.Expectation) {
        r, err := trace.NewReader(tr)
        if err != nil {
                if err := exp.Check(err); err != nil {
@@ -102,8 +104,6 @@ func testReader(t *testing.T, tr io.Reader, ver version.Version, exp *testtrace.
                }
                return
        }
-       v := testtrace.NewValidator()
-       v.GoVersion = ver
        for {
                ev, err := r.ReadEvent()
                if err == io.EOF {
index da0e871287c235c63ac75fc3a67b0ed867a461c7..2060d0d44c05786f2737c4833f139e86e17d4cf7 100644 (file)
@@ -23,6 +23,9 @@ type Validator struct {
        tasks     map[trace.TaskID]string
        lastSync  trace.Sync
        GoVersion version.Version
+
+       // Flags to modify validation behavior.
+       skipClockSnapshotChecks bool // Some platforms can't guarantee a monotonically increasing clock reading.
 }
 
 type schedContext struct {
@@ -53,6 +56,14 @@ func NewValidator() *Validator {
        }
 }
 
+// SkipClockSnapshotChecks causes the validator to skip checks on the clock snapshots.
+//
+// Some platforms like Windows, with a small enough trace period, are unable to produce
+// monotonically increasing timestamps due to very coarse clock granularity.
+func (v *Validator) SkipClockSnapshotChecks() {
+       v.skipClockSnapshotChecks = true
+}
+
 // Event validates ev as the next event in a stream of trace.Events.
 //
 // Returns an error if validation fails.
@@ -97,14 +108,16 @@ func (v *Validator) Event(ev trace.Event) error {
                        if s.ClockSnapshot.Trace == 0 {
                                e.Errorf("sync %d has zero trace time", s.N)
                        }
-                       if s.N >= 2 && !s.ClockSnapshot.Wall.After(v.lastSync.ClockSnapshot.Wall) {
-                               e.Errorf("sync %d has non-increasing wall time: %v vs %v", s.N, s.ClockSnapshot.Wall, v.lastSync.ClockSnapshot.Wall)
-                       }
-                       if s.N >= 2 && !(s.ClockSnapshot.Mono > v.lastSync.ClockSnapshot.Mono) {
-                               e.Errorf("sync %d has non-increasing mono time: %v vs %v", s.N, s.ClockSnapshot.Mono, v.lastSync.ClockSnapshot.Mono)
-                       }
-                       if s.N >= 2 && !(s.ClockSnapshot.Trace > v.lastSync.ClockSnapshot.Trace) {
-                               e.Errorf("sync %d has non-increasing trace time: %v vs %v", s.N, s.ClockSnapshot.Trace, v.lastSync.ClockSnapshot.Trace)
+                       if !v.skipClockSnapshotChecks {
+                               if s.N >= 2 && !s.ClockSnapshot.Wall.After(v.lastSync.ClockSnapshot.Wall) {
+                                       e.Errorf("sync %d has non-increasing wall time: %v vs %v", s.N, s.ClockSnapshot.Wall, v.lastSync.ClockSnapshot.Wall)
+                               }
+                               if s.N >= 2 && !(s.ClockSnapshot.Mono > v.lastSync.ClockSnapshot.Mono) {
+                                       e.Errorf("sync %d has non-increasing mono time: %v vs %v", s.N, s.ClockSnapshot.Mono, v.lastSync.ClockSnapshot.Mono)
+                               }
+                               if s.N >= 2 && !(s.ClockSnapshot.Trace > v.lastSync.ClockSnapshot.Trace) {
+                                       e.Errorf("sync %d has non-increasing trace time: %v vs %v", s.N, s.ClockSnapshot.Trace, v.lastSync.ClockSnapshot.Trace)
+                               }
                        }
                }
                v.lastSync = s
index 8c40e84a816d4f0a5d6d177683c5a850f25f9cc2..0aa297d7625814846586d0e47abb56b3aecdde98 100644 (file)
@@ -618,7 +618,16 @@ func testTraceProg(t *testing.T, progName string, extra func(t *testing.T, trace
                tb := traceBuf.Bytes()
 
                // Test the trace and the parser.
-               testReader(t, bytes.NewReader(tb), version.Current, testtrace.ExpectSuccess())
+               v := testtrace.NewValidator()
+               v.GoVersion = version.Current
+               if runtime.GOOS == "windows" && stress {
+                       // Under stress mode we're constantly advancing trace generations.
+                       // Windows' clock granularity is too coarse to guarantee monotonic
+                       // timestamps for monotonic and wall clock time in this case, so
+                       // skip the checks.
+                       v.SkipClockSnapshotChecks()
+               }
+               testReader(t, bytes.NewReader(tb), v, testtrace.ExpectSuccess())
 
                // Run some extra validation.
                if !t.Failed() && extra != nil {