Commit 45dd38c1 authored by Eric Holk's avatar Eric Holk Committed by Commit Bot

[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: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52767}
parent 238dff26
......@@ -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);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment