[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:
Eric Holk 2018-04-24 10:28:07 -07:00 committed by Commit Bot
parent 238dff2664
commit 45dd38c167
4 changed files with 67 additions and 1 deletions

View File

@ -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. */ \

View File

@ -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, ...) \

View File

@ -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) {

View File

@ -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);
};