@@ -394,7 +394,6 @@ type mspan struct {
394
394
divShift2 uint8 // for divide by elemsize - divMagic.shift2
395
395
scavenged bool // whether this span has had its pages released to the OS
396
396
elemsize uintptr // computed from sizeclass or from npages
397
- unusedsince int64 // first time spotted by gc in mspanfree state
398
397
limit uintptr // end of data in span
399
398
speciallock mutex // guards specials list
400
399
specials * special // linked list of special records sorted by offset.
@@ -1209,10 +1208,9 @@ HaveSpan:
1209
1208
// Also, scavenge may cause coalescing, so prevent
1210
1209
// coalescing with s by temporarily changing its state.
1211
1210
s .state = mSpanManual
1212
- h .scavengeLocked (s .npages * pageSize )
1211
+ h .scavengeLocked (s .npages * pageSize , true )
1213
1212
s .state = mSpanFree
1214
1213
}
1215
- s .unusedsince = 0
1216
1214
1217
1215
h .setSpans (s .base (), npage , s )
1218
1216
@@ -1243,7 +1241,7 @@ func (h *mheap) grow(npage uintptr) bool {
1243
1241
// is proportional to the number of sysUnused() calls rather than
1244
1242
// the number of pages released, so we make fewer of those calls
1245
1243
// with larger spans.
1246
- h .scavengeLocked (size )
1244
+ h .scavengeLocked (size , true )
1247
1245
1248
1246
// Create a fake "in use" span and free it, so that the
1249
1247
// right coalescing happens.
@@ -1253,7 +1251,7 @@ func (h *mheap) grow(npage uintptr) bool {
1253
1251
atomic .Store (& s .sweepgen , h .sweepgen )
1254
1252
s .state = mSpanInUse
1255
1253
h .pagesInUse += uint64 (s .npages )
1256
- h .freeSpanLocked (s , false , true , 0 )
1254
+ h .freeSpanLocked (s , false , true )
1257
1255
return true
1258
1256
}
1259
1257
@@ -1283,7 +1281,7 @@ func (h *mheap) freeSpan(s *mspan, large bool) {
1283
1281
// heap_scan changed.
1284
1282
gcController .revise ()
1285
1283
}
1286
- h .freeSpanLocked (s , true , true , 0 )
1284
+ h .freeSpanLocked (s , true , true )
1287
1285
unlock (& h .lock )
1288
1286
})
1289
1287
}
@@ -1304,12 +1302,12 @@ func (h *mheap) freeManual(s *mspan, stat *uint64) {
1304
1302
lock (& h .lock )
1305
1303
* stat -= uint64 (s .npages << _PageShift )
1306
1304
memstats .heap_sys += uint64 (s .npages << _PageShift )
1307
- h .freeSpanLocked (s , false , true , 0 )
1305
+ h .freeSpanLocked (s , false , true )
1308
1306
unlock (& h .lock )
1309
1307
}
1310
1308
1311
1309
// s must be on the busy list or unlinked.
1312
- func (h * mheap ) freeSpanLocked (s * mspan , acctinuse , acctidle bool , unusedsince int64 ) {
1310
+ func (h * mheap ) freeSpanLocked (s * mspan , acctinuse , acctidle bool ) {
1313
1311
switch s .state {
1314
1312
case mSpanManual :
1315
1313
if s .allocCount != 0 {
@@ -1337,13 +1335,6 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
1337
1335
}
1338
1336
s .state = mSpanFree
1339
1337
1340
- // Stamp newly unused spans. The scavenger will use that
1341
- // info to potentially give back some pages to the OS.
1342
- s .unusedsince = unusedsince
1343
- if unusedsince == 0 {
1344
- s .unusedsince = nanotime ()
1345
- }
1346
-
1347
1338
// Coalesce span with neighbors.
1348
1339
h .coalesce (s )
1349
1340
@@ -1353,15 +1344,23 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
1353
1344
1354
1345
// scavengeLocked scavenges nbytes worth of spans in the free treap by
1355
1346
// starting from the span with the highest base address and working down.
1356
- // It then takes those spans and places them in scav. h must be locked.
1357
- func (h * mheap ) scavengeLocked (nbytes uintptr ) {
1347
+ // It then takes those spans and places them in scav.
1348
+ //
1349
+ // useCredit determines whether a scavenging call should use the credit
1350
+ // system. In general, useCredit should be true except in special
1351
+ // circumstances.
1352
+ //
1353
+ // Returns the amount of memory scavenged in bytes. h must be locked.
1354
+ func (h * mheap ) scavengeLocked (nbytes uintptr , useCredit bool ) uintptr {
1358
1355
// Use up scavenge credit if there's any available.
1359
- if nbytes > h .scavengeCredit {
1360
- nbytes -= h .scavengeCredit
1361
- h .scavengeCredit = 0
1362
- } else {
1363
- h .scavengeCredit -= nbytes
1364
- return
1356
+ if useCredit {
1357
+ if nbytes > h .scavengeCredit {
1358
+ nbytes -= h .scavengeCredit
1359
+ h .scavengeCredit = 0
1360
+ } else {
1361
+ h .scavengeCredit -= nbytes
1362
+ return nbytes
1363
+ }
1365
1364
}
1366
1365
released := uintptr (0 )
1367
1366
// Iterate over spans with huge pages first, then spans without.
@@ -1388,60 +1387,41 @@ func (h *mheap) scavengeLocked(nbytes uintptr) {
1388
1387
h .free .insert (s )
1389
1388
}
1390
1389
}
1391
- // If we over-scavenged, turn that extra amount into credit.
1392
- if released > nbytes {
1393
- h .scavengeCredit += released - nbytes
1394
- }
1395
- }
1396
-
1397
- // scavengeAll visits each node in the unscav treap and scavenges the
1398
- // treapNode's span. It then removes the scavenged span from
1399
- // unscav and adds it into scav before continuing. h must be locked.
1400
- func (h * mheap ) scavengeAllLocked (now , limit uint64 ) uintptr {
1401
- // Iterate over the unscavenged spans in the treap scavenging spans
1402
- // if unused for at least limit time.
1403
- released := uintptr (0 )
1404
- for t := h .free .start (treapIterScav , 0 ); t .valid (); {
1405
- s := t .span ()
1406
- n := t .next ()
1407
- if (now - uint64 (s .unusedsince )) > limit {
1408
- start , end := s .physPageBounds ()
1409
- if start < end {
1410
- h .free .erase (t )
1411
- released += s .scavenge ()
1412
- // See (*mheap).scavengeLocked.
1413
- h .coalesce (s )
1414
- h .free .insert (s )
1415
- }
1390
+ if useCredit {
1391
+ // If we over-scavenged, turn that extra amount into credit.
1392
+ if released > nbytes {
1393
+ h .scavengeCredit += released - nbytes
1416
1394
}
1417
- t = n
1418
1395
}
1419
1396
return released
1420
1397
}
1421
1398
1422
- func (h * mheap ) scavengeAll (k int32 , now , limit uint64 ) {
1399
+ // scavengeAll visits each node in the free treap and scavenges the
1400
+ // treapNode's span. It then removes the scavenged span from
1401
+ // unscav and adds it into scav before continuing.
1402
+ func (h * mheap ) scavengeAll () {
1423
1403
// Disallow malloc or panic while holding the heap lock. We do
1424
1404
// this here because this is an non-mallocgc entry-point to
1425
1405
// the mheap API.
1426
1406
gp := getg ()
1427
1407
gp .m .mallocing ++
1428
1408
lock (& h .lock )
1429
- released := h .scavengeAllLocked ( now , limit )
1409
+ released := h .scavengeLocked ( ^ uintptr ( 0 ), false )
1430
1410
unlock (& h .lock )
1431
1411
gp .m .mallocing --
1432
1412
1433
1413
if debug .gctrace > 0 {
1434
1414
if released > 0 {
1435
- print ("scvg" , k , " : " , released >> 20 , " MB released\n " )
1415
+ print ("forced scvg : " , released >> 20 , " MB released\n " )
1436
1416
}
1437
- print ("scvg" , k , " : inuse: " , memstats .heap_inuse >> 20 , ", idle: " , memstats .heap_idle >> 20 , ", sys: " , memstats .heap_sys >> 20 , ", released: " , memstats .heap_released >> 20 , ", consumed: " , (memstats .heap_sys - memstats .heap_released )>> 20 , " (MB)\n " )
1417
+ print ("forced scvg : inuse: " , memstats .heap_inuse >> 20 , ", idle: " , memstats .heap_idle >> 20 , ", sys: " , memstats .heap_sys >> 20 , ", released: " , memstats .heap_released >> 20 , ", consumed: " , (memstats .heap_sys - memstats .heap_released )>> 20 , " (MB)\n " )
1438
1418
}
1439
1419
}
1440
1420
1441
1421
//go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory
1442
1422
func runtime_debug_freeOSMemory () {
1443
1423
GC ()
1444
- systemstack (func () { mheap_ .scavengeAll (- 1 , ^ uint64 ( 0 ), 0 ) })
1424
+ systemstack (func () { mheap_ .scavengeAll () })
1445
1425
}
1446
1426
1447
1427
// Initialize a new span with the given start and npages.
@@ -1456,7 +1436,6 @@ func (span *mspan) init(base uintptr, npages uintptr) {
1456
1436
span .spanclass = 0
1457
1437
span .elemsize = 0
1458
1438
span .state = mSpanDead
1459
- span .unusedsince = 0
1460
1439
span .scavenged = false
1461
1440
span .speciallock .key = 0
1462
1441
span .specials = nil
0 commit comments