process_node_impl_describer.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/performance_manager/graph/process_node_impl_describer.h"
  5. #include "base/i18n/time_formatting.h"
  6. #include "base/numerics/safe_conversions.h"
  7. #include "base/process/process.h"
  8. #include "base/process/process_handle.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "base/task/task_traits.h"
  13. #include "base/values.h"
  14. #include "build/build_config.h"
  15. #include "build/chromeos_buildflags.h"
  16. #include "components/performance_manager/public/graph/node_data_describer_registry.h"
  17. #include "components/performance_manager/public/graph/process_node.h"
  18. #include "content/public/common/child_process_host.h"
  19. #if BUILDFLAG(IS_WIN)
  20. #include "base/win/win_util.h"
  21. #endif
  22. namespace performance_manager {
  23. namespace {
  24. const char kDescriberName[] = "ProcessNodeImpl";
  25. std::string ContentTypeToString(ProcessNode::ContentType content_type) {
  26. switch (content_type) {
  27. case ProcessNode::ContentType::kExtension:
  28. return "Extension";
  29. case ProcessNode::ContentType::kMainFrame:
  30. return "Main frame";
  31. case ProcessNode::ContentType::kSubframe:
  32. return "Subframe";
  33. case ProcessNode::ContentType::kNavigatedFrame:
  34. return "Navigated Frame";
  35. case ProcessNode::ContentType::kAd:
  36. return "Ad";
  37. case ProcessNode::ContentType::kWorker:
  38. return "Worker";
  39. }
  40. }
  41. std::string HostedProcessTypesToString(
  42. ProcessNode::ContentTypes hosted_content_types) {
  43. std::vector<std::string> content_types_vector;
  44. content_types_vector.reserve(hosted_content_types.Size());
  45. for (ProcessNode::ContentType content_type : hosted_content_types)
  46. content_types_vector.push_back(ContentTypeToString(content_type));
  47. std::string str = base::JoinString(content_types_vector, ", ");
  48. if (str.empty())
  49. str = "none";
  50. return str;
  51. }
  52. base::Value GetProcessValueDict(const base::Process& process) {
  53. base::Value ret(base::Value::Type::DICTIONARY);
  54. // On Windows, handle is a void *. On Fuchsia it's an int. On other platforms
  55. // it is equal to the pid, so don't bother to record it.
  56. #if BUILDFLAG(IS_WIN)
  57. ret.SetIntKey("handle", base::win::HandleToUint32(process.Handle()));
  58. #elif BUILDFLAG(IS_FUCHSIA)
  59. ret.SetIntKey("handle", process.Handle());
  60. #endif
  61. // Most processes are not current, so only show the outliers.
  62. if (process.is_current()) {
  63. ret.SetBoolKey("is_current", true);
  64. }
  65. #if BUILDFLAG(IS_CHROMEOS_ASH)
  66. if (process.GetPidInNamespace() != base::kNullProcessId) {
  67. ret.SetIntKey("pid_in_namespace", process.GetPidInNamespace());
  68. }
  69. #endif
  70. #if BUILDFLAG(IS_WIN)
  71. // Creation time is always available on Windows, even for dead processes.
  72. // On other platforms it is available only for valid processes (see below).
  73. ret.SetStringKey("creation_time", base::TimeFormatTimeOfDayWithMilliseconds(
  74. process.CreationTime()));
  75. #endif
  76. if (process.IsValid()) {
  77. // These properties can only be accessed for valid processes.
  78. ret.SetIntKey("os_priority", process.GetPriority());
  79. #if !BUILDFLAG(IS_APPLE)
  80. ret.SetBoolKey("is_backgrounded", process.IsProcessBackgrounded());
  81. #endif
  82. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN)
  83. ret.SetStringKey("creation_time", base::TimeFormatTimeOfDayWithMilliseconds(
  84. process.CreationTime()));
  85. #endif
  86. #if BUILDFLAG(IS_WIN)
  87. // Most processes are running, so only show the outliers.
  88. if (!process.IsRunning()) {
  89. ret.SetBoolKey("is_running", false);
  90. }
  91. #endif
  92. } else {
  93. ret.SetBoolKey("is_valid", false);
  94. }
  95. return ret;
  96. }
  97. // Converts TimeTicks to Time. The conversion will be incorrect if system
  98. // time is adjusted between `ticks` and now.
  99. base::Time TicksToTime(base::TimeTicks ticks) {
  100. base::Time now_time = base::Time::Now();
  101. base::TimeTicks now_ticks = base::TimeTicks::Now();
  102. base::TimeDelta elapsed_since_ticks = now_ticks - ticks;
  103. return now_time - elapsed_since_ticks;
  104. }
  105. } // namespace
  106. void ProcessNodeImplDescriber::OnPassedToGraph(Graph* graph) {
  107. graph->GetNodeDataDescriberRegistry()->RegisterDescriber(this,
  108. kDescriberName);
  109. }
  110. void ProcessNodeImplDescriber::OnTakenFromGraph(Graph* graph) {
  111. graph->GetNodeDataDescriberRegistry()->UnregisterDescriber(this);
  112. }
  113. base::Value ProcessNodeImplDescriber::DescribeProcessNodeData(
  114. const ProcessNode* node) const {
  115. const ProcessNodeImpl* impl = ProcessNodeImpl::FromNode(node);
  116. base::Value ret(base::Value::Type::DICTIONARY);
  117. if (impl->private_footprint_kb()) {
  118. ret.SetIntKey("private_footprint_kb",
  119. base::saturated_cast<int>(impl->private_footprint_kb()));
  120. }
  121. if (impl->resident_set_kb()) {
  122. ret.SetIntKey("resident_set_kb",
  123. base::saturated_cast<int>(impl->resident_set_kb()));
  124. }
  125. constexpr RenderProcessHostId kInvalidRenderProcessHostId =
  126. RenderProcessHostId(content::ChildProcessHost::kInvalidUniqueID);
  127. if (impl->GetRenderProcessId() != kInvalidRenderProcessHostId) {
  128. ret.SetIntKey("render_process_id", impl->GetRenderProcessId().value());
  129. }
  130. // The content function returns "Tab" for renderers - whereas "Renderer" is
  131. // the common vernacular here.
  132. std::string process_type =
  133. content::GetProcessTypeNameInEnglish(impl->process_type());
  134. if (impl->process_type() == content::PROCESS_TYPE_RENDERER)
  135. process_type = "Renderer";
  136. ret.SetStringKey("process_type", process_type);
  137. ret.SetStringKey("pid", base::NumberToString(impl->process_id()));
  138. ret.SetKey("process", GetProcessValueDict(impl->process()));
  139. ret.SetStringKey("launch_time", base::TimeFormatTimeOfDayWithMilliseconds(
  140. TicksToTime(impl->launch_time())));
  141. if (impl->exit_status()) {
  142. ret.SetIntKey("exit_status", impl->exit_status().value());
  143. }
  144. if (!impl->metrics_name().empty()) {
  145. ret.SetStringKey("metrics_name", impl->metrics_name());
  146. }
  147. ret.SetBoolKey("main_thread_task_load_is_low",
  148. impl->main_thread_task_load_is_low());
  149. ret.SetStringKey("priority", base::TaskPriorityToString(impl->priority()));
  150. ret.SetStringKey("hosted_content_types",
  151. HostedProcessTypesToString(impl->hosted_content_types()));
  152. return ret;
  153. }
  154. } // namespace performance_manager