| Index: content/renderer/v8_heap_statistics_collector_impl.cc
|
| diff --git a/content/renderer/v8_heap_statistics_collector_impl.cc b/content/renderer/v8_heap_statistics_collector_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..40c6bba5ee05478046c1513dc913366a7f034e09
|
| --- /dev/null
|
| +++ b/content/renderer/v8_heap_statistics_collector_impl.cc
|
| @@ -0,0 +1,115 @@
|
| +// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/renderer/v8_heap_statistics_collector_impl.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "content/renderer/render_thread_impl.h"
|
| +#include "v8/include/v8.h"
|
| +
|
| +namespace content {
|
| +
|
| +static const int kWaitForWorkersStatsTimeoutMS = 20;
|
| +
|
| +V8HeapStatisticsCollector* V8HeapStatisticsCollector::Instance() {
|
| + return V8HeapStatisticsCollectorImpl::Instance();
|
| +}
|
| +
|
| +V8HeapStatisticsCollector* V8HeapStatisticsCollectorImpl::Instance() {
|
| + CR_DEFINE_STATIC_LOCAL(V8HeapStatisticsCollectorImpl, instance, ());
|
| + return &instance;
|
| +}
|
| +
|
| +V8HeapStatisticsCollectorImpl::V8HeapStatisticsCollectorImpl()
|
| + : round_id_(0) {}
|
| +
|
| +V8HeapStatisticsCollectorImpl::~V8HeapStatisticsCollectorImpl() {
|
| +}
|
| +
|
| +bool V8HeapStatisticsCollectorImpl::InitiateCollection(
|
| + const ResultCallback& callback) {
|
| + DCHECK(RenderThreadImpl::Get());
|
| + if (pending_result_callback_)
|
| + return false;
|
| + pending_result_callback_.reset(new ResultCallback(callback));
|
| +
|
| + v8::HeapStatistics heap_stats;
|
| + v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats);
|
| + pending_stats_.total_bytes = heap_stats.total_heap_size();
|
| + pending_stats_.used_bytes = heap_stats.used_heap_size();
|
| + base::Closure collect = base::Bind(
|
| + &V8HeapStatisticsCollectorImpl::CollectOnWorkerThread,
|
| + base::Unretained(this),
|
| + base::MessageLoopProxy::current(),
|
| + round_id_);
|
| + workers_to_go_ = RenderThreadImpl::Get()->PostTaskToAllWebWorkers(collect);
|
| + if (workers_to_go_) {
|
| + // The guard task to send out partial stats
|
| + // in case some workers are not responsive.
|
| + base::MessageLoopProxy::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&V8HeapStatisticsCollectorImpl::SendStatsToCallback,
|
| + base::Unretained(this),
|
| + round_id_),
|
| + base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
|
| + } else {
|
| + // No worker threads so just send out the main thread data immediately, via
|
| + // a postTask so that the behavior of sync completion matches the
|
| + // asynchronous behavior.
|
| + base::MessageLoopProxy::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&V8HeapStatisticsCollectorImpl::SendStatsToCallback,
|
| + base::Unretained(this),
|
| + round_id_));
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void V8HeapStatisticsCollectorImpl::CollectOnWorkerThread(
|
| + scoped_refptr<base::TaskRunner> master,
|
| + int round_id) {
|
| +
|
| + size_t total_bytes = 0;
|
| + size_t used_bytes = 0;
|
| + v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| + if (isolate) {
|
| + v8::HeapStatistics heap_stats;
|
| + isolate->GetHeapStatistics(&heap_stats);
|
| + total_bytes = heap_stats.total_heap_size();
|
| + used_bytes = heap_stats.used_heap_size();
|
| + }
|
| + master->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&V8HeapStatisticsCollectorImpl::ReceiveStats,
|
| + base::Unretained(this),
|
| + round_id,
|
| + total_bytes,
|
| + used_bytes));
|
| +}
|
| +
|
| +void V8HeapStatisticsCollectorImpl::ReceiveStats(int round_id,
|
| + size_t total_bytes,
|
| + size_t used_bytes) {
|
| + if (round_id != round_id_)
|
| + return;
|
| + pending_stats_.total_bytes += total_bytes;
|
| + pending_stats_.used_bytes += used_bytes;
|
| + if (!--workers_to_go_)
|
| + SendStatsToCallback(round_id);
|
| +}
|
| +
|
| +void V8HeapStatisticsCollectorImpl::SendStatsToCallback(int round_id) {
|
| + if (round_id != round_id_)
|
| + return;
|
| +
|
| + // TODO(alph): Do caching heap stats and use the cache if we haven't got
|
| + // reply from a worker.
|
| + // Currently a busy worker stats are not counted.
|
| + pending_result_callback_->Run(pending_stats_);
|
| + pending_result_callback_.reset();
|
| + ++round_id_;
|
| +}
|
| +
|
| +} // namespace content
|
|
|