}
}
+func TestPeriodicGC(t *testing.T) {
+ // Make sure we're not in the middle of a GC.
+ runtime.GC()
+
+ var ms1, ms2 runtime.MemStats
+ runtime.ReadMemStats(&ms1)
+
+ // Make periodic GC run continuously.
+ orig := *runtime.ForceGCPeriod
+ *runtime.ForceGCPeriod = 0
+
+ // Let some periodic GCs happen. In a heavily loaded system,
+ // it's possible these will be delayed, so this is designed to
+ // succeed quickly if things are working, but to give it some
+ // slack if things are slow.
+ var numGCs uint32
+ const want = 2
+ for i := 0; i < 20 && numGCs < want; i++ {
+ time.Sleep(5 * time.Millisecond)
+
+ // Test that periodic GC actually happened.
+ runtime.ReadMemStats(&ms2)
+ numGCs = ms2.NumGC - ms1.NumGC
+ }
+ *runtime.ForceGCPeriod = orig
+
+ if numGCs < want {
+ t.Fatalf("no periodic GC: got %v GCs, want >= 2", numGCs)
+ }
+}
+
func BenchmarkSetTypePtr(b *testing.B) {
benchSetType(b, new(*byte))
}
throw("all goroutines are asleep - deadlock!")
}
-func sysmon() {
- // If we go two minutes without a garbage collection, force one to run.
- forcegcperiod := int64(2 * 60 * 1e9)
+// forcegcperiod is the maximum time in nanoseconds between garbage
+// collections. If we go this long without a garbage collection, one
+// is forced to run.
+//
+// This is a variable for testing purposes. It normally doesn't change.
+var forcegcperiod int64 = 2 * 60 * 1e9
+func sysmon() {
// If a heap span goes unused for 5 minutes after a garbage collection,
// we hand it back to the operating system.
scavengelimit := int64(5 * 60 * 1e9)
lastscavenge := nanotime()
nscavenge := 0
- // Make wake-up period small enough for the sampling to be correct.
- maxsleep := forcegcperiod / 2
- if scavengelimit < forcegcperiod {
- maxsleep = scavengelimit / 2
- }
-
lasttrace := int64(0)
idle := 0 // how many cycles in succession we had not wokeup somebody
delay := uint32(0)
if atomicload(&sched.gcwaiting) != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs) {
atomicstore(&sched.sysmonwait, 1)
unlock(&sched.lock)
+ // Make wake-up period small enough
+ // for the sampling to be correct.
+ maxsleep := forcegcperiod / 2
+ if scavengelimit < forcegcperiod {
+ maxsleep = scavengelimit / 2
+ }
notetsleep(&sched.sysmonnote, maxsleep)
lock(&sched.lock)
atomicstore(&sched.sysmonwait, 0)