Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: src/heap.cc

Issue 9701093: Adjust heuristics for idle notifications after context disposal. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/heap.h ('K') | « src/heap.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after
4814 4814
4815 void Heap::EnsureHeapIsIterable() { 4815 void Heap::EnsureHeapIsIterable() {
4816 ASSERT(IsAllocationAllowed()); 4816 ASSERT(IsAllocationAllowed());
4817 if (!IsHeapIterable()) { 4817 if (!IsHeapIterable()) {
4818 CollectAllGarbage(kMakeHeapIterableMask, "Heap::EnsureHeapIsIterable"); 4818 CollectAllGarbage(kMakeHeapIterableMask, "Heap::EnsureHeapIsIterable");
4819 } 4819 }
4820 ASSERT(IsHeapIterable()); 4820 ASSERT(IsHeapIterable());
4821 } 4821 }
4822 4822
4823 4823
4824 void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) {
ulan 2012/03/16 13:37:23 This function is extracted from lines 4876-4894 of
4825 // This flag prevents incremental marking from requesting GC via stack guard
4826 idle_notification_will_schedule_next_gc_ = true;
4827 incremental_marking()->Step(step_size);
4828 idle_notification_will_schedule_next_gc_ = false;
4829
4830 if (incremental_marking()->IsComplete()) {
4831 bool uncommit = false;
4832 if (gc_count_at_last_idle_gc_ == gc_count_) {
4833 // No GC since the last full GC, the mutator is probably not active.
4834 isolate_->compilation_cache()->Clear();
4835 uncommit = true;
4836 }
4837 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental");
4838 gc_count_at_last_idle_gc_ = gc_count_;
4839 if (uncommit) {
4840 new_space_.Shrink();
4841 UncommitFromSpace();
4842 }
4843 }
4844 }
4845
4846
4824 bool Heap::IdleNotification(int hint) { 4847 bool Heap::IdleNotification(int hint) {
4825 if (hint >= 1000) return IdleGlobalGC(); 4848 intptr_t size_factor = Min(Max(hint, 30), 1000) / 10;
4826 if (contexts_disposed_ > 0 || !FLAG_incremental_marking || 4849 // The size factor is in range [3..100].
4850 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold;
4851
4852 if (contexts_disposed_ > 0) {
4853 if (hint > TimeMarkSweepWouldTakeInMs() && !FLAG_expose_gc) {
4854 HistogramTimerScope scope(isolate_->counters()->gc_context());
4855 CollectAllGarbage(kReduceMemoryFootprintMask,
4856 "idle notification: contexts disposed");
4857 } else {
4858 AdvanceIdleIncrementalMarking(step_size);
4859 contexts_disposed_ = 0;
4860 }
4861 // Make sure that we have no pending context disposals.
4862 // Take into account that we might have decided to delay full collection
4863 // because incremental marking is in progress.
4864 ASSERT((contexts_disposed_ == 0) || !incremental_marking()->IsStopped());
4865 return false;
4866 }
4867
4868 if (hint >= 1000 || !FLAG_incremental_marking ||
ulan 2012/03/16 13:37:23 Once this CL lands into Chromium without memory re
4827 FLAG_expose_gc || Serializer::enabled()) { 4869 FLAG_expose_gc || Serializer::enabled()) {
4828 return true; 4870 return IdleGlobalGC();
4829 } 4871 }
4830 4872
4831 // By doing small chunks of GC work in each IdleNotification, 4873 // By doing small chunks of GC work in each IdleNotification,
4832 // perform a round of incremental GCs and after that wait until 4874 // perform a round of incremental GCs and after that wait until
4833 // the mutator creates enough garbage to justify a new round. 4875 // the mutator creates enough garbage to justify a new round.
4834 // An incremental GC progresses as follows: 4876 // An incremental GC progresses as follows:
4835 // 1. many incremental marking steps, 4877 // 1. many incremental marking steps,
4836 // 2. one old space mark-sweep-compact, 4878 // 2. one old space mark-sweep-compact,
4837 // 3. many lazy sweep steps. 4879 // 3. many lazy sweep steps.
4838 // Use mark-sweep-compact events to count incremental GCs in a round. 4880 // Use mark-sweep-compact events to count incremental GCs in a round.
4839 4881
4840 intptr_t size_factor = Min(Max(hint, 30), 1000) / 10;
4841 // The size factor is in range [3..100].
4842 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold;
4843 4882
4844 if (incremental_marking()->IsStopped()) { 4883 if (incremental_marking()->IsStopped()) {
4845 if (!IsSweepingComplete() && 4884 if (!IsSweepingComplete() &&
4846 !AdvanceSweepers(static_cast<int>(step_size))) { 4885 !AdvanceSweepers(static_cast<int>(step_size))) {
4847 return false; 4886 return false;
4848 } 4887 }
4849 } 4888 }
4850 4889
4851 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { 4890 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
4852 if (EnoughGarbageSinceLastIdleRound()) { 4891 if (EnoughGarbageSinceLastIdleRound()) {
4853 StartIdleRound(); 4892 StartIdleRound();
4854 } else { 4893 } else {
4855 return true; 4894 return true;
4856 } 4895 }
4857 } 4896 }
4858 4897
4859 int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_; 4898 int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_;
4860 mark_sweeps_since_idle_round_started_ += new_mark_sweeps; 4899 mark_sweeps_since_idle_round_started_ += new_mark_sweeps;
4861 ms_count_at_last_idle_notification_ = ms_count_; 4900 ms_count_at_last_idle_notification_ = ms_count_;
4862 4901
4863 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { 4902 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
4864 FinishIdleRound(); 4903 FinishIdleRound();
4865 return true; 4904 return true;
4866 } 4905 }
4867 4906
4868 if (incremental_marking()->IsStopped()) { 4907 if (incremental_marking()->IsStopped()) {
4869 if (hint < 1000 && !WorthStartingGCWhenIdle()) { 4908 if (!WorthStartingGCWhenIdle()) {
4870 FinishIdleRound(); 4909 FinishIdleRound();
4871 return true; 4910 return true;
4872 } 4911 }
4873 incremental_marking()->Start(); 4912 incremental_marking()->Start();
4874 } 4913 }
4875 4914
4876 // This flag prevents incremental marking from requesting GC via stack guard 4915 AdvanceIdleIncrementalMarking(step_size);
4877 idle_notification_will_schedule_next_gc_ = true;
4878 incremental_marking()->Step(step_size);
4879 idle_notification_will_schedule_next_gc_ = false;
4880
4881 if (incremental_marking()->IsComplete()) {
4882 bool uncommit = false;
4883 if (gc_count_at_last_idle_gc_ == gc_count_) {
4884 // No GC since the last full GC, the mutator is probably not active.
4885 isolate_->compilation_cache()->Clear();
4886 uncommit = true;
4887 }
4888 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental");
4889 gc_count_at_last_idle_gc_ = gc_count_;
4890 if (uncommit) {
4891 new_space_.Shrink();
4892 UncommitFromSpace();
4893 }
4894 }
4895 return false; 4916 return false;
4896 } 4917 }
4897 4918
4898 4919
4899 bool Heap::IdleGlobalGC() { 4920 bool Heap::IdleGlobalGC() {
4900 static const int kIdlesBeforeScavenge = 4; 4921 static const int kIdlesBeforeScavenge = 4;
4901 static const int kIdlesBeforeMarkSweep = 7; 4922 static const int kIdlesBeforeMarkSweep = 7;
4902 static const int kIdlesBeforeMarkCompact = 8; 4923 static const int kIdlesBeforeMarkCompact = 8;
4903 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; 4924 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
4904 static const unsigned int kGCsBetweenCleanup = 4; 4925 static const unsigned int kGCsBetweenCleanup = 4;
(...skipping 12 matching lines...) Expand all
4917 // provoke a number of garbage collections. 4938 // provoke a number of garbage collections.
4918 if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) { 4939 if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) {
4919 number_idle_notifications_ = 4940 number_idle_notifications_ =
4920 Min(number_idle_notifications_ + 1, kMaxIdleCount); 4941 Min(number_idle_notifications_ + 1, kMaxIdleCount);
4921 } else { 4942 } else {
4922 number_idle_notifications_ = 0; 4943 number_idle_notifications_ = 0;
4923 last_idle_notification_gc_count_ = gc_count_; 4944 last_idle_notification_gc_count_ = gc_count_;
4924 } 4945 }
4925 4946
4926 if (number_idle_notifications_ == kIdlesBeforeScavenge) { 4947 if (number_idle_notifications_ == kIdlesBeforeScavenge) {
4927 if (contexts_disposed_ > 0) { 4948 CollectGarbage(NEW_SPACE, "idle notification");
4928 HistogramTimerScope scope(isolate_->counters()->gc_context());
4929 CollectAllGarbage(kReduceMemoryFootprintMask,
4930 "idle notification: contexts disposed");
4931 } else {
4932 CollectGarbage(NEW_SPACE, "idle notification");
4933 }
4934 new_space_.Shrink(); 4949 new_space_.Shrink();
4935 last_idle_notification_gc_count_ = gc_count_; 4950 last_idle_notification_gc_count_ = gc_count_;
4936 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) { 4951 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) {
4937 // Before doing the mark-sweep collections we clear the 4952 // Before doing the mark-sweep collections we clear the
4938 // compilation cache to avoid hanging on to source code and 4953 // compilation cache to avoid hanging on to source code and
4939 // generated code for cached functions. 4954 // generated code for cached functions.
4940 isolate_->compilation_cache()->Clear(); 4955 isolate_->compilation_cache()->Clear();
4941 4956
4942 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification"); 4957 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification");
4943 new_space_.Shrink(); 4958 new_space_.Shrink();
4944 last_idle_notification_gc_count_ = gc_count_; 4959 last_idle_notification_gc_count_ = gc_count_;
4945 4960
4946 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) { 4961 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) {
4947 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification"); 4962 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification");
4948 new_space_.Shrink(); 4963 new_space_.Shrink();
4949 last_idle_notification_gc_count_ = gc_count_; 4964 last_idle_notification_gc_count_ = gc_count_;
4950 number_idle_notifications_ = 0; 4965 number_idle_notifications_ = 0;
4951 finished = true; 4966 finished = true;
4952 } else if (contexts_disposed_ > 0) {
4953 if (FLAG_expose_gc) {
4954 contexts_disposed_ = 0;
4955 } else {
4956 HistogramTimerScope scope(isolate_->counters()->gc_context());
4957 CollectAllGarbage(kReduceMemoryFootprintMask,
4958 "idle notification: contexts disposed");
4959 last_idle_notification_gc_count_ = gc_count_;
4960 }
4961 // If this is the first idle notification, we reset the
4962 // notification count to avoid letting idle notifications for
4963 // context disposal garbage collections start a potentially too
4964 // aggressive idle GC cycle.
4965 if (number_idle_notifications_ <= 1) {
4966 number_idle_notifications_ = 0;
4967 uncommit = false;
4968 }
4969 } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) { 4967 } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) {
4970 // If we have received more than kIdlesBeforeMarkCompact idle 4968 // If we have received more than kIdlesBeforeMarkCompact idle
4971 // notifications we do not perform any cleanup because we don't 4969 // notifications we do not perform any cleanup because we don't
4972 // expect to gain much by doing so. 4970 // expect to gain much by doing so.
4973 finished = true; 4971 finished = true;
4974 } 4972 }
4975 4973
4976 // Make sure that we have no pending context disposals and
4977 // conditionally uncommit from space.
4978 // Take into account that we might have decided to delay full collection
4979 // because incremental marking is in progress.
4980 ASSERT((contexts_disposed_ == 0) || !incremental_marking()->IsStopped());
4981 if (uncommit) UncommitFromSpace(); 4974 if (uncommit) UncommitFromSpace();
4982 4975
4983 return finished; 4976 return finished;
4984 } 4977 }
4985 4978
4986 4979
4987 #ifdef DEBUG 4980 #ifdef DEBUG
4988 4981
4989 void Heap::Print() { 4982 void Heap::Print() {
4990 if (!HasBeenSetUp()) return; 4983 if (!HasBeenSetUp()) return;
(...skipping 1974 matching lines...) Expand 10 before | Expand all | Expand 10 after
6965 isolate_->heap()->store_buffer()->Compact(); 6958 isolate_->heap()->store_buffer()->Compact();
6966 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); 6959 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
6967 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { 6960 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
6968 next = chunk->next_chunk(); 6961 next = chunk->next_chunk();
6969 isolate_->memory_allocator()->Free(chunk); 6962 isolate_->memory_allocator()->Free(chunk);
6970 } 6963 }
6971 chunks_queued_for_free_ = NULL; 6964 chunks_queued_for_free_ = NULL;
6972 } 6965 }
6973 6966
6974 } } // namespace v8::internal 6967 } } // namespace v8::internal
OLDNEW
« src/heap.h ('K') | « src/heap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698