test_memory_utils.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. import ray
  2. from ray.dashboard.memory_utils import (
  3. ReferenceType,
  4. decode_object_ref_if_needed,
  5. MemoryTableEntry,
  6. MemoryTable,
  7. SortingType,
  8. )
  9. """Memory Table Unit Test"""
  10. NODE_ADDRESS = "127.0.0.1"
  11. IS_DRIVER = True
  12. PID = 1
  13. OBJECT_ID = "ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZg=="
  14. ACTOR_ID = "fffffffffffffffffffffffffffffffff66d17ba010000c801000000"
  15. DECODED_ID = decode_object_ref_if_needed(OBJECT_ID)
  16. OBJECT_SIZE = 100
  17. def build_memory_entry(
  18. *,
  19. local_ref_count,
  20. pinned_in_memory,
  21. submitted_task_reference_count,
  22. contained_in_owned,
  23. object_size,
  24. pid,
  25. object_id=OBJECT_ID,
  26. node_address=NODE_ADDRESS
  27. ):
  28. object_ref = {
  29. "objectId": object_id,
  30. "callSite": "(task call) /Users:458",
  31. "objectSize": object_size,
  32. "localRefCount": local_ref_count,
  33. "pinnedInMemory": pinned_in_memory,
  34. "submittedTaskRefCount": submitted_task_reference_count,
  35. "containedInOwned": contained_in_owned,
  36. }
  37. return MemoryTableEntry(
  38. object_ref=object_ref, node_address=node_address, is_driver=IS_DRIVER, pid=pid
  39. )
  40. def build_local_reference_entry(
  41. object_size=OBJECT_SIZE, pid=PID, node_address=NODE_ADDRESS
  42. ):
  43. return build_memory_entry(
  44. local_ref_count=1,
  45. pinned_in_memory=False,
  46. submitted_task_reference_count=0,
  47. contained_in_owned=[],
  48. object_size=object_size,
  49. pid=pid,
  50. node_address=node_address,
  51. )
  52. def build_used_by_pending_task_entry(
  53. object_size=OBJECT_SIZE, pid=PID, node_address=NODE_ADDRESS
  54. ):
  55. return build_memory_entry(
  56. local_ref_count=0,
  57. pinned_in_memory=False,
  58. submitted_task_reference_count=2,
  59. contained_in_owned=[],
  60. object_size=object_size,
  61. pid=pid,
  62. node_address=node_address,
  63. )
  64. def build_captured_in_object_entry(
  65. object_size=OBJECT_SIZE, pid=PID, node_address=NODE_ADDRESS
  66. ):
  67. return build_memory_entry(
  68. local_ref_count=0,
  69. pinned_in_memory=False,
  70. submitted_task_reference_count=0,
  71. contained_in_owned=[OBJECT_ID],
  72. object_size=object_size,
  73. pid=pid,
  74. node_address=node_address,
  75. )
  76. def build_actor_handle_entry(
  77. object_size=OBJECT_SIZE, pid=PID, node_address=NODE_ADDRESS
  78. ):
  79. return build_memory_entry(
  80. local_ref_count=1,
  81. pinned_in_memory=False,
  82. submitted_task_reference_count=0,
  83. contained_in_owned=[],
  84. object_size=object_size,
  85. pid=pid,
  86. node_address=node_address,
  87. object_id=ACTOR_ID,
  88. )
  89. def build_pinned_in_memory_entry(
  90. object_size=OBJECT_SIZE, pid=PID, node_address=NODE_ADDRESS
  91. ):
  92. return build_memory_entry(
  93. local_ref_count=0,
  94. pinned_in_memory=True,
  95. submitted_task_reference_count=0,
  96. contained_in_owned=[],
  97. object_size=object_size,
  98. pid=pid,
  99. node_address=node_address,
  100. )
  101. def build_entry(
  102. object_size=OBJECT_SIZE,
  103. pid=PID,
  104. node_address=NODE_ADDRESS,
  105. reference_type=ReferenceType.PINNED_IN_MEMORY,
  106. ):
  107. if reference_type == ReferenceType.USED_BY_PENDING_TASK:
  108. return build_used_by_pending_task_entry(
  109. pid=pid, object_size=object_size, node_address=node_address
  110. )
  111. elif reference_type == ReferenceType.LOCAL_REFERENCE:
  112. return build_local_reference_entry(
  113. pid=pid, object_size=object_size, node_address=node_address
  114. )
  115. elif reference_type == ReferenceType.PINNED_IN_MEMORY:
  116. return build_pinned_in_memory_entry(
  117. pid=pid, object_size=object_size, node_address=node_address
  118. )
  119. elif reference_type == ReferenceType.ACTOR_HANDLE:
  120. return build_actor_handle_entry(
  121. pid=pid, object_size=object_size, node_address=node_address
  122. )
  123. elif reference_type == ReferenceType.CAPTURED_IN_OBJECT:
  124. return build_captured_in_object_entry(
  125. pid=pid, object_size=object_size, node_address=node_address
  126. )
  127. def test_invalid_memory_entry():
  128. memory_entry = build_memory_entry(
  129. local_ref_count=0,
  130. pinned_in_memory=False,
  131. submitted_task_reference_count=0,
  132. contained_in_owned=[],
  133. object_size=OBJECT_SIZE,
  134. pid=PID,
  135. )
  136. assert memory_entry.is_valid() is False
  137. memory_entry = build_memory_entry(
  138. local_ref_count=0,
  139. pinned_in_memory=False,
  140. submitted_task_reference_count=0,
  141. contained_in_owned=[],
  142. object_size=-1,
  143. pid=PID,
  144. )
  145. assert memory_entry.is_valid() is False
  146. def test_valid_reference_memory_entry():
  147. memory_entry = build_local_reference_entry()
  148. assert memory_entry.reference_type == ReferenceType.LOCAL_REFERENCE
  149. assert memory_entry.object_ref == ray.ObjectRef(
  150. decode_object_ref_if_needed(OBJECT_ID)
  151. )
  152. assert memory_entry.is_valid() is True
  153. def test_reference_type():
  154. # pinned in memory
  155. memory_entry = build_pinned_in_memory_entry()
  156. assert memory_entry.reference_type == ReferenceType.PINNED_IN_MEMORY
  157. # used by pending task
  158. memory_entry = build_used_by_pending_task_entry()
  159. assert memory_entry.reference_type == ReferenceType.USED_BY_PENDING_TASK
  160. # captued in object
  161. memory_entry = build_captured_in_object_entry()
  162. assert memory_entry.reference_type == ReferenceType.CAPTURED_IN_OBJECT
  163. # actor handle
  164. memory_entry = build_actor_handle_entry()
  165. assert memory_entry.reference_type == ReferenceType.ACTOR_HANDLE
  166. def test_memory_table_summary():
  167. entries = [
  168. build_pinned_in_memory_entry(),
  169. build_used_by_pending_task_entry(),
  170. build_captured_in_object_entry(),
  171. build_actor_handle_entry(),
  172. build_local_reference_entry(),
  173. build_local_reference_entry(),
  174. ]
  175. memory_table = MemoryTable(entries)
  176. assert len(memory_table.group) == 1
  177. assert memory_table.summary["total_actor_handles"] == 1
  178. assert memory_table.summary["total_captured_in_objects"] == 1
  179. assert memory_table.summary["total_local_ref_count"] == 2
  180. assert memory_table.summary["total_object_size"] == len(entries) * OBJECT_SIZE
  181. assert memory_table.summary["total_pinned_in_memory"] == 1
  182. assert memory_table.summary["total_used_by_pending_task"] == 1
  183. def test_memory_table_sort_by_pid():
  184. unsort = [1, 3, 2]
  185. entries = [build_entry(pid=pid) for pid in unsort]
  186. memory_table = MemoryTable(entries, sort_by_type=SortingType.PID)
  187. sort = sorted(unsort)
  188. for pid, entry in zip(sort, memory_table.table):
  189. assert pid == entry.pid
  190. def test_memory_table_sort_by_reference_type():
  191. unsort = [
  192. ReferenceType.USED_BY_PENDING_TASK,
  193. ReferenceType.LOCAL_REFERENCE,
  194. ReferenceType.LOCAL_REFERENCE,
  195. ReferenceType.PINNED_IN_MEMORY,
  196. ]
  197. entries = [build_entry(reference_type=reference_type) for reference_type in unsort]
  198. memory_table = MemoryTable(entries, sort_by_type=SortingType.REFERENCE_TYPE)
  199. sort = sorted(unsort)
  200. for reference_type, entry in zip(sort, memory_table.table):
  201. assert reference_type == entry.reference_type
  202. def test_memory_table_sort_by_object_size():
  203. unsort = [312, 214, -1, 1244, 642]
  204. entries = [build_entry(object_size=object_size) for object_size in unsort]
  205. memory_table = MemoryTable(entries, sort_by_type=SortingType.OBJECT_SIZE)
  206. sort = sorted(unsort)
  207. for object_size, entry in zip(sort, memory_table.table):
  208. assert object_size == entry.object_size
  209. def test_group_by():
  210. node_second = "127.0.0.2"
  211. node_first = "127.0.0.1"
  212. entries = [
  213. build_entry(node_address=node_second, pid=2),
  214. build_entry(node_address=node_second, pid=1),
  215. build_entry(node_address=node_first, pid=2),
  216. build_entry(node_address=node_first, pid=1),
  217. ]
  218. memory_table = MemoryTable(entries)
  219. # Make sure it is correctly grouped
  220. assert node_first in memory_table.group
  221. assert node_second in memory_table.group
  222. # make sure pid is sorted in the right order.
  223. for group_key, group_memory_table in memory_table.group.items():
  224. pid = 1
  225. for entry in group_memory_table.table:
  226. assert pid == entry.pid
  227. pid += 1
  228. if __name__ == "__main__":
  229. import sys
  230. import pytest
  231. sys.exit(pytest.main(["-v", __file__]))