OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 4568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4579 static_cast<size_t>(idle_time_in_ms), size_of_objects, | 4579 static_cast<size_t>(idle_time_in_ms), size_of_objects, |
4580 final_incremental_mark_compact_speed_in_bytes_per_ms))) { | 4580 final_incremental_mark_compact_speed_in_bytes_per_ms))) { |
4581 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); | 4581 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); |
4582 gc_idle_time_handler_.NotifyIdleMarkCompact(); | 4582 gc_idle_time_handler_.NotifyIdleMarkCompact(); |
4583 return true; | 4583 return true; |
4584 } | 4584 } |
4585 return false; | 4585 return false; |
4586 } | 4586 } |
4587 | 4587 |
4588 | 4588 |
4589 double Heap::MonotonicallyIncreasingTimeInMs() { | 4589 GCIdleTimeHandler::HeapState Heap::ComputeHeapState(bool reduce_memory) { |
4590 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * | |
4591 static_cast<double>(base::Time::kMillisecondsPerSecond); | |
4592 } | |
4593 | |
4594 | |
4595 bool Heap::IdleNotification(int idle_time_in_ms) { | |
4596 return IdleNotification( | |
4597 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + | |
4598 (static_cast<double>(idle_time_in_ms) / | |
4599 static_cast<double>(base::Time::kMillisecondsPerSecond))); | |
4600 } | |
4601 | |
4602 | |
4603 bool Heap::IdleNotification(double deadline_in_seconds) { | |
4604 CHECK(HasBeenSetUp()); // http://crbug.com/425035 | |
4605 double deadline_in_ms = | |
4606 deadline_in_seconds * | |
4607 static_cast<double>(base::Time::kMillisecondsPerSecond); | |
4608 HistogramTimerScope idle_notification_scope( | |
4609 isolate_->counters()->gc_idle_notification()); | |
4610 double start_ms = MonotonicallyIncreasingTimeInMs(); | |
4611 double idle_time_in_ms = deadline_in_ms - start_ms; | |
4612 bool is_long_idle_notification = | |
4613 static_cast<size_t>(idle_time_in_ms) > | |
4614 GCIdleTimeHandler::kMaxFrameRenderingIdleTime; | |
4615 | |
4616 static const double kLastGCTimeTreshold = 1000; | |
4617 | |
4618 GCIdleTimeHandler::HeapState heap_state; | 4590 GCIdleTimeHandler::HeapState heap_state; |
4619 heap_state.contexts_disposed = contexts_disposed_; | 4591 heap_state.contexts_disposed = contexts_disposed_; |
4620 heap_state.contexts_disposal_rate = | 4592 heap_state.contexts_disposal_rate = |
4621 tracer()->ContextDisposalRateInMilliseconds(); | 4593 tracer()->ContextDisposalRateInMilliseconds(); |
4622 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); | 4594 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); |
4623 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); | 4595 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); |
4624 // TODO(ulan): Start incremental marking only for large heaps. | 4596 // TODO(ulan): Start incremental marking only for large heaps. |
4625 intptr_t limit = old_generation_allocation_limit_; | 4597 intptr_t limit = old_generation_allocation_limit_; |
4626 if (is_long_idle_notification && | 4598 if (reduce_memory) { |
4627 (start_ms - last_gc_time_ > kLastGCTimeTreshold)) { | |
4628 limit = idle_old_generation_allocation_limit_; | 4599 limit = idle_old_generation_allocation_limit_; |
4629 } | 4600 } |
4630 | 4601 |
4631 heap_state.can_start_incremental_marking = | 4602 heap_state.can_start_incremental_marking = |
4632 incremental_marking()->CanBeActivated() && | 4603 incremental_marking()->CanBeActivated() && |
4633 HeapIsFullEnoughToStartIncrementalMarking(limit) && | 4604 HeapIsFullEnoughToStartIncrementalMarking(limit) && |
4634 !mark_compact_collector()->sweeping_in_progress(); | 4605 !mark_compact_collector()->sweeping_in_progress(); |
4635 heap_state.sweeping_in_progress = | 4606 heap_state.sweeping_in_progress = |
4636 mark_compact_collector()->sweeping_in_progress(); | 4607 mark_compact_collector()->sweeping_in_progress(); |
4637 heap_state.sweeping_completed = | 4608 heap_state.sweeping_completed = |
4638 mark_compact_collector()->IsSweepingCompleted(); | 4609 mark_compact_collector()->IsSweepingCompleted(); |
4639 heap_state.mark_compact_speed_in_bytes_per_ms = | 4610 heap_state.mark_compact_speed_in_bytes_per_ms = |
4640 static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); | 4611 static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); |
4641 heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>( | 4612 heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>( |
4642 tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); | 4613 tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); |
4643 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms = | 4614 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms = |
4644 static_cast<size_t>( | 4615 static_cast<size_t>( |
4645 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); | 4616 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); |
4646 heap_state.scavenge_speed_in_bytes_per_ms = | 4617 heap_state.scavenge_speed_in_bytes_per_ms = |
4647 static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond()); | 4618 static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond()); |
4648 heap_state.used_new_space_size = new_space_.Size(); | 4619 heap_state.used_new_space_size = new_space_.Size(); |
4649 heap_state.new_space_capacity = new_space_.Capacity(); | 4620 heap_state.new_space_capacity = new_space_.Capacity(); |
4650 heap_state.new_space_allocation_throughput_in_bytes_per_ms = | 4621 heap_state.new_space_allocation_throughput_in_bytes_per_ms = |
4651 static_cast<size_t>( | 4622 static_cast<size_t>( |
4652 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); | 4623 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); |
| 4624 return heap_state; |
| 4625 } |
4653 | 4626 |
4654 GCIdleTimeAction action = | |
4655 gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); | |
4656 | 4627 |
4657 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( | 4628 bool Heap::PerformIdleTimeAction(GCIdleTimeAction action, |
4658 static_cast<int>(idle_time_in_ms)); | 4629 GCIdleTimeHandler::HeapState heap_state, |
4659 if (is_long_idle_notification) { | 4630 double deadline_in_ms, |
4660 int committed_memory = static_cast<int>(CommittedMemory() / KB); | 4631 bool is_long_idle_notification) { |
4661 int used_memory = static_cast<int>(heap_state.size_of_objects / KB); | |
4662 isolate()->counters()->aggregated_memory_heap_committed()->AddSample( | |
4663 start_ms, committed_memory); | |
4664 isolate()->counters()->aggregated_memory_heap_used()->AddSample( | |
4665 start_ms, used_memory); | |
4666 } | |
4667 | |
4668 bool result = false; | 4632 bool result = false; |
4669 switch (action.type) { | 4633 switch (action.type) { |
4670 case DONE: | 4634 case DONE: |
4671 result = true; | 4635 result = true; |
4672 break; | 4636 break; |
4673 case DO_INCREMENTAL_MARKING: { | 4637 case DO_INCREMENTAL_MARKING: { |
4674 if (incremental_marking()->IsStopped()) { | 4638 if (incremental_marking()->IsStopped()) { |
4675 // TODO(ulan): take reduce_memory into account. | 4639 // TODO(ulan): take reduce_memory into account. |
4676 incremental_marking()->Start(); | 4640 incremental_marking()->Start(); |
4677 } | 4641 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4716 mark_compact_collector()->EnsureSweepingCompleted(); | 4680 mark_compact_collector()->EnsureSweepingCompleted(); |
4717 break; | 4681 break; |
4718 case DO_NOTHING: | 4682 case DO_NOTHING: |
4719 break; | 4683 break; |
4720 } | 4684 } |
4721 | 4685 |
4722 if (action.reduce_memory) { | 4686 if (action.reduce_memory) { |
4723 new_space_.Shrink(); | 4687 new_space_.Shrink(); |
4724 UncommitFromSpace(); | 4688 UncommitFromSpace(); |
4725 } | 4689 } |
| 4690 return result; |
| 4691 } |
4726 | 4692 |
| 4693 |
| 4694 void Heap::IdleNotificationEpilogue(GCIdleTimeAction action, |
| 4695 GCIdleTimeHandler::HeapState heap_state, |
| 4696 double start_ms, double deadline_in_ms, |
| 4697 bool is_long_idle_notification) { |
| 4698 double idle_time_in_ms = deadline_in_ms - start_ms; |
4727 double current_time = MonotonicallyIncreasingTimeInMs(); | 4699 double current_time = MonotonicallyIncreasingTimeInMs(); |
4728 last_idle_notification_time_ = current_time; | 4700 last_idle_notification_time_ = current_time; |
4729 double deadline_difference = deadline_in_ms - current_time; | 4701 double deadline_difference = deadline_in_ms - current_time; |
4730 | 4702 |
| 4703 contexts_disposed_ = 0; |
| 4704 |
| 4705 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
| 4706 static_cast<int>(idle_time_in_ms)); |
| 4707 |
| 4708 if (is_long_idle_notification) { |
| 4709 int committed_memory = static_cast<int>(CommittedMemory() / KB); |
| 4710 int used_memory = static_cast<int>(heap_state.size_of_objects / KB); |
| 4711 isolate()->counters()->aggregated_memory_heap_committed()->AddSample( |
| 4712 start_ms, committed_memory); |
| 4713 isolate()->counters()->aggregated_memory_heap_used()->AddSample( |
| 4714 start_ms, used_memory); |
| 4715 } |
| 4716 |
4731 if (deadline_difference >= 0) { | 4717 if (deadline_difference >= 0) { |
4732 if (action.type != DONE && action.type != DO_NOTHING) { | 4718 if (action.type != DONE && action.type != DO_NOTHING) { |
4733 isolate()->counters()->gc_idle_time_limit_undershot()->AddSample( | 4719 isolate()->counters()->gc_idle_time_limit_undershot()->AddSample( |
4734 static_cast<int>(deadline_difference)); | 4720 static_cast<int>(deadline_difference)); |
4735 } | 4721 } |
4736 } else { | 4722 } else { |
4737 isolate()->counters()->gc_idle_time_limit_overshot()->AddSample( | 4723 isolate()->counters()->gc_idle_time_limit_overshot()->AddSample( |
4738 static_cast<int>(-deadline_difference)); | 4724 static_cast<int>(-deadline_difference)); |
4739 } | 4725 } |
4740 | 4726 |
4741 if ((FLAG_trace_idle_notification && action.type > DO_NOTHING) || | 4727 if ((FLAG_trace_idle_notification && action.type > DO_NOTHING) || |
4742 FLAG_trace_idle_notification_verbose) { | 4728 FLAG_trace_idle_notification_verbose) { |
4743 PrintIsolate(isolate_, "%8.0f ms: ", isolate()->time_millis_since_init()); | 4729 PrintIsolate(isolate_, "%8.0f ms: ", isolate()->time_millis_since_init()); |
4744 PrintF( | 4730 PrintF( |
4745 "Idle notification: requested idle time %.2f ms, used idle time %.2f " | 4731 "Idle notification: requested idle time %.2f ms, used idle time %.2f " |
4746 "ms, deadline usage %.2f ms [", | 4732 "ms, deadline usage %.2f ms [", |
4747 idle_time_in_ms, idle_time_in_ms - deadline_difference, | 4733 idle_time_in_ms, idle_time_in_ms - deadline_difference, |
4748 deadline_difference); | 4734 deadline_difference); |
4749 action.Print(); | 4735 action.Print(); |
4750 PrintF("]"); | 4736 PrintF("]"); |
4751 if (FLAG_trace_idle_notification_verbose) { | 4737 if (FLAG_trace_idle_notification_verbose) { |
4752 PrintF("["); | 4738 PrintF("["); |
4753 heap_state.Print(); | 4739 heap_state.Print(); |
4754 PrintF("]"); | 4740 PrintF("]"); |
4755 } | 4741 } |
4756 PrintF("\n"); | 4742 PrintF("\n"); |
4757 } | 4743 } |
| 4744 } |
4758 | 4745 |
4759 contexts_disposed_ = 0; | 4746 |
| 4747 double Heap::MonotonicallyIncreasingTimeInMs() { |
| 4748 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * |
| 4749 static_cast<double>(base::Time::kMillisecondsPerSecond); |
| 4750 } |
| 4751 |
| 4752 |
| 4753 bool Heap::IdleNotification(int idle_time_in_ms) { |
| 4754 return IdleNotification( |
| 4755 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + |
| 4756 (static_cast<double>(idle_time_in_ms) / |
| 4757 static_cast<double>(base::Time::kMillisecondsPerSecond))); |
| 4758 } |
| 4759 |
| 4760 |
| 4761 bool Heap::IdleNotification(double deadline_in_seconds) { |
| 4762 CHECK(HasBeenSetUp()); |
| 4763 static const double kLastGCTimeTreshold = 1000; |
| 4764 double deadline_in_ms = |
| 4765 deadline_in_seconds * |
| 4766 static_cast<double>(base::Time::kMillisecondsPerSecond); |
| 4767 HistogramTimerScope idle_notification_scope( |
| 4768 isolate_->counters()->gc_idle_notification()); |
| 4769 double start_ms = MonotonicallyIncreasingTimeInMs(); |
| 4770 double idle_time_in_ms = deadline_in_ms - start_ms; |
| 4771 bool is_long_idle_notification = |
| 4772 static_cast<size_t>(idle_time_in_ms) > |
| 4773 GCIdleTimeHandler::kMaxFrameRenderingIdleTime; |
| 4774 bool has_low_gc_activity = (start_ms - last_gc_time_) > kLastGCTimeTreshold; |
| 4775 |
| 4776 GCIdleTimeHandler::HeapState heap_state = |
| 4777 ComputeHeapState(is_long_idle_notification && has_low_gc_activity); |
| 4778 |
| 4779 GCIdleTimeAction action = |
| 4780 gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); |
| 4781 |
| 4782 bool result = PerformIdleTimeAction(action, heap_state, deadline_in_ms, |
| 4783 is_long_idle_notification); |
| 4784 |
| 4785 IdleNotificationEpilogue(action, heap_state, start_ms, deadline_in_ms, |
| 4786 is_long_idle_notification); |
4760 return result; | 4787 return result; |
4761 } | 4788 } |
4762 | 4789 |
4763 | 4790 |
4764 bool Heap::RecentIdleNotificationHappened() { | 4791 bool Heap::RecentIdleNotificationHappened() { |
4765 return (last_idle_notification_time_ + | 4792 return (last_idle_notification_time_ + |
4766 GCIdleTimeHandler::kMaxScheduledIdleTime) > | 4793 GCIdleTimeHandler::kMaxScheduledIdleTime) > |
4767 MonotonicallyIncreasingTimeInMs(); | 4794 MonotonicallyIncreasingTimeInMs(); |
4768 } | 4795 } |
4769 | 4796 |
(...skipping 1775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6545 *object_type = "CODE_TYPE"; \ | 6572 *object_type = "CODE_TYPE"; \ |
6546 *object_sub_type = "CODE_AGE/" #name; \ | 6573 *object_sub_type = "CODE_AGE/" #name; \ |
6547 return true; | 6574 return true; |
6548 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6575 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6549 #undef COMPARE_AND_RETURN_NAME | 6576 #undef COMPARE_AND_RETURN_NAME |
6550 } | 6577 } |
6551 return false; | 6578 return false; |
6552 } | 6579 } |
6553 } | 6580 } |
6554 } // namespace v8::internal | 6581 } // namespace v8::internal |
OLD | NEW |