objectdb_profiler.rst 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. .. _doc_objectdb_profiler:
  2. Using the ObjectDB profiler
  3. ===========================
  4. Since Godot 4.6, there is a new **ObjectDB Profiler** tab in the Debugger bottom panel.
  5. This profiler allows you to take snapshots of the current state of the ObjectDB,
  6. which is the database that contains all the :ref:`class_object`-derived classes
  7. currently allocated in memory. This is useful for identifying memory leaks and
  8. understanding the memory usage of your project.
  9. Additionally, this tool is able to visualize differences between two snapshots.
  10. This can be used to identify improvements or regressions in memory usage after
  11. making changes to your project. Reducing memory usage can lead to better performance,
  12. even in cases where memory is not a bottleneck. By reducing memory usage,
  13. you can perform fewer allocations, which can be a costly operation, especially
  14. if performed in large amounts during gameplay.
  15. .. seealso::
  16. See :ref:`doc_node_alternatives` for information on using lighter-weight
  17. alternatives to nodes, which can help reduce memory usage in your project.
  18. .. warning::
  19. The ObjectDB profiler does **not** track every bit of memory used by the engine or
  20. by external libraries. Native engine classes that are not exposed to the scripting
  21. API will not appear in snapshots.
  22. Consider using external memory profiling tools if you need access to this information.
  23. Usage
  24. -----
  25. Open the ObjectDB Profiler tab in the :menu:`Debugger` bottom panel.
  26. You will land on the summary page with no snapshots taken yet.
  27. .. figure:: img/objectdb_profiler_summary_no_snapshots.webp
  28. :align: center
  29. :alt: ObjectDB profiler summary with no snapshots taken
  30. ObjectDB profiler summary with no snapshots taken
  31. Run the project, then get to a point where you'd like to take a snapshot
  32. (for example, after loading a level). Click :button:`Take ObjectDB Snapshot`
  33. to take a snapshot at the current point in time. If the button appears grayed out,
  34. make sure the project is running first.
  35. .. figure:: img/objectdb_profiler_summary_snapshot.webp
  36. :align: center
  37. :alt: ObjectDB profiler summary with one snapshot taken
  38. ObjectDB profiler summary with one snapshot taken
  39. You can take multiple snapshots during a single run of the project.
  40. Also, you can right-click a snapshot in the snapshot list to rename it,
  41. show it in the file manager, or delete it.
  42. .. tip::
  43. It's a good idea to rename snapshots
  44. after taking them to give them descriptive names (e.g., ``before_optimization``,
  45. ``after_optimization``). Regardless of the name, the date at which the snapshot
  46. was taken remains saved in the snapshot file itself.
  47. Snapshot files have a ``.odb_snapshot`` extension and are located in
  48. ``user://objectdb_snapshots/`` (see :ref:`Data paths <doc_data_paths_accessing_persistent_user_data>`
  49. details). These can safely be copied across devices, as they're platform-independent.
  50. Viewing differences between snapshots
  51. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  52. After taking at least two snapshots, the :menu:`Diff Against` dropdown becomes
  53. available. Here, you can select another snapshot to compare the currently selected
  54. snapshot with.
  55. .. figure:: img/objectdb_profiler_summary_diff_against.webp
  56. :align: center
  57. :alt: Diff Against dropdown in the bottom-left corner of the ObjectDB profiler
  58. Diff Against dropdown in the bottom-left corner of the ObjectDB profiler
  59. The summary page will then show the differences between the two snapshots:
  60. .. figure:: img/objectdb_profiler_summary_snapshot_diff.webp
  61. :align: center
  62. :alt: Two snapshots being compared in the Summary tab
  63. Two snapshots being compared in the Summary tab
  64. This also applies to every other tab in the ObjectDB profiler, which will show
  65. the differences between the two snapshots in additional columns.
  66. Classes
  67. ^^^^^^^
  68. In the Classes tab, you can view how many instances of each class have been
  69. created at the moment the snapshot was taken:
  70. .. figure:: img/objectdb_profiler_classes.webp
  71. :align: center
  72. :alt: One snapshots being viewed in the Classes tab
  73. One snapshots being viewed in the Classes tab
  74. When in diff mode, it will show the class instance count for the currently
  75. selected snapshot (column A) and the snapshot that is being diffed against
  76. (column B). It will also show the difference in instance count in the column Delta.
  77. .. figure:: img/objectdb_profiler_classes_diff.webp
  78. :align: center
  79. :alt: Two snapshots being compared in the Classes tab. Here, column A is ``second_session``, column B is ``first_session``
  80. Two snapshots being compared in the Classes tab. Here, column A is ``second_session``, column B is ``first_session``
  81. You can click on a class in the list on the right to view it in the inspector.
  82. .. figure:: img/objectdb_profiler_classes_inspector.webp
  83. :align: center
  84. :alt: A selected class instance being viewed in the inspector
  85. A selected class instance being viewed in the inspector
  86. .. tip::
  87. Previewing instances in the inspector is also available in other tabs
  88. (Nodes, Objects, and RefCounted).
  89. Objects
  90. ^^^^^^^
  91. The Objects tab is similar, but differs in the way it presents data. Here,
  92. every instance is listed in a linear fashion, instead of grouping them by class.
  93. When selecting an object, you will see a list of other objects it references
  94. on the right (:menu:`Outbound References`), as well as a list of objects
  95. it's being referenced by (:menu:`Inbound References`).
  96. This allows you to view objects either in a "top-down" manner (viewing
  97. what objects a given object references) or in a "bottom-up" manner (viewing
  98. what objects reference a given object).
  99. .. figure:: img/objectdb_profiler_objects_top_down.webp
  100. :align: center
  101. :alt: The Objects tab being used to view objects in a "top-down" manner
  102. The Objects tab being used to view objects in a "top-down" manner
  103. In the above image, clicking the ``default_font`` object in the list will
  104. switch the view to the perspective of that object. This object is being
  105. referenced by a lot of other objects as well, which effectively switches
  106. to a "bottom-up" perspective.
  107. .. figure:: img/objectdb_profiler_objects_bottom_up.webp
  108. :align: center
  109. :alt: The Objects tab being used to view objects in a "bottom-up" manner
  110. The Objects tab being used to view objects in a "bottom-up" manner
  111. Nodes
  112. ^^^^^
  113. Next, the Nodes tab shows the scene tree at the time the snapshot was taken.
  114. .. figure:: img/objectdb_profiler_nodes.webp
  115. :align: center
  116. :alt: The Nodes tab being used to view the scene tree
  117. The Nodes tab being used to view the scene tree
  118. This tab is particularly interesting in diff view, since it supports showing
  119. the difference between the two snapshots in a more visual manner.
  120. When :button:`Combined Diff` is unchecked, you can see the differences side by side.
  121. .. figure:: img/objectdb_profiler_nodes_diff_separate.webp
  122. :align: center
  123. :alt: Separate diff view in the Nodes tab
  124. Separate diff view in the Nodes tab
  125. When :button:`Combined Diff` is checked, you can see the differences merged
  126. into a single tree, with added nodes highlighted in green and removed nodes
  127. highlighted in red.
  128. .. figure:: img/objectdb_profiler_nodes_diff_combined.webp
  129. :align: center
  130. :alt: Combined diff view in the Nodes tab
  131. Combined diff view in the Nodes tab
  132. Additionally, you can view a list of orphan nodes (nodes that are not
  133. attached to the scene tree root) at the end of the tree view. You can view
  134. it more easily by collapsing the root node, since these are listed outside
  135. the main scene tree.
  136. .. figure:: img/objectdb_profiler_nodes_orphan.webp
  137. :align: center
  138. :alt: Orphan nodes at the end of the nodes tree in the ObjectDB profiler
  139. Orphan nodes at the end of the nodes tree in the ObjectDB profiler
  140. RefCounted
  141. ^^^^^^^^^^
  142. The last tab is the RefCounted tab. This tab is similar to the Objects
  143. tab, but it shows the reference counts of :ref:`class_refcounted`-derived
  144. classes directly in the table. The table has four columns:
  145. - **Native Refs:** The number of native engine references to the object.
  146. - **ObjectDB Refs:** The number of ObjectDB references to the object.
  147. - **Total Refs:** The sum of native references and ObjectDB references.
  148. - **ObjectDB Cycles:** The number of circular references detected.
  149. When in diff view, snapshot B is always listed *above* snapshot A
  150. if a RefCounted instance exists in both snapshots.
  151. The list on the right shows details on the selected instance,
  152. including a list of references and whether these are duplicates.
  153. .. figure:: img/objectdb_profiler_refcounted.webp
  154. :align: center
  155. :alt: The RefCounted tab being used to view RefCounted instances
  156. The RefCounted tab being used to view RefCounted instances
  157. .. note::
  158. The RefCounted tab does **not** list objects that derive directly from
  159. :ref:`class_object`, as these don't use reference counting.