ruby_memprofiler_pprof 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+ }