[wasm] Add metrics for Wasm memory allocation
This adds two new UMA histograms to give us more insight into Wasm memory allocation. The first records the result of every attempt to to allocate a Wasm backing store. This will let us know things like how often we explicitly trigger a GC, or how often we hit our address space limit. The second records how many megabytes of address space Wasm reserves. A sample is added every time the number either increases or decreases. This metric will give us a sense of how many outstanding Wasm memories there are in typical usage. Change-Id: I38c1bc1ad915c26b6cda3c373ededdd395193a4c Reviewed-on: https://chromium-review.googlesource.com/1024646 Commit-Queue: Eric Holk <eholk@chromium.org> Reviewed-by: Deepti Gandluri <gdeepti@chromium.org> Cr-Commit-Position: refs/heads/master@{#52767}
This commit is contained in:
parent
238dff2664
commit
45dd38c167
@ -1143,7 +1143,10 @@ class RuntimeCallTimerScope {
|
||||
20) \
|
||||
HR(wasm_lazy_compilation_throughput, V8.WasmLazyCompilationThroughput, 1, \
|
||||
10000, 50) \
|
||||
HR(compile_script_cache_behaviour, V8.CompileScript.CacheBehaviour, 0, 19, 20)
|
||||
HR(compile_script_cache_behaviour, V8.CompileScript.CacheBehaviour, 0, 19, \
|
||||
20) \
|
||||
HR(wasm_memory_allocation_result, V8.WasmMemoryAllocationResult, 0, 3, 4) \
|
||||
HR(wasm_address_space_usage_mb, V8.WasmAddressSpaceUsageMiB, 0, 1 << 20, 128)
|
||||
|
||||
#define HISTOGRAM_TIMER_LIST(HT) \
|
||||
/* Garbage collection timers. */ \
|
||||
|
@ -3020,6 +3020,10 @@ bool Isolate::Init(StartupDeserializer* des) {
|
||||
wasm_engine_.reset(new wasm::WasmEngine(
|
||||
std::unique_ptr<wasm::WasmCodeManager>(new wasm::WasmCodeManager(
|
||||
reinterpret_cast<v8::Isolate*>(this), max_code_size))));
|
||||
wasm_engine_->memory_tracker()->SetAllocationResultHistogram(
|
||||
counters()->wasm_memory_allocation_result());
|
||||
wasm_engine_->memory_tracker()->SetAddressSpaceUsageHistogram(
|
||||
counters()->wasm_address_space_usage_mb());
|
||||
|
||||
// Initialize the interface descriptors ahead of time.
|
||||
#define INTERFACE_DESCRIPTOR(Name, ...) \
|
||||
|
@ -13,10 +13,13 @@ namespace internal {
|
||||
namespace wasm {
|
||||
|
||||
namespace {
|
||||
|
||||
void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
|
||||
size_t size, bool require_guard_regions,
|
||||
void** allocation_base,
|
||||
size_t* allocation_length) {
|
||||
using AllocationStatus = WasmMemoryTracker::AllocationStatus;
|
||||
|
||||
#if V8_TARGET_ARCH_32_BIT
|
||||
DCHECK(!require_guard_regions);
|
||||
#endif
|
||||
@ -36,10 +39,12 @@ void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
|
||||
// Try up to three times; getting rid of dead JSArrayBuffer allocations might
|
||||
// require two GCs.
|
||||
// TODO(gc): Fix this to only require one GC (crbug.com/v8/7621).
|
||||
bool did_retry = false;
|
||||
for (int trial = 0;; ++trial) {
|
||||
if (memory_tracker->ReserveAddressSpace(*allocation_length)) break;
|
||||
// Collect garbage and retry.
|
||||
heap->MemoryPressureNotification(MemoryPressureLevel::kCritical, true);
|
||||
did_retry = true;
|
||||
// After first and second GC: retry.
|
||||
if (trial < 2) continue;
|
||||
// We are over the address space limit. Fail.
|
||||
@ -51,6 +56,8 @@ void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
|
||||
if (FLAG_abort_on_stack_or_string_length_overflow) {
|
||||
FATAL("could not allocate wasm memory");
|
||||
}
|
||||
memory_tracker->AddAllocationStatusSample(
|
||||
AllocationStatus::kAddressSpaceLimitReachedFailure);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -59,6 +66,7 @@ void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
|
||||
PageAllocator::kNoAccess);
|
||||
if (*allocation_base == nullptr) {
|
||||
memory_tracker->ReleaseReservation(*allocation_length);
|
||||
memory_tracker->AddAllocationStatusSample(AllocationStatus::kOtherFailure);
|
||||
return nullptr;
|
||||
}
|
||||
void* memory = *allocation_base;
|
||||
@ -71,6 +79,9 @@ void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
|
||||
|
||||
memory_tracker->RegisterAllocation(*allocation_base, *allocation_length,
|
||||
memory, size);
|
||||
memory_tracker->AddAllocationStatusSample(
|
||||
did_retry ? AllocationStatus::kSuccessAfterRetry
|
||||
: AllocationStatus::kSuccess);
|
||||
return memory;
|
||||
}
|
||||
} // namespace
|
||||
@ -126,6 +137,7 @@ void WasmMemoryTracker::RegisterAllocation(void* allocation_base,
|
||||
base::LockGuard<base::Mutex> scope_lock(&mutex_);
|
||||
|
||||
allocated_address_space_ += allocation_length;
|
||||
AddAddressSpaceSample();
|
||||
|
||||
allocations_.emplace(buffer_start,
|
||||
AllocationData{allocation_base, allocation_length,
|
||||
@ -153,6 +165,7 @@ WasmMemoryTracker::AllocationData WasmMemoryTracker::InternalReleaseAllocation(
|
||||
DCHECK_LE(num_bytes, allocated_address_space_);
|
||||
reserved_address_space_ -= num_bytes;
|
||||
allocated_address_space_ -= num_bytes;
|
||||
AddAddressSpaceSample();
|
||||
|
||||
AllocationData allocation_data = find_result->second;
|
||||
allocations_.erase(find_result);
|
||||
@ -216,6 +229,21 @@ bool WasmMemoryTracker::FreeMemoryIfIsWasmMemory(const void* buffer_start) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WasmMemoryTracker::AddAllocationStatusSample(AllocationStatus status) {
|
||||
if (allocation_result_) {
|
||||
allocation_result_->AddSample(static_cast<int>(status));
|
||||
}
|
||||
}
|
||||
|
||||
void WasmMemoryTracker::AddAddressSpaceSample() {
|
||||
if (address_space_usage_mb_) {
|
||||
// Report address space usage in MiB so the full range fits in an int on all
|
||||
// platforms.
|
||||
address_space_usage_mb_->AddSample(
|
||||
static_cast<int>(allocated_address_space_ >> 20));
|
||||
}
|
||||
}
|
||||
|
||||
Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store,
|
||||
size_t size, bool is_external,
|
||||
SharedFlag shared) {
|
||||
|
@ -14,6 +14,9 @@
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Histogram; // defined in counters.h
|
||||
|
||||
namespace wasm {
|
||||
|
||||
class WasmMemoryTracker {
|
||||
@ -82,8 +85,32 @@ class WasmMemoryTracker {
|
||||
// free the buffer manually.
|
||||
bool FreeMemoryIfIsWasmMemory(const void* buffer_start);
|
||||
|
||||
void SetAllocationResultHistogram(Histogram* allocation_result) {
|
||||
allocation_result_ = allocation_result;
|
||||
}
|
||||
void SetAddressSpaceUsageHistogram(Histogram* address_space_usage) {
|
||||
address_space_usage_mb_ = address_space_usage;
|
||||
}
|
||||
|
||||
// Allocation results are reported to UMA
|
||||
//
|
||||
// See wasm_memory_allocation_result in counters.h
|
||||
enum class AllocationStatus {
|
||||
kSuccess, // Succeeded on the first try
|
||||
|
||||
kSuccessAfterRetry, // Succeeded after garbage collection
|
||||
|
||||
kAddressSpaceLimitReachedFailure, // Failed because Wasm is at its address
|
||||
// space limit
|
||||
|
||||
kOtherFailure // Failed for an unknown reason
|
||||
};
|
||||
|
||||
void AddAllocationStatusSample(AllocationStatus status);
|
||||
|
||||
private:
|
||||
AllocationData InternalReleaseAllocation(const void* buffer_start);
|
||||
void AddAddressSpaceSample();
|
||||
|
||||
// Clients use a two-part process. First they "reserve" the address space,
|
||||
// which signifies an intent to actually allocate it. This determines whether
|
||||
@ -110,6 +137,10 @@ class WasmMemoryTracker {
|
||||
// shared backing store here.
|
||||
AllocationData empty_backing_store_;
|
||||
|
||||
// Keep pointers to
|
||||
Histogram* allocation_result_;
|
||||
Histogram* address_space_usage_mb_; // in MiB
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WasmMemoryTracker);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user