|
@@ -7,21 +7,31 @@
|
|
|
#include <algorithm>
|
|
|
#include <iostream>
|
|
|
#include <string>
|
|
|
+#include <utility>
|
|
|
+#include <vector>
|
|
|
|
|
|
+#include "atom/browser/browser.h"
|
|
|
#include "atom/common/api/locker.h"
|
|
|
#include "atom/common/application_info.h"
|
|
|
#include "atom/common/atom_version.h"
|
|
|
#include "atom/common/heap_snapshot.h"
|
|
|
#include "atom/common/native_mate_converters/file_path_converter.h"
|
|
|
#include "atom/common/native_mate_converters/string16_converter.h"
|
|
|
-#include "atom/common/node_includes.h"
|
|
|
+#include "atom/common/promise_util.h"
|
|
|
#include "base/logging.h"
|
|
|
+#include "base/process/process_handle.h"
|
|
|
#include "base/process/process_info.h"
|
|
|
#include "base/process/process_metrics_iocounters.h"
|
|
|
#include "base/sys_info.h"
|
|
|
#include "base/threading/thread_restrictions.h"
|
|
|
#include "chrome/common/chrome_version.h"
|
|
|
#include "native_mate/dictionary.h"
|
|
|
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
|
|
|
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
|
|
|
+
|
|
|
+// Must be the last in the includes list, otherwise the definition of chromium
|
|
|
+// macros conflicts with node macros.
|
|
|
+#include "atom/common/node_includes.h"
|
|
|
|
|
|
namespace atom {
|
|
|
|
|
@@ -61,6 +71,7 @@ void AtomBindings::BindTo(v8::Isolate* isolate, v8::Local<v8::Object> process) {
|
|
|
dict.SetMethod("getHeapStatistics", &GetHeapStatistics);
|
|
|
dict.SetMethod("getCreationTime", &GetCreationTime);
|
|
|
dict.SetMethod("getSystemMemoryInfo", &GetSystemMemoryInfo);
|
|
|
+ dict.SetMethod("getProcessMemoryInfo", &GetProcessMemoryInfo);
|
|
|
dict.SetMethod("getCPUUsage", base::Bind(&AtomBindings::GetCPUUsage,
|
|
|
base::Unretained(metrics_.get())));
|
|
|
dict.SetMethod("getIOCounters", &GetIOCounters);
|
|
@@ -208,6 +219,67 @@ v8::Local<v8::Value> AtomBindings::GetSystemMemoryInfo(v8::Isolate* isolate,
|
|
|
return dict.GetHandle();
|
|
|
}
|
|
|
|
|
|
+// static
|
|
|
+v8::Local<v8::Promise> AtomBindings::GetProcessMemoryInfo(
|
|
|
+ v8::Isolate* isolate) {
|
|
|
+ scoped_refptr<util::Promise> promise = new util::Promise(isolate);
|
|
|
+
|
|
|
+ if (mate::Locker::IsBrowserProcess() && !Browser::Get()->is_ready()) {
|
|
|
+ promise->RejectWithErrorMessage(
|
|
|
+ "Memory Info is available only after app ready");
|
|
|
+ return promise->GetHandle();
|
|
|
+ }
|
|
|
+
|
|
|
+ v8::Global<v8::Context> context(isolate, isolate->GetCurrentContext());
|
|
|
+ memory_instrumentation::MemoryInstrumentation::GetInstance()
|
|
|
+ ->RequestGlobalDumpForPid(base::GetCurrentProcId(),
|
|
|
+ std::vector<std::string>(),
|
|
|
+ base::Bind(&AtomBindings::DidReceiveMemoryDump,
|
|
|
+ std::move(context), promise));
|
|
|
+ return promise->GetHandle();
|
|
|
+}
|
|
|
+
|
|
|
+// static
|
|
|
+void AtomBindings::DidReceiveMemoryDump(
|
|
|
+ const v8::Global<v8::Context>& context,
|
|
|
+ scoped_refptr<util::Promise> promise,
|
|
|
+ bool success,
|
|
|
+ std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump) {
|
|
|
+ v8::Isolate* isolate = promise->isolate();
|
|
|
+ mate::Locker locker(isolate);
|
|
|
+ v8::HandleScope handle_scope(isolate);
|
|
|
+ v8::MicrotasksScope script_scope(isolate,
|
|
|
+ v8::MicrotasksScope::kRunMicrotasks);
|
|
|
+ v8::Context::Scope context_scope(
|
|
|
+ v8::Local<v8::Context>::New(isolate, context));
|
|
|
+
|
|
|
+ if (!success) {
|
|
|
+ promise->RejectWithErrorMessage("Failed to create memory dump");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool resolved = false;
|
|
|
+ for (const memory_instrumentation::GlobalMemoryDump::ProcessDump& dump :
|
|
|
+ global_dump->process_dumps()) {
|
|
|
+ if (base::GetCurrentProcId() == dump.pid()) {
|
|
|
+ mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
|
|
+ const auto& osdump = dump.os_dump();
|
|
|
+#if defined(OS_LINUX) || defined(OS_WIN)
|
|
|
+ dict.Set("residentSet", osdump.resident_set_kb);
|
|
|
+#endif
|
|
|
+ dict.Set("private", osdump.private_footprint_kb);
|
|
|
+ dict.Set("shared", osdump.shared_footprint_kb);
|
|
|
+ promise->Resolve(dict.GetHandle());
|
|
|
+ resolved = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!resolved) {
|
|
|
+ promise->RejectWithErrorMessage(
|
|
|
+ R"(Failed to find current process memory details in memory dump)");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// static
|
|
|
v8::Local<v8::Value> AtomBindings::GetCPUUsage(base::ProcessMetrics* metrics,
|
|
|
v8::Isolate* isolate) {
|