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

Side by Side Diff: content/common/gpu/gpu_memory_manager.cc

Issue 12087078: Add unit tests for nonuniform GPU memmgr policy (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Clean up private Created 7 years, 10 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium 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 "content/common/gpu/gpu_memory_manager.h" 5 #include "content/common/gpu/gpu_memory_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 GpuChannelManager* channel_manager, 49 GpuChannelManager* channel_manager,
50 uint64 max_surfaces_with_frontbuffer_soft_limit) 50 uint64 max_surfaces_with_frontbuffer_soft_limit)
51 : channel_manager_(channel_manager), 51 : channel_manager_(channel_manager),
52 use_nonuniform_memory_policy_(false), 52 use_nonuniform_memory_policy_(false),
53 manage_immediate_scheduled_(false), 53 manage_immediate_scheduled_(false),
54 max_surfaces_with_frontbuffer_soft_limit_( 54 max_surfaces_with_frontbuffer_soft_limit_(
55 max_surfaces_with_frontbuffer_soft_limit), 55 max_surfaces_with_frontbuffer_soft_limit),
56 bytes_available_gpu_memory_(0), 56 bytes_available_gpu_memory_(0),
57 bytes_available_gpu_memory_overridden_(false), 57 bytes_available_gpu_memory_overridden_(false),
58 bytes_minimum_per_client_(0), 58 bytes_minimum_per_client_(0),
59 bytes_minimum_per_client_overridden_(false), 59 bytes_default_per_client_(0),
60 bytes_nonvisible_available_gpu_memory_(0), 60 bytes_nonvisible_available_gpu_memory_(0),
61 bytes_allocated_managed_current_(0), 61 bytes_allocated_managed_current_(0),
62 bytes_allocated_managed_visible_(0), 62 bytes_allocated_managed_visible_(0),
63 bytes_allocated_managed_nonvisible_(0), 63 bytes_allocated_managed_nonvisible_(0),
64 bytes_allocated_unmanaged_current_(0), 64 bytes_allocated_unmanaged_current_(0),
65 bytes_allocated_historical_max_(0), 65 bytes_allocated_historical_max_(0),
66 bytes_allocated_unmanaged_high_(0), 66 bytes_allocated_unmanaged_high_(0),
67 bytes_allocated_unmanaged_low_(0), 67 bytes_allocated_unmanaged_low_(0),
68 bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep), 68 bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep),
69 window_count_has_been_received_(false), 69 window_count_has_been_received_(false),
70 window_count_(0), 70 window_count_(0),
71 disable_schedule_manage_(false) 71 disable_schedule_manage_(false)
72 { 72 {
73 CommandLine* command_line = CommandLine::ForCurrentProcess(); 73 CommandLine* command_line = CommandLine::ForCurrentProcess();
74
75 #if defined(OS_ANDROID)
76 bytes_default_per_client_ = 32 * 1024 * 1024;
77 bytes_minimum_per_client_ = 32 * 1024 * 1024;
78 #else
79 bytes_default_per_client_ = 64 * 1024 * 1024;
80 bytes_minimum_per_client_ = 64 * 1024 * 1024;
81 #endif
82
74 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { 83 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) {
75 base::StringToUint64( 84 base::StringToUint64(
76 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), 85 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb),
77 &bytes_available_gpu_memory_); 86 &bytes_available_gpu_memory_);
78 bytes_available_gpu_memory_ *= 1024 * 1024; 87 bytes_available_gpu_memory_ *= 1024 * 1024;
79 bytes_available_gpu_memory_overridden_ = true; 88 bytes_available_gpu_memory_overridden_ = true;
80 } else 89 } else
81 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); 90 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory();
82 UpdateNonvisibleAvailableGpuMemory(); 91 UpdateNonvisibleAvailableGpuMemory();
83 } 92 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) 140 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
132 return bytes_available_gpu_memory_; 141 return bytes_available_gpu_memory_;
133 #else 142 #else
134 // This is to avoid allowing a single page on to use a full 256MB of memory 143 // This is to avoid allowing a single page on to use a full 256MB of memory
135 // (the current total limit). Long-scroll pages will hit this limit, 144 // (the current total limit). Long-scroll pages will hit this limit,
136 // resulting in instability on some platforms (e.g, issue 141377). 145 // resulting in instability on some platforms (e.g, issue 141377).
137 return bytes_available_gpu_memory_ / 2; 146 return bytes_available_gpu_memory_ / 2;
138 #endif 147 #endif
139 } 148 }
140 149
141 uint64 GpuMemoryManager::GetMinimumClientAllocation() const {
142 if (bytes_minimum_per_client_overridden_)
143 return bytes_minimum_per_client_;
144 #if defined(OS_ANDROID)
145 return 32 * 1024 * 1024;
146 #elif defined(OS_CHROMEOS)
147 return 64 * 1024 * 1024;
148 #else
149 return 64 * 1024 * 1024;
150 #endif
151 }
152
153 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) { 150 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) {
154 // We can't query available GPU memory from the system on Android, but 151 // We can't query available GPU memory from the system on Android, but
155 // 18X the viewport and 50% of the dalvik heap size give us a good 152 // 18X the viewport and 50% of the dalvik heap size give us a good
156 // estimate of available GPU memory on a wide range of devices. 153 // estimate of available GPU memory on a wide range of devices.
157 const int kViewportMultiplier = 18; 154 const int kViewportMultiplier = 18;
158 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA 155 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA
159 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte) 156 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte)
160 uint64 viewport_limit = viewport_area * kViewportMultiplier * 157 uint64 viewport_limit = viewport_area * kViewportMultiplier *
161 kComponentsPerPixel * 158 kComponentsPerPixel *
162 kBytesPerComponent; 159 kBytesPerComponent;
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 GpuMemoryManagerClientState* client_state, 379 GpuMemoryManagerClientState* client_state,
383 const GpuManagedMemoryStats& stats) 380 const GpuManagedMemoryStats& stats)
384 { 381 {
385 TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, 382 TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated,
386 stats.bytes_allocated, 383 stats.bytes_allocated,
387 client_state->visible_ ? 384 client_state->visible_ ?
388 &bytes_allocated_managed_visible_ : 385 &bytes_allocated_managed_visible_ :
389 &bytes_allocated_managed_nonvisible_); 386 &bytes_allocated_managed_nonvisible_);
390 client_state->managed_memory_stats_ = stats; 387 client_state->managed_memory_stats_ = stats;
391 388
389 // If this is the first time that stats have been received for this
390 // client, use them immediately.
391 if (!client_state->managed_memory_stats_received_) {
392 client_state->managed_memory_stats_received_ = true;
393 ScheduleManage(kScheduleManageNow);
394 return;
395 }
396
392 if (use_nonuniform_memory_policy_) { 397 if (use_nonuniform_memory_policy_) {
393 // If these statistics sit outside of the range that we used in our 398 // If these statistics sit outside of the range that we used in our
394 // computation of memory allocations then recompute the allocations. 399 // computation of memory allocations then recompute the allocations.
395 if (client_state->managed_memory_stats_.bytes_nice_to_have > 400 if (client_state->managed_memory_stats_.bytes_nice_to_have >
396 client_state->bytes_nicetohave_limit_high_) { 401 client_state->bytes_nicetohave_limit_high_) {
397 ScheduleManage(kScheduleManageNow); 402 ScheduleManage(kScheduleManageNow);
398 } else if (client_state->managed_memory_stats_.bytes_nice_to_have < 403 } else if (client_state->managed_memory_stats_.bytes_nice_to_have <
399 client_state->bytes_nicetohave_limit_low_) { 404 client_state->bytes_nicetohave_limit_low_) {
400 ScheduleManage(kScheduleManageLater); 405 ScheduleManage(kScheduleManageLater);
401 } 406 }
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 return bytes_sum_limit / bytes_size; 559 return bytes_sum_limit / bytes_size;
555 } 560 }
556 561
557 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible( 562 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible(
558 GpuMemoryManagerClientState* client_state, 563 GpuMemoryManagerClientState* client_state,
559 uint64 bytes_above_required_cap, 564 uint64 bytes_above_required_cap,
560 uint64 bytes_above_minimum_cap, 565 uint64 bytes_above_minimum_cap,
561 uint64 bytes_overall_cap) { 566 uint64 bytes_overall_cap) {
562 GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_; 567 GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_;
563 568
569 if (!client_state->managed_memory_stats_received_)
570 return GetDefaultClientAllocation();
571
564 uint64 bytes_required = 9 * stats->bytes_required / 8; 572 uint64 bytes_required = 9 * stats->bytes_required / 8;
565 bytes_required = std::min(bytes_required, GetMaximumClientAllocation()); 573 bytes_required = std::min(bytes_required, GetMaximumClientAllocation());
566 bytes_required = std::max(bytes_required, GetMinimumClientAllocation()); 574 bytes_required = std::max(bytes_required, GetMinimumClientAllocation());
567 575
568 uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3; 576 uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3;
569 bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation()); 577 bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation());
570 bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation()); 578 bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation());
571 bytes_nicetohave = std::max(bytes_nicetohave, bytes_required); 579 bytes_nicetohave = std::max(bytes_nicetohave, bytes_required);
572 580
573 uint64 allocation = GetMinimumClientAllocation(); 581 uint64 allocation = GetMinimumClientAllocation();
574 allocation += std::min(bytes_required - GetMinimumClientAllocation(), 582 allocation += std::min(bytes_required - GetMinimumClientAllocation(),
575 bytes_above_minimum_cap); 583 bytes_above_minimum_cap);
576 allocation += std::min(bytes_nicetohave - bytes_required, 584 allocation += std::min(bytes_nicetohave - bytes_required,
577 bytes_above_required_cap); 585 bytes_above_required_cap);
578 allocation = std::min(allocation, 586 allocation = std::min(allocation,
579 bytes_overall_cap); 587 bytes_overall_cap);
580 return allocation; 588 return allocation;
581 } 589 }
582 590
583 uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible( 591 uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible(
584 GpuMemoryManagerClientState* client_state) { 592 GpuMemoryManagerClientState* client_state) {
593
594 if (!client_state->managed_memory_stats_received_)
595 return 0;
596
585 return 9 * client_state->managed_memory_stats_.bytes_required / 8; 597 return 9 * client_state->managed_memory_stats_.bytes_required / 8;
586 } 598 }
587 599
588 void GpuMemoryManager::ComputeVisibleSurfacesAllocationsNonuniform() { 600 void GpuMemoryManager::ComputeVisibleSurfacesAllocationsNonuniform() {
589 uint64 bytes_available_total = GetAvailableGpuMemory(); 601 uint64 bytes_available_total = GetAvailableGpuMemory();
590 uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max(); 602 uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max();
591 uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max(); 603 uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max();
592 uint64 bytes_overall_cap_visible = GetMaximumClientAllocation(); 604 uint64 bytes_overall_cap_visible = GetMaximumClientAllocation();
593 605
594 // Compute memory usage at three levels 606 // Compute memory usage at three levels
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 bytes_available_nonvisible_adjusted) 760 bytes_available_nonvisible_adjusted)
749 client_state->bytes_allocation_when_nonvisible_ = 0; 761 client_state->bytes_allocation_when_nonvisible_ = 0;
750 } 762 }
751 763
752 // Compute which currently nonvisible clients should keep their contents. 764 // Compute which currently nonvisible clients should keep their contents.
753 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin(); 765 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
754 it != clients_nonvisible_mru_.end(); 766 it != clients_nonvisible_mru_.end();
755 ++it) { 767 ++it) {
756 GpuMemoryManagerClientState* client_state = *it; 768 GpuMemoryManagerClientState* client_state = *it;
757 769
770 // If this client is nonvisible and has already had its contents discarded,
771 // don't re-generate the contents until the client becomes visible again.
772 if (!client_state->bytes_allocation_when_nonvisible_)
773 continue;
774
758 client_state->bytes_allocation_when_nonvisible_ = 775 client_state->bytes_allocation_when_nonvisible_ =
759 ComputeClientAllocationWhenNonvisible(client_state); 776 ComputeClientAllocationWhenNonvisible(client_state);
760 777
761 // Take into account all more recently used nonvisible clients, and only if 778 // Take into account all more recently used nonvisible clients, and only if
762 // this client still fits, all it to keep its contents. 779 // this client still fits, all it to keep its contents.
763 if (bytes_allocated_nonvisible + 780 if (bytes_allocated_nonvisible +
764 client_state->bytes_allocation_when_nonvisible_ > 781 client_state->bytes_allocation_when_nonvisible_ >
765 bytes_allocated_nonvisible) { 782 bytes_available_nonvisible) {
766 client_state->bytes_allocation_when_nonvisible_ = 0; 783 client_state->bytes_allocation_when_nonvisible_ = 0;
767 } 784 }
768 bytes_allocated_nonvisible += 785 bytes_allocated_nonvisible +=
769 client_state->bytes_allocation_when_nonvisible_; 786 client_state->bytes_allocation_when_nonvisible_;
770 } 787 }
771 } 788 }
772 789
773 void GpuMemoryManager::AssignSurfacesAllocationsNonuniform() { 790 void GpuMemoryManager::AssignSurfacesAllocationsNonuniform() {
774 // Compute allocation when for all clients. 791 // Compute allocation when for all clients.
775 ComputeVisibleSurfacesAllocationsNonuniform(); 792 ComputeVisibleSurfacesAllocationsNonuniform();
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 1042
1026 void GpuMemoryManager::RemoveClientFromList( 1043 void GpuMemoryManager::RemoveClientFromList(
1027 GpuMemoryManagerClientState* client_state) { 1044 GpuMemoryManagerClientState* client_state) {
1028 DCHECK(client_state->list_iterator_valid_); 1045 DCHECK(client_state->list_iterator_valid_);
1029 ClientStateList* client_list = GetClientList(client_state); 1046 ClientStateList* client_list = GetClientList(client_state);
1030 client_list->erase(client_state->list_iterator_); 1047 client_list->erase(client_state->list_iterator_);
1031 client_state->list_iterator_valid_ = false; 1048 client_state->list_iterator_valid_ = false;
1032 } 1049 }
1033 1050
1034 } // namespace content 1051 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698