Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | 850fdf70db2b |
children | cff162798819 |
comparison
equal
deleted
inserted
replaced
1111:44f61c24ddab | 1145:e018e6884bd8 |
---|---|
60 tl->set_hint(0); | 60 tl->set_hint(0); |
61 tl->set_size(tc->size()); | 61 tl->set_size(tc->size()); |
62 tl->link_head(tc); | 62 tl->link_head(tc); |
63 tl->link_tail(tc); | 63 tl->link_tail(tc); |
64 tl->set_count(1); | 64 tl->set_count(1); |
65 tl->init_statistics(); | 65 tl->init_statistics(true /* split_birth */); |
66 tl->setParent(NULL); | 66 tl->setParent(NULL); |
67 tl->setLeft(NULL); | 67 tl->setLeft(NULL); |
68 tl->setRight(NULL); | 68 tl->setRight(NULL); |
69 return tl; | 69 return tl; |
70 } | 70 } |
71 | |
71 TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) { | 72 TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) { |
72 TreeChunk* tc = (TreeChunk*) addr; | 73 TreeChunk* tc = (TreeChunk*) addr; |
73 assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk"); | 74 assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk"); |
74 // The space in the heap will have been mangled initially but | 75 // The space in the heap will have been mangled initially but |
75 // is not remangled when a free chunk is returned to the free list | 76 // is not remangled when a free chunk is returned to the free list |
265 } | 266 } |
266 assert(retTC->list() == this, "Wrong type of chunk."); | 267 assert(retTC->list() == this, "Wrong type of chunk."); |
267 return retTC; | 268 return retTC; |
268 } | 269 } |
269 | 270 |
271 // Returns the block with the largest heap address amongst | |
272 // those in the list for this size; potentially slow and expensive, | |
273 // use with caution! | |
274 TreeChunk* TreeList::largest_address() { | |
275 guarantee(head() != NULL, "The head of the list cannot be NULL"); | |
276 FreeChunk* fc = head()->next(); | |
277 TreeChunk* retTC; | |
278 if (fc == NULL) { | |
279 retTC = head_as_TreeChunk(); | |
280 } else { | |
281 // walk down the list and return the one with the highest | |
282 // heap address among chunks of this size. | |
283 FreeChunk* last = fc; | |
284 while (fc->next() != NULL) { | |
285 if ((HeapWord*)last < (HeapWord*)fc) { | |
286 last = fc; | |
287 } | |
288 fc = fc->next(); | |
289 } | |
290 retTC = TreeChunk::as_TreeChunk(last); | |
291 } | |
292 assert(retTC->list() == this, "Wrong type of chunk."); | |
293 return retTC; | |
294 } | |
295 | |
270 BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay): | 296 BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay): |
271 _splay(splay) | 297 _splay(splay) |
272 { | 298 { |
273 assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size"); | 299 assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size"); |
274 | 300 |
377 // Change the candidate. | 403 // Change the candidate. |
378 curTL = hintTL; | 404 curTL = hintTL; |
379 break; | 405 break; |
380 } | 406 } |
381 // The evm code reset the hint of the candidate as | 407 // The evm code reset the hint of the candidate as |
382 // at an interrim point. Why? Seems like this leaves | 408 // at an interim point. Why? Seems like this leaves |
383 // the hint pointing to a list that didn't work. | 409 // the hint pointing to a list that didn't work. |
384 // curTL->set_hint(hintTL->size()); | 410 // curTL->set_hint(hintTL->size()); |
385 } | 411 } |
386 } | 412 } |
387 } | 413 } |
434 | 460 |
435 FreeChunk* BinaryTreeDictionary::findLargestDict() const { | 461 FreeChunk* BinaryTreeDictionary::findLargestDict() const { |
436 TreeList *curTL = root(); | 462 TreeList *curTL = root(); |
437 if (curTL != NULL) { | 463 if (curTL != NULL) { |
438 while(curTL->right() != NULL) curTL = curTL->right(); | 464 while(curTL->right() != NULL) curTL = curTL->right(); |
439 return curTL->first_available(); | 465 return curTL->largest_address(); |
440 } else { | 466 } else { |
441 return NULL; | 467 return NULL; |
442 } | 468 } |
443 } | 469 } |
444 | 470 |
662 assert(curTL->size() < size, "size inconsistency"); | 688 assert(curTL->size() < size, "size inconsistency"); |
663 curTL = curTL->right(); | 689 curTL = curTL->right(); |
664 } | 690 } |
665 } | 691 } |
666 TreeChunk* tc = TreeChunk::as_TreeChunk(fc); | 692 TreeChunk* tc = TreeChunk::as_TreeChunk(fc); |
667 // This chunk is being returned to the binary try. It's embedded | 693 // This chunk is being returned to the binary tree. Its embedded |
668 // TreeList should be unused at this point. | 694 // TreeList should be unused at this point. |
669 tc->initialize(); | 695 tc->initialize(); |
670 if (curTL != NULL) { // exact match | 696 if (curTL != NULL) { // exact match |
671 tc->set_list(curTL); | 697 tc->set_list(curTL); |
672 curTL->returnChunkAtTail(tc); | 698 curTL->returnChunkAtTail(tc); |
805 // This is a birth associated with a LinAB. The chunk | 831 // This is a birth associated with a LinAB. The chunk |
806 // for the LinAB is not in the dictionary. | 832 // for the LinAB is not in the dictionary. |
807 } | 833 } |
808 | 834 |
809 bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) { | 835 bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) { |
836 if (FLSAlwaysCoalesceLarge) return true; | |
837 | |
810 TreeList* list_of_size = findList(size); | 838 TreeList* list_of_size = findList(size); |
811 // None of requested size implies overpopulated. | 839 // None of requested size implies overpopulated. |
812 return list_of_size == NULL || list_of_size->coalDesired() <= 0 || | 840 return list_of_size == NULL || list_of_size->coalDesired() <= 0 || |
813 list_of_size->count() > list_of_size->coalDesired(); | 841 list_of_size->count() > list_of_size->coalDesired(); |
814 } | 842 } |
852 // coalesce, count before sweep, and surplus before sweep. | 880 // coalesce, count before sweep, and surplus before sweep. |
853 class BeginSweepClosure : public AscendTreeCensusClosure { | 881 class BeginSweepClosure : public AscendTreeCensusClosure { |
854 double _percentage; | 882 double _percentage; |
855 float _inter_sweep_current; | 883 float _inter_sweep_current; |
856 float _inter_sweep_estimate; | 884 float _inter_sweep_estimate; |
885 float _intra_sweep_estimate; | |
857 | 886 |
858 public: | 887 public: |
859 BeginSweepClosure(double p, float inter_sweep_current, | 888 BeginSweepClosure(double p, float inter_sweep_current, |
860 float inter_sweep_estimate) : | 889 float inter_sweep_estimate, |
890 float intra_sweep_estimate) : | |
861 _percentage(p), | 891 _percentage(p), |
862 _inter_sweep_current(inter_sweep_current), | 892 _inter_sweep_current(inter_sweep_current), |
863 _inter_sweep_estimate(inter_sweep_estimate) { } | 893 _inter_sweep_estimate(inter_sweep_estimate), |
894 _intra_sweep_estimate(intra_sweep_estimate) { } | |
864 | 895 |
865 void do_list(FreeList* fl) { | 896 void do_list(FreeList* fl) { |
866 double coalSurplusPercent = _percentage; | 897 double coalSurplusPercent = _percentage; |
867 fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate); | 898 fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); |
868 fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent)); | 899 fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent)); |
869 fl->set_beforeSweep(fl->count()); | 900 fl->set_beforeSweep(fl->count()); |
870 fl->set_bfrSurp(fl->surplus()); | 901 fl->set_bfrSurp(fl->surplus()); |
871 } | 902 } |
872 }; | 903 }; |
937 assert(!found_target || etsc.found() != NULL, "Consistency check"); | 968 assert(!found_target || etsc.found() != NULL, "Consistency check"); |
938 return etsc.found(); | 969 return etsc.found(); |
939 } | 970 } |
940 | 971 |
941 void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent, | 972 void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent, |
942 float inter_sweep_current, float inter_sweep_estimate) { | 973 float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { |
943 BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, | 974 BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, |
944 inter_sweep_estimate); | 975 inter_sweep_estimate, |
976 intra_sweep_estimate); | |
945 bsc.do_tree(root()); | 977 bsc.do_tree(root()); |
946 } | 978 } |
947 | 979 |
948 // Closures and methods for calculating total bytes returned to the | 980 // Closures and methods for calculating total bytes returned to the |
949 // free lists in the tree. | 981 // free lists in the tree. |
1075 } | 1107 } |
1076 | 1108 |
1077 // Print census information - counts, births, deaths, etc. | 1109 // Print census information - counts, births, deaths, etc. |
1078 // for each list in the tree. Also print some summary | 1110 // for each list in the tree. Also print some summary |
1079 // information. | 1111 // information. |
1080 class printTreeCensusClosure : public AscendTreeCensusClosure { | 1112 class PrintTreeCensusClosure : public AscendTreeCensusClosure { |
1081 int _print_line; | 1113 int _print_line; |
1082 size_t _totalFree; | 1114 size_t _totalFree; |
1083 FreeList _total; | 1115 FreeList _total; |
1084 | 1116 |
1085 public: | 1117 public: |
1086 printTreeCensusClosure() { | 1118 PrintTreeCensusClosure() { |
1087 _print_line = 0; | 1119 _print_line = 0; |
1088 _totalFree = 0; | 1120 _totalFree = 0; |
1089 } | 1121 } |
1090 FreeList* total() { return &_total; } | 1122 FreeList* total() { return &_total; } |
1091 size_t totalFree() { return _totalFree; } | 1123 size_t totalFree() { return _totalFree; } |
1111 | 1143 |
1112 void BinaryTreeDictionary::printDictCensus(void) const { | 1144 void BinaryTreeDictionary::printDictCensus(void) const { |
1113 | 1145 |
1114 gclog_or_tty->print("\nBinaryTree\n"); | 1146 gclog_or_tty->print("\nBinaryTree\n"); |
1115 FreeList::print_labels_on(gclog_or_tty, "size"); | 1147 FreeList::print_labels_on(gclog_or_tty, "size"); |
1116 printTreeCensusClosure ptc; | 1148 PrintTreeCensusClosure ptc; |
1117 ptc.do_tree(root()); | 1149 ptc.do_tree(root()); |
1118 | 1150 |
1119 FreeList* total = ptc.total(); | 1151 FreeList* total = ptc.total(); |
1120 FreeList::print_labels_on(gclog_or_tty, " "); | 1152 FreeList::print_labels_on(gclog_or_tty, " "); |
1121 total->print_on(gclog_or_tty, "TOTAL\t"); | 1153 total->print_on(gclog_or_tty, "TOTAL\t"); |
1126 (double)(total->splitBirths() + total->coalBirths() | 1158 (double)(total->splitBirths() + total->coalBirths() |
1127 - total->splitDeaths() - total->coalDeaths()) | 1159 - total->splitDeaths() - total->coalDeaths()) |
1128 /(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0), | 1160 /(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0), |
1129 (double)(total->desired() - total->count()) | 1161 (double)(total->desired() - total->count()) |
1130 /(total->desired() != 0 ? (double)total->desired() : 1.0)); | 1162 /(total->desired() != 0 ? (double)total->desired() : 1.0)); |
1163 } | |
1164 | |
1165 class PrintFreeListsClosure : public AscendTreeCensusClosure { | |
1166 outputStream* _st; | |
1167 int _print_line; | |
1168 | |
1169 public: | |
1170 PrintFreeListsClosure(outputStream* st) { | |
1171 _st = st; | |
1172 _print_line = 0; | |
1173 } | |
1174 void do_list(FreeList* fl) { | |
1175 if (++_print_line >= 40) { | |
1176 FreeList::print_labels_on(_st, "size"); | |
1177 _print_line = 0; | |
1178 } | |
1179 fl->print_on(gclog_or_tty); | |
1180 size_t sz = fl->size(); | |
1181 for (FreeChunk* fc = fl->head(); fc != NULL; | |
1182 fc = fc->next()) { | |
1183 _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", | |
1184 fc, (HeapWord*)fc + sz, | |
1185 fc->cantCoalesce() ? "\t CC" : ""); | |
1186 } | |
1187 } | |
1188 }; | |
1189 | |
1190 void BinaryTreeDictionary::print_free_lists(outputStream* st) const { | |
1191 | |
1192 FreeList::print_labels_on(st, "size"); | |
1193 PrintFreeListsClosure pflc(st); | |
1194 pflc.do_tree(root()); | |
1131 } | 1195 } |
1132 | 1196 |
1133 // Verify the following tree invariants: | 1197 // Verify the following tree invariants: |
1134 // . _root has no parent | 1198 // . _root has no parent |
1135 // . parent and child point to each other | 1199 // . parent and child point to each other |