ruby_memprofiler_pprof 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ruby_memprofiler_pprof_ext/collector.c +803 -0
  3. data/ext/ruby_memprofiler_pprof_ext/compat.c +184 -0
  4. data/ext/ruby_memprofiler_pprof_ext/compile_commands.json +1 -0
  5. data/ext/ruby_memprofiler_pprof_ext/extconf.rb +152 -0
  6. data/ext/ruby_memprofiler_pprof_ext/pprof.upb.c +199 -0
  7. data/ext/ruby_memprofiler_pprof_ext/pprof.upb.h +924 -0
  8. data/ext/ruby_memprofiler_pprof_ext/pprof_out.c +430 -0
  9. data/ext/ruby_memprofiler_pprof_ext/ruby_hacks.c +118 -0
  10. data/ext/ruby_memprofiler_pprof_ext/ruby_memprofiler_pprof.c +10 -0
  11. data/ext/ruby_memprofiler_pprof_ext/ruby_memprofiler_pprof.h +183 -0
  12. data/ext/ruby_memprofiler_pprof_ext/ruby_private/ruby26/gc_private.h +324 -0
  13. data/ext/ruby_memprofiler_pprof_ext/ruby_private/ruby27/gc_private.h +339 -0
  14. data/ext/ruby_memprofiler_pprof_ext/ruby_private/ruby30/gc_private.h +361 -0
  15. data/ext/ruby_memprofiler_pprof_ext/ruby_private/ruby31/gc_private.h +374 -0
  16. data/ext/ruby_memprofiler_pprof_ext/ruby_private.h +31 -0
  17. data/ext/ruby_memprofiler_pprof_ext/sample.c +43 -0
  18. data/ext/ruby_memprofiler_pprof_ext/vendor/backtracie/backtracie.h +268 -0
  19. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/BUILD +0 -0
  20. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/CONTRIBUTING.md +0 -0
  21. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/DESIGN.md +0 -0
  22. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/LICENSE +0 -0
  23. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/README.md +0 -0
  24. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/WORKSPACE +0 -0
  25. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/BUILD +0 -0
  26. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/amalgamate.py +0 -0
  27. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/build_defs.bzl +0 -0
  28. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/lua.BUILD +0 -0
  29. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/protobuf.patch +0 -0
  30. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/py_proto_library.bzl +0 -0
  31. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/python_downloads.bzl +0 -0
  32. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/system_python.bzl +0 -0
  33. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/upb_proto_library.bzl +0 -0
  34. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/bazel/workspace_deps.bzl +0 -0
  35. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/BUILD +0 -0
  36. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/BUILD.googleapis +0 -0
  37. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/benchmark.cc +0 -0
  38. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/build_defs.bzl +0 -0
  39. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/compare.py +0 -0
  40. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/descriptor.proto +0 -0
  41. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/descriptor_sv.proto +0 -0
  42. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/empty.proto +0 -0
  43. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/gen_protobuf_binary_cc.py +0 -0
  44. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/gen_synthetic_protos.py +0 -0
  45. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/benchmarks/gen_upb_binary_c.py +0 -0
  46. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/cmake/BUILD.bazel +0 -0
  47. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/cmake/README.md +0 -0
  48. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/cmake/build_defs.bzl +0 -0
  49. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/cmake/make_cmakelists.py +0 -0
  50. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/cmake/staleness_test.py +0 -0
  51. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/cmake/staleness_test_lib.py +0 -0
  52. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/docs/render.py +0 -0
  53. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/docs/style-guide.md +0 -0
  54. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/docs/vs-cpp-protos.md +0 -0
  55. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/docs/wrapping-upb.md +0 -0
  56. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/BUILD +0 -0
  57. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/convert.c +0 -0
  58. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/convert.h +0 -0
  59. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/descriptor.c +0 -0
  60. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/descriptor.h +0 -0
  61. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/descriptor_containers.c +0 -0
  62. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/descriptor_containers.h +0 -0
  63. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/descriptor_pool.c +0 -0
  64. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/descriptor_pool.h +0 -0
  65. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/dist/BUILD.bazel +0 -0
  66. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/dist/dist.bzl +0 -0
  67. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/extension_dict.c +0 -0
  68. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/extension_dict.h +0 -0
  69. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/map.c +0 -0
  70. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/map.h +0 -0
  71. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/message.c +0 -0
  72. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/message.h +0 -0
  73. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/minimal_test.py +0 -0
  74. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/BUILD +0 -0
  75. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/README.md +0 -0
  76. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/descriptor_database_test_wrapper.py +0 -0
  77. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/descriptor_pool_test_wrapper.py +0 -0
  78. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/descriptor_test_wrapper.py +0 -0
  79. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/generator_test_wrapper.py +0 -0
  80. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/json_format_test_wrapper.py +0 -0
  81. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/keywords_test_wrapper.py +0 -0
  82. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/message_factory_test_wrapper.py +0 -0
  83. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/message_test_wrapper.py +0 -0
  84. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/proto_builder_test_wrapper.py +0 -0
  85. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/pyproto_test_wrapper.bzl +0 -0
  86. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/reflection_test_wrapper.py +0 -0
  87. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/service_reflection_test_wrapper.py +0 -0
  88. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/symbol_database_test_wrapper.py +0 -0
  89. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/text_encoding_test_wrapper.py +0 -0
  90. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/text_format_test_wrapper.py +0 -0
  91. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/unknown_fields_test_wrapper.py +0 -0
  92. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/well_known_types_test_wrapper.py +0 -0
  93. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/pb_unit_tests/wire_format_test_wrapper.py +0 -0
  94. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/protobuf.c +0 -0
  95. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/protobuf.h +0 -0
  96. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/py_extension.bzl +0 -0
  97. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/python_api.h +0 -0
  98. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/repeated.c +0 -0
  99. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/repeated.h +0 -0
  100. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/unknown_fields.c +0 -0
  101. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/unknown_fields.h +0 -0
  102. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/python/version_script.lds +0 -0
  103. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/lunit/LICENSE +0 -0
  104. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/lunit/README.google +0 -0
  105. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/lunit/console.lua +0 -0
  106. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/lunit/lunit.lua +0 -0
  107. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/utf8_range/BUILD +0 -0
  108. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/utf8_range/LICENSE +0 -0
  109. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/utf8_range/naive.c +0 -0
  110. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/utf8_range/range2-neon.c +0 -0
  111. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/utf8_range/range2-sse.c +0 -0
  112. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/third_party/utf8_range/utf8_range.h +0 -0
  113. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/BUILD.bazel +0 -0
  114. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/README.md +0 -0
  115. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/def.c +0 -0
  116. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/lua_proto_library.bzl +0 -0
  117. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/main.c +0 -0
  118. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/msg.c +0 -0
  119. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/test.proto +0 -0
  120. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/test_upb.lua +0 -0
  121. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/upb.c +0 -0
  122. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/upb.h +0 -0
  123. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/upb.lua +0 -0
  124. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/bindings/lua/upbc.cc +0 -0
  125. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/collections.c +0 -0
  126. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/collections.h +0 -0
  127. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/conformance_upb.c +0 -0
  128. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/conformance_upb_failures.txt +0 -0
  129. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/decode.c +0 -0
  130. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/decode.h +0 -0
  131. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/decode_fast.c +0 -0
  132. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/decode_fast.h +0 -0
  133. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/decode_internal.h +0 -0
  134. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/def.c +0 -0
  135. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/def.h +0 -0
  136. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/def.hpp +0 -0
  137. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/empty.proto +0 -0
  138. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/encode.c +0 -0
  139. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/encode.h +0 -0
  140. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/fuzz/BUILD +0 -0
  141. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/fuzz/file_descriptor_parsenew_fuzzer.cc +0 -0
  142. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/json_decode.c +0 -0
  143. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/json_decode.h +0 -0
  144. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/json_encode.c +0 -0
  145. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/json_encode.h +0 -0
  146. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table.c +0 -0
  147. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table.h +0 -0
  148. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table.hpp +0 -0
  149. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table_accessors.c +0 -0
  150. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table_accessors.h +0 -0
  151. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table_accessors_internal.h +0 -0
  152. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table_accessors_test.cc +0 -0
  153. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/mini_table_test.cc +0 -0
  154. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/msg.c +0 -0
  155. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/msg.h +0 -0
  156. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/msg_internal.h +0 -0
  157. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/msg_test.cc +0 -0
  158. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/msg_test.proto +0 -0
  159. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/port_def.inc +0 -0
  160. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/port_undef.inc +0 -0
  161. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/reflection.c +0 -0
  162. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/reflection.h +0 -0
  163. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/reflection.hpp +0 -0
  164. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/table.c +0 -0
  165. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/table_internal.h +0 -0
  166. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/test.proto +0 -0
  167. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/test_cpp.cc +0 -0
  168. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/test_cpp.proto +0 -0
  169. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/test_generated_code.cc +0 -0
  170. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/test_table.cc +0 -0
  171. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/text_encode.c +0 -0
  172. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/text_encode.h +0 -0
  173. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/upb.c +0 -0
  174. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/upb.h +0 -0
  175. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/upb.hpp +0 -0
  176. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/upb_internal.h +0 -0
  177. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/BUILD +0 -0
  178. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/README.md +0 -0
  179. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/compare.c +0 -0
  180. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/compare.h +0 -0
  181. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/compare_test.cc +0 -0
  182. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto.c +0 -0
  183. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto.h +0 -0
  184. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto_public_import_test.proto +0 -0
  185. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto_regular_import_test.proto +0 -0
  186. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto_test.cc +0 -0
  187. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto_test.proto +0 -0
  188. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto_weak_import_test.proto +0 -0
  189. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/def_to_proto_wweak_import_test.proto +0 -0
  190. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/required_fields.c +0 -0
  191. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/required_fields.h +0 -0
  192. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/required_fields_test.cc +0 -0
  193. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upb/util/required_fields_test.proto +0 -0
  194. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upbc/BUILD +0 -0
  195. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upbc/common.cc +0 -0
  196. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upbc/common.h +0 -0
  197. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upbc/protoc-gen-upb.cc +0 -0
  198. data/ext/{ruby_memprofiler_pprof → ruby_memprofiler_pprof_ext}/vendor/upb/upbc/protoc-gen-upbdefs.cc +0 -0
  199. data/lib/ruby_memprofiler_pprof/atfork.rb +1 -1
  200. data/lib/ruby_memprofiler_pprof/block_flusher.rb +48 -4
  201. data/lib/ruby_memprofiler_pprof/file_flusher.rb +13 -6
  202. data/lib/ruby_memprofiler_pprof/profile_app.rb +8 -12
  203. data/lib/ruby_memprofiler_pprof/profile_data.rb +7 -8
  204. data/lib/ruby_memprofiler_pprof/version.rb +1 -1
  205. data/lib/ruby_memprofiler_pprof.rb +5 -4
  206. data/libexec/ruby_memprofiler_pprof_profile +6 -6
  207. metadata +207 -200
  208. data/ext/ruby_memprofiler_pprof/backtrace.c +0 -429
  209. data/ext/ruby_memprofiler_pprof/collector.c +0 -1055
  210. data/ext/ruby_memprofiler_pprof/compat.c +0 -182
  211. data/ext/ruby_memprofiler_pprof/extconf.rb +0 -72
  212. data/ext/ruby_memprofiler_pprof/pprof.upb.c +0 -170
  213. data/ext/ruby_memprofiler_pprof/pprof.upb.h +0 -848
  214. data/ext/ruby_memprofiler_pprof/pprof_out.c +0 -285
  215. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.c +0 -11
  216. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.h +0 -301
  217. data/ext/ruby_memprofiler_pprof/strtab.c +0 -391
@@ -0,0 +1,430 @@
1
+ #include <ruby.h>
2
+ #include <ruby/st.h>
3
+ #include <zlib.h>
4
+
5
+ #include "pprof.upb.h"
6
+ #include "ruby/st.h"
7
+ #include "ruby_memprofiler_pprof.h"
8
+ #include "upb/upb.h"
9
+
10
+ #define CHECK_IF_INTERRUPTED(action) \
11
+ do { \
12
+ uint8_t interrupted; \
13
+ __atomic_load(&ctx->interrupt, &interrupted, __ATOMIC_SEQ_CST); \
14
+ if (interrupted) { \
15
+ snprintf(errbuf, errbuflen, "interrupted"); \
16
+ action; \
17
+ } \
18
+ } while (0);
19
+
20
+ // allocator/free function for our upb_arena. Contract is:
21
+ // If "size" is 0 then the function acts like free(), otherwise it acts like
22
+ // realloc(). Only "oldsize" bytes from a previous allocation are preserved.
23
+ static void *mpp_pprof_upb_arena_malloc(upb_alloc *alloc, void *ptr, size_t oldsize, size_t size) {
24
+ if (size == 0) {
25
+ mpp_free(ptr);
26
+ return NULL;
27
+ } else {
28
+ return mpp_realloc(ptr, size);
29
+ }
30
+ }
31
+
32
+ // Methods for a hash of (function ID, line number) -> (location)
33
+ // Needed because we have to intern a given function:line to a consistent location ID as per
34
+ // the protobuf spec.
35
+ // Key is a uint64_t[2].
36
+ static int intpair_st_hash_compare(st_data_t arg1, st_data_t arg2) {
37
+ uint64_t *k1 = (uint64_t *)arg1;
38
+ uint64_t *k2 = (uint64_t *)arg2;
39
+
40
+ if (k1[0] != k2[0]) {
41
+ return k1[0] < k2[0];
42
+ } else {
43
+ return k1[1] < k2[1];
44
+ }
45
+ }
46
+
47
+ // I copied this magic number out of st.c from Ruby.
48
+ #define FNV1_32A_INIT 0x811c9dc5
49
+
50
+ static st_index_t intpair_st_hash_hash(st_data_t arg) {
51
+ uint64_t *k = (uint64_t *)arg;
52
+ return st_hash(k, 2 * sizeof(uint64_t), FNV1_32A_INIT);
53
+ }
54
+
55
+ static const struct st_hash_type intpair_st_hash_type = {
56
+ .compare = intpair_st_hash_compare,
57
+ .hash = intpair_st_hash_hash,
58
+ };
59
+
60
+ // Methods for a hash of (string, len) -> (string tab index)
61
+ struct str_st_hash_key {
62
+ const char *str;
63
+ size_t str_len;
64
+ };
65
+
66
+ static int str_st_hash_compare(st_data_t arg1, st_data_t arg2) {
67
+ struct str_st_hash_key *k1 = (struct str_st_hash_key *)arg1;
68
+ struct str_st_hash_key *k2 = (struct str_st_hash_key *)arg2;
69
+
70
+ size_t smaller_len = (k1->str_len > k2->str_len) ? k2->str_len : k1->str_len;
71
+ int cmp = memcmp(k1->str, k2->str, smaller_len);
72
+
73
+ if (cmp != 0 || k1->str_len == k2->str_len) {
74
+ // Either: one of the first smaller_len bytes were different, or
75
+ // they were the same, AND the lenghts are the same, which make them the same string.
76
+ return cmp;
77
+ }
78
+ // The first smaller_len bytes are the same, but one is longer than the other.
79
+ // The shorter string should be considered smaller.
80
+ return k1->str_len > k2->str_len ? 1 : -1;
81
+ }
82
+
83
+ static st_index_t str_st_hash_hash(st_data_t arg) {
84
+ struct str_st_hash_key *k = (struct str_st_hash_key *)arg;
85
+ return st_hash(k->str, k->str_len, FNV1_32A_INIT);
86
+ }
87
+
88
+ static const struct st_hash_type str_st_hash_type = {
89
+ .compare = str_st_hash_compare,
90
+ .hash = str_st_hash_hash,
91
+ };
92
+
93
+ struct intern_string_hash_update_ctx {
94
+ struct mpp_pprof_serctx *serctx;
95
+ bool copy;
96
+ bool did_retain_out;
97
+ int index_out;
98
+ };
99
+
100
+ static int intern_string_hash_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing) {
101
+ struct intern_string_hash_update_ctx *ctx = (struct intern_string_hash_update_ctx *)arg;
102
+ if (existing) {
103
+ // Value was already in the hash; just return its existing index.
104
+ ctx->index_out = *value;
105
+ } else {
106
+ struct mpp_pprof_serctx *serctx = ctx->serctx;
107
+ bool copy = ctx->copy;
108
+ upb_Arena *arena = serctx->arena;
109
+ // Value NOT already in the hash. We need to add it.
110
+ // Need to actually create a new *key; the one passed into st_update is a stack pointer, which won't be valid after
111
+ // intern_string returns.
112
+ struct str_st_hash_key *new_key = upb_Arena_Malloc(arena, sizeof(struct str_st_hash_key));
113
+ struct str_st_hash_key *old_key = (struct str_st_hash_key *)*key;
114
+ const char *old_str = old_key->str;
115
+ size_t old_str_len = old_key->str_len;
116
+ // May also need to copy the string, if it's not already a pointer to the arena.
117
+ if (copy) {
118
+ char *new_str = upb_Arena_Malloc(arena, old_str_len + 1);
119
+ memcpy(new_str, old_str, old_str_len);
120
+ new_str[old_str_len] = '\0';
121
+ new_key->str = new_str;
122
+ } else {
123
+ new_key->str = old_str;
124
+ ctx->did_retain_out = true;
125
+ }
126
+ new_key->str_len = old_str_len;
127
+ *key = (st_data_t)new_key;
128
+
129
+ // Now increment the value
130
+ *value = serctx->strings_counter++;
131
+ ctx->index_out = *value;
132
+ }
133
+ return ST_CONTINUE;
134
+ }
135
+
136
+ static int intern_string(struct mpp_pprof_serctx *serctx, const char *str, size_t len) {
137
+ struct str_st_hash_key key = {.str = str, .str_len = len};
138
+ struct intern_string_hash_update_ctx ctx = {.serctx = serctx, .index_out = 0, .copy = true};
139
+ st_update(serctx->strings, (st_data_t)&key, intern_string_hash_update, (st_data_t)&ctx);
140
+ return ctx.index_out;
141
+ }
142
+
143
+ static int intern_scratch_buffer(struct mpp_pprof_serctx *serctx) {
144
+ // If the string length is larger than the buffer capacity, clamp to capacity.
145
+ // ->scratch_buffer_capa gets set as the return value of backtracie_*_cstr, which returns the number
146
+ // of bytes that _would_ be needed to store the whole output.
147
+ size_t str_len = serctx->scratch_buffer_strlen;
148
+ if (str_len >= serctx->scratch_buffer_capa) {
149
+ str_len = serctx->scratch_buffer_capa - 1;
150
+ }
151
+ struct str_st_hash_key key = {.str = serctx->scratch_buffer, .str_len = str_len};
152
+ struct intern_string_hash_update_ctx ctx = {.serctx = serctx, .index_out = 0, .copy = false, .did_retain_out = false};
153
+ st_update(serctx->strings, (st_data_t)&key, intern_string_hash_update, (st_data_t)&ctx);
154
+ if (ctx.did_retain_out) {
155
+ serctx->scratch_buffer = NULL;
156
+ serctx->scratch_buffer_capa = 0;
157
+ serctx->scratch_buffer_strlen = 0;
158
+ }
159
+ return ctx.index_out;
160
+ }
161
+
162
+ static void ensure_scratch_buffer(struct mpp_pprof_serctx *serctx) {
163
+ if (!serctx->scratch_buffer) {
164
+ serctx->scratch_buffer = upb_Arena_Malloc(serctx->arena, 256);
165
+ serctx->scratch_buffer_capa = 256;
166
+ serctx->scratch_buffer_strlen = 0;
167
+ }
168
+ }
169
+
170
+ // Initialize an already-allocated serialization context.
171
+ struct mpp_pprof_serctx *mpp_pprof_serctx_new(char *errbuf, size_t errbuflen) {
172
+ struct mpp_pprof_serctx *ctx = mpp_xmalloc(sizeof(struct mpp_pprof_serctx));
173
+ ctx->allocator.func = mpp_pprof_upb_arena_malloc;
174
+ ctx->arena = upb_Arena_Init(NULL, 0, &ctx->allocator);
175
+ ctx->profile_proto = perftools_profiles_Profile_new(ctx->arena);
176
+ ctx->function_pbs = st_init_numtable();
177
+ ctx->location_pbs = st_init_table(&intpair_st_hash_type);
178
+ ctx->function_ids = st_init_table(&intpair_st_hash_type);
179
+ ctx->strings = st_init_table(&str_st_hash_type);
180
+ ctx->loc_counter = 1;
181
+ ctx->function_id_counter = 1;
182
+ ctx->strings_counter = 0;
183
+ ctx->interrupt = 0;
184
+ ctx->scratch_buffer = NULL;
185
+ ctx->scratch_buffer_capa = 0;
186
+ ctx->scratch_buffer_strlen = 0;
187
+
188
+ // Pprof requires that "" be interned at position 0 in the string table, so intern that now.
189
+ intern_string(ctx, "", 0);
190
+
191
+ // Set up the sample types etc.
192
+ perftools_profiles_ValueType *retained_objects_vt =
193
+ perftools_profiles_Profile_add_sample_type(ctx->profile_proto, ctx->arena);
194
+ perftools_profiles_ValueType_set_type(retained_objects_vt,
195
+ intern_string(ctx, "retained_objects", strlen("retained_objects")));
196
+ perftools_profiles_ValueType_set_unit(retained_objects_vt, intern_string(ctx, "count", strlen("count")));
197
+ perftools_profiles_ValueType *retained_size_vt =
198
+ perftools_profiles_Profile_add_sample_type(ctx->profile_proto, ctx->arena);
199
+ perftools_profiles_ValueType_set_type(retained_size_vt, intern_string(ctx, "retained_size", strlen("retained_size")));
200
+ perftools_profiles_ValueType_set_unit(retained_size_vt, intern_string(ctx, "bytes", strlen("bytes")));
201
+
202
+ return ctx;
203
+ }
204
+
205
+ // Destroys the serialization context. After this call, any stringtab indexes it held
206
+ // are released, and any memory from its internal state is freed. *ctx itself is also
207
+ // freed and must not be dereferenced after this.
208
+ void mpp_pprof_serctx_destroy(struct mpp_pprof_serctx *ctx) {
209
+ if (ctx->function_pbs) {
210
+ st_free_table(ctx->function_pbs);
211
+ }
212
+ if (ctx->location_pbs) {
213
+ st_free_table(ctx->location_pbs);
214
+ }
215
+ if (ctx->function_ids) {
216
+ st_free_table(ctx->function_ids);
217
+ }
218
+ if (ctx->strings) {
219
+ st_free_table(ctx->strings);
220
+ }
221
+ upb_Arena_Free(ctx->arena);
222
+ mpp_free(ctx);
223
+ }
224
+
225
+ struct mpp_pprof_serctx_map_add_ctx {
226
+ struct mpp_pprof_serctx *ctx;
227
+ int is_error;
228
+ char *errbuf;
229
+ size_t errbuflen;
230
+
231
+ int function_name;
232
+ int file_name;
233
+ unsigned long function_id;
234
+
235
+ // for add_location
236
+ int line_number;
237
+ unsigned long location_id_out;
238
+ };
239
+
240
+ static int mpp_pprof_serctx_add_function(st_data_t *key, st_data_t *value, st_data_t data, int existing) {
241
+ if (*value) {
242
+ // already exists in the map, don't create it again.
243
+ return ST_CONTINUE;
244
+ }
245
+
246
+ struct mpp_pprof_serctx_map_add_ctx *thunkctx = (struct mpp_pprof_serctx_map_add_ctx *)data;
247
+ struct perftools_profiles_Function *fn_proto =
248
+ perftools_profiles_Profile_add_function(thunkctx->ctx->profile_proto, thunkctx->ctx->arena);
249
+
250
+ perftools_profiles_Function_set_id(fn_proto, thunkctx->function_id);
251
+
252
+ perftools_profiles_Function_set_name(fn_proto, thunkctx->function_name);
253
+ perftools_profiles_Function_set_system_name(fn_proto, thunkctx->function_name);
254
+ perftools_profiles_Function_set_filename(fn_proto, thunkctx->file_name);
255
+
256
+ *value = (st_data_t)fn_proto;
257
+ return ST_CONTINUE;
258
+ }
259
+
260
+ static int mpp_pprof_serctx_add_location(st_data_t *key, st_data_t *value, st_data_t data, int existing) {
261
+ struct mpp_pprof_serctx_map_add_ctx *thunkctx = (struct mpp_pprof_serctx_map_add_ctx *)data;
262
+ if (*value) {
263
+ // already exists in the map, don't create it again.
264
+ struct perftools_profiles_Location *existing_loc = (struct perftools_profiles_Location *)(*value);
265
+ thunkctx->location_id_out = perftools_profiles_Location_id(existing_loc);
266
+ return ST_CONTINUE;
267
+ }
268
+
269
+ struct perftools_profiles_Location *loc_proto =
270
+ perftools_profiles_Profile_add_location(thunkctx->ctx->profile_proto, thunkctx->ctx->arena);
271
+
272
+ perftools_profiles_Location_set_id(loc_proto, thunkctx->ctx->loc_counter++);
273
+ perftools_profiles_Line *line_proto = perftools_profiles_Location_add_line(loc_proto, thunkctx->ctx->arena);
274
+ perftools_profiles_Line_set_function_id(line_proto, thunkctx->function_id);
275
+ perftools_profiles_Line_set_line(line_proto, (int64_t)thunkctx->line_number);
276
+
277
+ thunkctx->location_id_out = perftools_profiles_Location_id(loc_proto);
278
+ *value = (st_data_t)loc_proto;
279
+ return ST_CONTINUE;
280
+ }
281
+
282
+ static int function_id_update_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing) {
283
+ struct mpp_pprof_serctx_map_add_ctx *thunkctx = (struct mpp_pprof_serctx_map_add_ctx *)arg;
284
+ if (!existing) {
285
+ *value = thunkctx->ctx->function_id_counter++;
286
+ }
287
+ thunkctx->function_id = *value;
288
+ return ST_CONTINUE;
289
+ }
290
+
291
+ int mpp_pprof_serctx_add_sample(struct mpp_pprof_serctx *ctx, struct mpp_sample *sample, char *errbuf,
292
+ size_t errbuflen) {
293
+ CHECK_IF_INTERRUPTED(return -1);
294
+
295
+ size_t frames_count = sample->frames_count;
296
+ perftools_profiles_Sample *sample_proto = perftools_profiles_Profile_add_sample(ctx->profile_proto, ctx->arena);
297
+ uint64_t *location_ids = perftools_profiles_Sample_resize_location_id(sample_proto, frames_count, ctx->arena);
298
+
299
+ // Protobuf needs to be in most-recent-call-first, and backtracie is also in that order.
300
+ for (size_t i = 0; i < frames_count; i++) {
301
+ // Create protobufs for function/location ID as needed.
302
+ struct mpp_pprof_serctx_map_add_ctx thunkctx;
303
+ thunkctx.ctx = ctx;
304
+ thunkctx.errbuf = errbuf;
305
+ thunkctx.errbuflen = errbuflen;
306
+ thunkctx.is_error = 0;
307
+ thunkctx.location_id_out = 0;
308
+
309
+ // Intern the frame names & filenames.
310
+ ensure_scratch_buffer(ctx);
311
+ ctx->scratch_buffer_strlen =
312
+ mpp_sample_frame_function_name(sample, i, ctx->scratch_buffer, ctx->scratch_buffer_capa);
313
+ thunkctx.function_name = intern_scratch_buffer(ctx);
314
+
315
+ ensure_scratch_buffer(ctx);
316
+ ctx->scratch_buffer_strlen = mpp_sample_frame_file_name(sample, i, ctx->scratch_buffer, ctx->scratch_buffer_capa);
317
+ thunkctx.file_name = intern_scratch_buffer(ctx);
318
+
319
+ thunkctx.line_number = mpp_sample_frame_line_number(sample, i);
320
+
321
+ // Fill in the function ID; the key is the (function_name, file_name) interned string index pair.
322
+ // This means that two frames are the same function if they have the same name and the same filename.
323
+ uint64_t func_id_key[2] = {thunkctx.function_name, thunkctx.file_name};
324
+ st_update(ctx->function_ids, (st_data_t)&func_id_key, function_id_update_func, (st_data_t)&thunkctx);
325
+
326
+ // Fill in the function & location protobuf structures.
327
+ st_update(ctx->function_pbs, thunkctx.function_id, mpp_pprof_serctx_add_function, (st_data_t)&thunkctx);
328
+ if (thunkctx.is_error) {
329
+ return -1;
330
+ }
331
+ uint64_t loc_key[2] = {thunkctx.function_id, thunkctx.line_number};
332
+ st_update(ctx->location_pbs, (st_data_t)&loc_key, mpp_pprof_serctx_add_location, (st_data_t)&thunkctx);
333
+ if (thunkctx.is_error) {
334
+ return -1;
335
+ }
336
+ MPP_ASSERT_MSG(thunkctx.location_id_out, "missing location ID out!");
337
+ location_ids[i] = thunkctx.location_id_out;
338
+ }
339
+
340
+ // Values are (retained_count, retained_size).
341
+ perftools_profiles_Sample_add_value(sample_proto, 1, ctx->arena);
342
+ perftools_profiles_Sample_add_value(sample_proto, (int64_t)sample->allocated_value_objsize, ctx->arena);
343
+ return 0;
344
+ }
345
+
346
+ static int write_each_string_table_entry(st_data_t key, st_data_t value, st_data_t arg) {
347
+ struct str_st_hash_key *string_key = (struct str_st_hash_key *)key;
348
+ upb_StringView *stringtab_list_proto = (upb_StringView *)arg;
349
+ int index = value;
350
+ stringtab_list_proto[index].data = string_key->str;
351
+ stringtab_list_proto[index].size = string_key->str_len;
352
+ return ST_CONTINUE;
353
+ }
354
+
355
+ // Serializes the contained protobuf, and gzips the result. Writes a pointer to the memory in *buf_out,
356
+ // and its length to buflen_out. The returned pointer is freed when mpp_pprof_serctx_destroy() is called,
357
+ // and should NOT be individually freed by the caller in any way (and nor is it valid after the call
358
+ // to destroy()).
359
+ int mpp_pprof_serctx_serialize(struct mpp_pprof_serctx *ctx, char **buf_out, size_t *buflen_out, char *errbuf,
360
+ size_t errbuflen) {
361
+ CHECK_IF_INTERRUPTED(return -1);
362
+
363
+ // Include the string table in the output
364
+ upb_StringView *stringtab_list_proto =
365
+ perftools_profiles_Profile_resize_string_table(ctx->profile_proto, ctx->strings_counter, ctx->arena);
366
+ st_foreach(ctx->strings, write_each_string_table_entry, (st_data_t)stringtab_list_proto);
367
+
368
+ CHECK_IF_INTERRUPTED(return -1);
369
+
370
+ // It looks like some codepaths might leak the protobuf_data pointer, but that's OK - it's in
371
+ // the ctx->arena so it'll get freed when ctx does.
372
+ size_t protobuf_data_len;
373
+ char *protobuf_data = perftools_profiles_Profile_serialize(ctx->profile_proto, ctx->arena, &protobuf_data_len);
374
+
375
+ CHECK_IF_INTERRUPTED(return -1);
376
+
377
+ // Gzip it as per standard.
378
+ z_stream strm;
379
+ int r;
380
+ int retval = 0;
381
+
382
+ strm.zalloc = Z_NULL;
383
+ strm.zfree = Z_NULL;
384
+ strm.opaque = Z_NULL;
385
+ strm.msg = NULL;
386
+ int windowBits = 15;
387
+ int GZIP_ENCODING = 16;
388
+ r = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY);
389
+ if (r != Z_OK) {
390
+ ruby_snprintf(errbuf, errbuflen, "error initializing zlib (errno %d: %s)", r, strm.msg ?: "");
391
+ return -1;
392
+ }
393
+ strm.avail_in = (unsigned int)protobuf_data_len;
394
+ strm.next_in = (unsigned char *)protobuf_data;
395
+
396
+ const size_t out_chunk_size = 4096;
397
+ char *gzip_data = upb_Arena_Malloc(ctx->arena, out_chunk_size);
398
+ size_t gzip_data_allocd_len = out_chunk_size;
399
+ strm.avail_out = out_chunk_size;
400
+ strm.next_out = (unsigned char *)gzip_data;
401
+ while (true) {
402
+ CHECK_IF_INTERRUPTED(goto zstream_free);
403
+
404
+ int flush = strm.avail_in == 0 ? Z_FINISH : Z_NO_FLUSH;
405
+ r = deflate(&strm, flush);
406
+ if (r == Z_STREAM_END) {
407
+ break;
408
+ } else if (r != Z_OK) {
409
+ // uh wat?
410
+ ruby_snprintf(errbuf, errbuflen, "error doing zlib output (errno %d: %s)", r, strm.msg ?: "");
411
+ retval = -1;
412
+ goto zstream_free;
413
+ }
414
+
415
+ if (strm.avail_out == 0) {
416
+ size_t old_gzip_data_allocd_len = gzip_data_allocd_len;
417
+ gzip_data_allocd_len += out_chunk_size;
418
+ gzip_data = upb_Arena_Realloc(ctx->arena, gzip_data, old_gzip_data_allocd_len, gzip_data_allocd_len);
419
+ strm.avail_out = out_chunk_size;
420
+ strm.next_out = (unsigned char *)(gzip_data + old_gzip_data_allocd_len);
421
+ }
422
+ }
423
+ // Set output pointers
424
+ *buf_out = gzip_data;
425
+ *buflen_out = gzip_data_allocd_len - strm.avail_out;
426
+
427
+ zstream_free:
428
+ deflateEnd(&strm);
429
+ return retval;
430
+ }
@@ -0,0 +1,118 @@
1
+ #include "ruby_private.h"
2
+
3
+ #include "ruby_memprofiler_pprof.h"
4
+
5
+ // An implementation of rb_gc_disable_no_rest(), which is defined non-static in gc.c in >= 2.7
6
+ // but not given public symbol visibility.
7
+ VALUE mpp_rb_gc_disable_no_rest() {
8
+ int old_dont_gc = GET_VM()->objspace->flags.dont_gc;
9
+ GET_VM()->objspace->flags.dont_gc = 1;
10
+ return old_dont_gc ? Qtrue : Qfalse;
11
+ }
12
+
13
+ // An implementation of rb_gc_memsize_of. Actually, in all Ruby versions >= 2.6, this has public
14
+ // symbol visibility, so just proxy through to it.
15
+ size_t mpp_rb_obj_memsize_of(VALUE obj) { return rb_obj_memsize_of(obj); }
16
+
17
+ // An implementation of is_pointer_to_heap, which is static in gc.c
18
+ static int mpp_is_pointer_to_heap(rb_objspace_t *objspace, void *ptr) {
19
+ register RVALUE *p = RANY(ptr);
20
+ register struct heap_page *page;
21
+ register size_t hi, lo, mid;
22
+
23
+ if (p < objspace->heap_pages.range[0] || p > objspace->heap_pages.range[1])
24
+ return FALSE;
25
+ if ((VALUE)p % sizeof(RVALUE) != 0)
26
+ return FALSE;
27
+ /* check if p looks like a pointer using bsearch*/
28
+ lo = 0;
29
+ hi = objspace->heap_pages.allocated_pages;
30
+ while (lo < hi) {
31
+ mid = (lo + hi) / 2;
32
+ page = objspace->heap_pages.sorted[mid];
33
+ if (page->start <= p) {
34
+ #ifdef HAVE_VARIABLE_SLOT_SIZE
35
+ // >= Ruby 3.1
36
+ if ((uintptr_t)p < ((uintptr_t)page->start + (page->total_slots * page->slot_size))) {
37
+ #else
38
+ // <= Ruby 3.0
39
+ if (p < page->start + page->total_slots) {
40
+ #endif
41
+ if (page->flags.in_tomb) {
42
+ return FALSE;
43
+ } else {
44
+ #ifdef HAVE_VARIABLE_SLOT_SIZE
45
+ if ((NUM_IN_PAGE(p) * sizeof(RVALUE)) % page->slot_size != 0)
46
+ return FALSE;
47
+ #endif
48
+ return TRUE;
49
+ }
50
+ }
51
+ lo = mid + 1;
52
+ } else {
53
+ hi = mid;
54
+ }
55
+ }
56
+ return FALSE;
57
+ }
58
+
59
+ // Answers the question, would rb_obj_memsize_of crash on this object?
60
+ bool mpp_is_value_still_validish(VALUE obj) {
61
+ if (obj == Qundef) {
62
+ return false;
63
+ }
64
+ if (!mpp_is_pointer_to_heap(GET_VM()->objspace, (void *)obj)) {
65
+ return false;
66
+ }
67
+ int type = RB_BUILTIN_TYPE(obj);
68
+ // do NOT return true for T_NODE; rb_obj_memsize_of() can't handle it.
69
+ switch (type) {
70
+ case T_OBJECT:
71
+ case T_MODULE:
72
+ case T_CLASS:
73
+ case T_ICLASS:
74
+ case T_STRING:
75
+ case T_ARRAY:
76
+ case T_HASH:
77
+ case T_REGEXP:
78
+ case T_DATA:
79
+ case T_MATCH:
80
+ case T_FILE:
81
+ case T_RATIONAL:
82
+ case T_COMPLEX:
83
+ case T_IMEMO:
84
+ case T_FLOAT:
85
+ case T_SYMBOL:
86
+ case T_BIGNUM:
87
+ case T_STRUCT:
88
+ return true;
89
+ }
90
+ return false;
91
+ }
92
+
93
+ // Peeks into internal GVL structures to spy if someone else is waiting for the GVL; we can
94
+ // then be polite and yield it for them.
95
+ bool mpp_is_someone_else_waiting_for_gvl() {
96
+ rb_global_vm_lock_t *gvl;
97
+ #ifdef HAVE_GET_RACTOR
98
+ gvl = &(GET_RACTOR()->threads.gvl);
99
+ #else
100
+ gvl = &(GET_VM()->gvl);
101
+ #endif
102
+ pthread_mutex_lock(&gvl->lock);
103
+ bool someone_waiting = !list_empty(&gvl->waitq);
104
+ pthread_mutex_unlock(&gvl->lock);
105
+ return someone_waiting;
106
+ }
107
+
108
+ // Unfreezes a passed in object so we can force setting something on
109
+ // its internal attributes hash.
110
+ VALUE mpp_rb_ivar_set_ignore_frozen(VALUE obj, ID key, VALUE value) {
111
+ bool was_frozen = RB_OBJ_FROZEN(obj);
112
+ RB_FL_UNSET_RAW(obj, FL_FREEZE);
113
+ VALUE ret = rb_ivar_set(obj, key, value);
114
+ if (was_frozen) {
115
+ RB_FL_SET_RAW(obj, FL_FREEZE);
116
+ }
117
+ return ret;
118
+ }
@@ -0,0 +1,10 @@
1
+ #include "ruby_memprofiler_pprof.h"
2
+ #include <ruby.h>
3
+
4
+ // This should be the only symbol actually visible to Ruby
5
+ __attribute__((visibility("default"))) void Init_ruby_memprofiler_pprof_ext() {
6
+ rb_ext_ractor_safe(true);
7
+
8
+ rb_define_module("MemprofilerPprof");
9
+ mpp_setup_collector_class();
10
+ }