@@ -1018,7 +1018,7 @@ func TestRuntimeLockMetricsAndProfile(t *testing.T) {
1018
1018
return metricGrowth , profileGrowth , p
1019
1019
}
1020
1020
1021
- testcase := func (strictTiming bool , stk []string , workers int , fn func () bool ) func (t * testing.T ) (metricGrowth , profileGrowth float64 , n , value int64 ) {
1021
+ testcase := func (strictTiming bool , acceptStacks [] []string , workers int , fn func () bool ) func (t * testing.T ) (metricGrowth , profileGrowth float64 , n , value int64 ) {
1022
1022
return func (t * testing.T ) (metricGrowth , profileGrowth float64 , n , value int64 ) {
1023
1023
metricGrowth , profileGrowth , p := measureDelta (t , func () {
1024
1024
var started , stopped sync.WaitGroup
@@ -1056,19 +1056,24 @@ func TestRuntimeLockMetricsAndProfile(t *testing.T) {
1056
1056
t .Logf ("lock contention growth in runtime/pprof's view (%fs)" , profileGrowth )
1057
1057
t .Logf ("lock contention growth in runtime/metrics' view (%fs)" , metricGrowth )
1058
1058
1059
- if goexperiment .StaticLockRanking {
1060
- if ! slices .ContainsFunc (stk , func (s string ) bool {
1061
- return s == "runtime.systemstack" || s == "runtime.mcall" || s == "runtime.mstart"
1062
- }) {
1063
- // stk is a call stack that is still on the user stack when
1064
- // it calls runtime.unlock. Add the extra function that
1065
- // we'll see, when the static lock ranking implementation of
1066
- // runtime.unlockWithRank switches to the system stack.
1067
- stk = append ([]string {"runtime.unlockWithRank" }, stk ... )
1059
+ acceptStacks = append ([][]string (nil ), acceptStacks ... )
1060
+ for i , stk := range acceptStacks {
1061
+ if goexperiment .StaticLockRanking {
1062
+ if ! slices .ContainsFunc (stk , func (s string ) bool {
1063
+ return s == "runtime.systemstack" || s == "runtime.mcall" || s == "runtime.mstart"
1064
+ }) {
1065
+ // stk is a call stack that is still on the user stack when
1066
+ // it calls runtime.unlock. Add the extra function that
1067
+ // we'll see, when the static lock ranking implementation of
1068
+ // runtime.unlockWithRank switches to the system stack.
1069
+ stk = append ([]string {"runtime.unlockWithRank" }, stk ... )
1070
+ }
1068
1071
}
1072
+ acceptStacks [i ] = stk
1069
1073
}
1070
1074
1071
1075
var stks [][]string
1076
+ values := make ([][2 ]int64 , len (acceptStacks ))
1072
1077
for _ , s := range p .Sample {
1073
1078
var have []string
1074
1079
for _ , loc := range s .Location {
@@ -1077,18 +1082,26 @@ func TestRuntimeLockMetricsAndProfile(t *testing.T) {
1077
1082
}
1078
1083
}
1079
1084
stks = append (stks , have )
1080
- if slices .Equal (have , stk ) {
1081
- n += s .Value [0 ]
1082
- value += s .Value [1 ]
1085
+ for i , stk := range acceptStacks {
1086
+ if slices .Equal (have , stk ) {
1087
+ values [i ][0 ] += s .Value [0 ]
1088
+ values [i ][1 ] += s .Value [1 ]
1089
+ }
1083
1090
}
1084
1091
}
1085
- t .Logf ("stack %v has samples totaling n=%d value=%d" , stk , n , value )
1092
+ for i , stk := range acceptStacks {
1093
+ n += values [i ][0 ]
1094
+ value += values [i ][1 ]
1095
+ t .Logf ("stack %v has samples totaling n=%d value=%d" , stk , values [i ][0 ], values [i ][1 ])
1096
+ }
1086
1097
if n == 0 && value == 0 {
1087
1098
t .Logf ("profile:\n %s" , p )
1088
1099
for _ , have := range stks {
1089
1100
t .Logf ("have stack %v" , have )
1090
1101
}
1091
- t .Errorf ("want stack %v" , stk )
1102
+ for _ , stk := range acceptStacks {
1103
+ t .Errorf ("want stack %v" , stk )
1104
+ }
1092
1105
}
1093
1106
1094
1107
return metricGrowth , profileGrowth , n , value
@@ -1140,18 +1153,18 @@ func TestRuntimeLockMetricsAndProfile(t *testing.T) {
1140
1153
return true
1141
1154
}
1142
1155
1143
- stk := []string {
1156
+ stks := [][] string { {
1144
1157
"runtime.unlock" ,
1145
1158
"runtime_test." + name + ".func5.1" ,
1146
1159
"runtime_test.(*contentionWorker).run" ,
1147
- }
1160
+ }}
1148
1161
1149
1162
t .Run ("sample-1" , func (t * testing.T ) {
1150
1163
old := runtime .SetMutexProfileFraction (1 )
1151
1164
defer runtime .SetMutexProfileFraction (old )
1152
1165
1153
1166
needContention .Store (int64 (len (mus ) - 1 ))
1154
- metricGrowth , profileGrowth , n , _ := testcase (true , stk , workers , fn )(t )
1167
+ metricGrowth , profileGrowth , n , _ := testcase (true , stks , workers , fn )(t )
1155
1168
1156
1169
if have , want := metricGrowth , delay .Seconds ()* float64 (len (mus )); have < want {
1157
1170
// The test imposes a delay with usleep, verified with calls to
@@ -1175,7 +1188,7 @@ func TestRuntimeLockMetricsAndProfile(t *testing.T) {
1175
1188
defer runtime .SetMutexProfileFraction (old )
1176
1189
1177
1190
needContention .Store (int64 (len (mus ) - 1 ))
1178
- metricGrowth , profileGrowth , n , _ := testcase (true , stk , workers , fn )(t )
1191
+ metricGrowth , profileGrowth , n , _ := testcase (true , stks , workers , fn )(t )
1179
1192
1180
1193
// With 100 trials and profile fraction of 2, we expect to capture
1181
1194
// 50 samples. Allow the test to pass if we get at least 20 samples;
@@ -1231,19 +1244,32 @@ func TestRuntimeLockMetricsAndProfile(t *testing.T) {
1231
1244
return true
1232
1245
}
1233
1246
1234
- stk := []string {
1235
- "runtime.unlock" ,
1236
- "runtime.semrelease1" ,
1237
- "runtime_test.TestRuntimeLockMetricsAndProfile.func6.1" ,
1238
- "runtime_test.(*contentionWorker).run" ,
1247
+ stks := [][]string {
1248
+ {
1249
+ "runtime.unlock" ,
1250
+ "runtime.semrelease1" ,
1251
+ "runtime_test.TestRuntimeLockMetricsAndProfile.func6.1" ,
1252
+ "runtime_test.(*contentionWorker).run" ,
1253
+ },
1254
+ {
1255
+ "runtime.unlock" ,
1256
+ "runtime.semacquire1" ,
1257
+ "runtime.semacquire" ,
1258
+ "runtime_test.TestRuntimeLockMetricsAndProfile.func6.1" ,
1259
+ "runtime_test.(*contentionWorker).run" ,
1260
+ },
1239
1261
}
1240
1262
1241
1263
// Verify that we get call stack we expect, with anything more than zero
1242
1264
// cycles / zero samples. The duration of each contention event is too
1243
1265
// small relative to the expected overhead for us to verify its value
1244
1266
// more directly. Leave that to the explicit lock/unlock test.
1245
1267
1246
- testcase (false , stk , workers , fn )(t )
1268
+ testcase (false , stks , workers , fn )(t )
1269
+
1270
+ if remaining := tries .Load (); remaining >= 0 {
1271
+ t .Logf ("finished test early (%d tries remaining)" , remaining )
1272
+ }
1247
1273
})
1248
1274
}
1249
1275
0 commit comments