diff options
| author | Richard Brooksby | 2012-09-11 21:21:26 +0100 |
|---|---|---|
| committer | Richard Brooksby | 2012-09-11 21:21:26 +0100 |
| commit | 789066596d1b4f74706620fe6b60d1927a21723e (patch) | |
| tree | 8003a0f656bc9e9f9d1ba21031fee24f63b6bda9 /mps/code | |
| parent | 346ab4aa0943646ae69758a89ece3dc21a8f5524 (diff) | |
| download | emacs-789066596d1b4f74706620fe6b60d1927a21723e.tar.gz emacs-789066596d1b4f74706620fe6b60d1927a21723e.zip | |
Configuring awl pool to give give up and scan an entire segment after 200 single access hits, after observing open dylan bootstrap on ubuntu 12 hammering the table and making no progress.
AWL pool no longer tries a single access if the trace band has reached rank WEAK, since it doesn't need to.
Copied from Perforce
Change: 179434
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/config.h | 8 | ||||
| -rw-r--r-- | mps/code/eventdef.h | 14 | ||||
| -rw-r--r-- | mps/code/poolawl.c | 83 |
3 files changed, 76 insertions, 29 deletions
diff --git a/mps/code/config.h b/mps/code/config.h index 8df33201f5f..5eb8ee50e13 100644 --- a/mps/code/config.h +++ b/mps/code/config.h | |||
| @@ -393,6 +393,14 @@ | |||
| 393 | #define AMCLargeSegPAGES ((Count)8) | 393 | #define AMCLargeSegPAGES ((Count)8) |
| 394 | 394 | ||
| 395 | 395 | ||
| 396 | /* Pool Class AWL configuration -- see poolawl.c for usage */ | ||
| 397 | |||
| 398 | #define AWL_HAVE_SEG_SA_LIMIT TRUE | ||
| 399 | #define AWL_SEG_SA_LIMIT 200 /* TODO: Improve guesswork with measurements */ | ||
| 400 | #define AWL_HAVE_TOTAL_SA_LIMIT FALSE | ||
| 401 | #define AWL_TOTAL_SA_LIMIT 0 | ||
| 402 | |||
| 403 | |||
| 396 | #endif /* config_h */ | 404 | #endif /* config_h */ |
| 397 | 405 | ||
| 398 | 406 | ||
diff --git a/mps/code/eventdef.h b/mps/code/eventdef.h index 56d0271975b..9f5ea780787 100644 --- a/mps/code/eventdef.h +++ b/mps/code/eventdef.h | |||
| @@ -68,7 +68,7 @@ | |||
| 68 | */ | 68 | */ |
| 69 | 69 | ||
| 70 | #define EventNameMAX ((size_t)19) | 70 | #define EventNameMAX ((size_t)19) |
| 71 | #define EventCodeMAX ((EventCode)0x0071) | 71 | #define EventCodeMAX ((EventCode)0x0073) |
| 72 | 72 | ||
| 73 | #define EVENT_LIST(EVENT, X) \ | 73 | #define EVENT_LIST(EVENT, X) \ |
| 74 | /* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \ | 74 | /* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \ |
| @@ -177,7 +177,9 @@ | |||
| 177 | EVENT(X, MessagesExist , 0x006E, TRUE, Arena) \ | 177 | EVENT(X, MessagesExist , 0x006E, TRUE, Arena) \ |
| 178 | EVENT(X, ChainCondemnAuto , 0x006F, TRUE, Trace) \ | 178 | EVENT(X, ChainCondemnAuto , 0x006F, TRUE, Trace) \ |
| 179 | EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \ | 179 | EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \ |
| 180 | EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) | 180 | EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) \ |
| 181 | EVENT(X, AWLDeclineTotal , 0x0072, TRUE, Trace) \ | ||
| 182 | EVENT(X, AWLDeclineSeg , 0x0073, TRUE, Trace) | ||
| 181 | 183 | ||
| 182 | 184 | ||
| 183 | /* Remember to update EventNameMAX and EventCodeMAX in eventcom.h! | 185 | /* Remember to update EventNameMAX and EventCodeMAX in eventcom.h! |
| @@ -610,6 +612,14 @@ | |||
| 610 | PARAM(X, 1, W, ti) \ | 612 | PARAM(X, 1, W, ti) \ |
| 611 | PARAM(X, 2, W, rank) | 613 | PARAM(X, 2, W, rank) |
| 612 | 614 | ||
| 615 | #define EVENT_AWLDeclineTotal_PARAMS(PARAM, X) \ | ||
| 616 | PARAM(X, 0, P, seg) /* segment declined single access */ \ | ||
| 617 | PARAM(X, 1, U, succAccesses) /* total successive accesses */ | ||
| 618 | |||
| 619 | #define EVENT_AWLDeclineSeg_PARAMS(PARAM, X) \ | ||
| 620 | PARAM(X, 0, P, seg) /* segment declined single access */ \ | ||
| 621 | PARAM(X, 1, U, singleAccesses) /* single accesses this cycle */ | ||
| 622 | |||
| 613 | 623 | ||
| 614 | #endif /* eventdef_h */ | 624 | #endif /* eventdef_h */ |
| 615 | 625 | ||
diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index da63a4374d3..e775517a7b2 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c | |||
| @@ -289,50 +289,79 @@ DEFINE_SEG_CLASS(AWLSegClass, class) | |||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | 291 | ||
| 292 | /* Single access permission control parameters */ | 292 | /* Single access pattern control parameters |
| 293 | * | ||
| 294 | * These control the number of expensive emulated single-accesses we allow | ||
| 295 | * before we give up and scan a segment at whatever rank, possibly causing | ||
| 296 | * retention of weak objects. | ||
| 297 | * | ||
| 298 | * AWLSegSALimit is the number of accesses for a single segment in a GC cycle. | ||
| 299 | * AWLTotalSALimit is the total number of accesses during a GC cycle. | ||
| 300 | * | ||
| 301 | * These should be set in config.h, but are here in static variables so that | ||
| 302 | * it's possible to tweak them in a debugger. | ||
| 303 | */ | ||
| 293 | 304 | ||
| 294 | Count AWLSegSALimit = 0; /* Number of single accesses permitted per segment */ | 305 | Count AWLSegSALimit = AWL_SEG_SA_LIMIT; |
| 295 | Bool AWLHaveSegSALimit = FALSE; /* When TRUE, AWLSegSALimit applies */ | 306 | Bool AWLHaveSegSALimit = AWL_HAVE_SEG_SA_LIMIT; |
| 296 | 307 | ||
| 297 | Count AWLTotalSALimit = 0; /* Number of single accesses permitted in a row */ | 308 | Count AWLTotalSALimit = AWL_TOTAL_SA_LIMIT; |
| 298 | Bool AWLHaveTotalSALimit = FALSE; /* When TRUE, AWLTotalSALimit applies */ | 309 | Bool AWLHaveTotalSALimit = AWL_HAVE_TOTAL_SA_LIMIT; |
| 299 | 310 | ||
| 300 | 311 | ||
| 301 | /* Determine whether to permit scanning a single ref. */ | 312 | /* Determine whether to permit scanning a single ref. */ |
| 302 | 313 | ||
| 303 | static Bool AWLCanTrySingleAccess(AWL awl, Seg seg, Addr addr) | 314 | static Bool AWLCanTrySingleAccess(Arena arena, AWL awl, Seg seg, Addr addr) |
| 304 | { | 315 | { |
| 316 | AWLSeg awlseg; | ||
| 317 | |||
| 305 | AVERT(AWL, awl); | 318 | AVERT(AWL, awl); |
| 306 | AVERT(Seg, seg); | 319 | AVERT(Seg, seg); |
| 307 | AVER(addr != NULL); | 320 | AVER(addr != NULL); |
| 308 | 321 | ||
| 309 | /* .assume.noweak */ | 322 | /* .assume.noweak */ |
| 310 | /* .assume.alltraceable */ | 323 | /* .assume.alltraceable */ |
| 311 | if(RankSetIsMember(SegRankSet(seg), RankWEAK)) { | 324 | if (!RankSetIsMember(SegRankSet(seg), RankWEAK)) |
| 312 | AWLSeg awlseg; | 325 | return FALSE; |
| 313 | 326 | ||
| 314 | awlseg = Seg2AWLSeg(seg); | 327 | /* If there are no traces in progress then the segment isn't read |
| 315 | AVERT(AWLSeg, awlseg); | 328 | protected and this is just an ordinary write barrier hit. No need to |
| 329 | scan at all. */ | ||
| 330 | if (arena->flippedTraces == TraceSetEMPTY) { | ||
| 331 | AVER(!(SegSM(seg) & AccessREAD)); | ||
| 332 | return FALSE; | ||
| 333 | } | ||
| 316 | 334 | ||
| 317 | if(AWLHaveTotalSALimit) { | 335 | /* The trace is already in the weak band, so we can scan the whole |
| 318 | if(AWLTotalSALimit < awl->succAccesses) { | 336 | segment without retention anyway. Go for it. */ |
| 319 | STATISTIC(awl->stats.declined++); | 337 | if (TraceRankForAccess(arena, seg) == RankWEAK) |
| 320 | return FALSE; /* decline single access because of total limit */ | 338 | return FALSE; |
| 321 | } | ||
| 322 | } | ||
| 323 | 339 | ||
| 324 | if(AWLHaveSegSALimit) { | 340 | awlseg = Seg2AWLSeg(seg); |
| 325 | if(AWLSegSALimit < awlseg->singleAccesses) { | 341 | AVERT(AWLSeg, awlseg); |
| 326 | STATISTIC(awl->stats.declined++); | ||
| 327 | return FALSE; /* decline single access because of segment limit */ | ||
| 328 | } | ||
| 329 | } | ||
| 330 | 342 | ||
| 331 | return TRUE; | 343 | /* If there have been too many single accesses in a row then don't |
| 344 | keep trying them, even if it means retaining objects. */ | ||
| 345 | if(AWLHaveTotalSALimit) { | ||
| 346 | if(awl->succAccesses >= AWLTotalSALimit) { | ||
| 347 | STATISTIC(awl->stats.declined++); | ||
| 348 | EVENT2(AWLDeclineTotal, seg, awl->succAccesses); | ||
| 349 | return FALSE; /* decline single access because of total limit */ | ||
| 350 | } | ||
| 351 | } | ||
| 332 | 352 | ||
| 333 | } else { | 353 | /* If there have been too many single accesses to this segment |
| 334 | return FALSE; /* Single access only for weak segs (.assume.noweak) */ | 354 | then don't keep trying them, even if it means retaining objects. |
| 355 | (Observed behaviour in Open Dylan 2012-09-10 by RB.) */ | ||
| 356 | if(AWLHaveSegSALimit) { | ||
| 357 | if(awlseg->singleAccesses >= AWLSegSALimit) { | ||
| 358 | STATISTIC(awl->stats.declined++); | ||
| 359 | EVENT2(AWLDeclineSeg, seg, awlseg->singleAccesses); | ||
| 360 | return FALSE; /* decline single access because of segment limit */ | ||
| 361 | } | ||
| 335 | } | 362 | } |
| 363 | |||
| 364 | return TRUE; | ||
| 336 | } | 365 | } |
| 337 | 366 | ||
| 338 | 367 | ||
| @@ -1116,9 +1145,9 @@ static Res AWLAccess(Pool pool, Seg seg, Addr addr, | |||
| 1116 | AVER(SegBase(seg) <= addr); | 1145 | AVER(SegBase(seg) <= addr); |
| 1117 | AVER(addr < SegLimit(seg)); | 1146 | AVER(addr < SegLimit(seg)); |
| 1118 | AVER(SegPool(seg) == pool); | 1147 | AVER(SegPool(seg) == pool); |
| 1119 | 1148 | ||
| 1120 | /* Attempt scanning a single reference if permitted */ | 1149 | /* Attempt scanning a single reference if permitted */ |
| 1121 | if(AWLCanTrySingleAccess(awl, seg, addr)) { | 1150 | if(AWLCanTrySingleAccess(PoolArena(pool), awl, seg, addr)) { |
| 1122 | res = PoolSingleAccess(pool, seg, addr, mode, context); | 1151 | res = PoolSingleAccess(pool, seg, addr, mode, context); |
| 1123 | switch(res) { | 1152 | switch(res) { |
| 1124 | case ResOK: | 1153 | case ResOK: |