ruby_memprofiler_pprof 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. checksums.yaml +7 -0
  2. data/ext/ruby_memprofiler_pprof/backtrace.c +429 -0
  3. data/ext/ruby_memprofiler_pprof/collector.c +1055 -0
  4. data/ext/ruby_memprofiler_pprof/compat.c +182 -0
  5. data/ext/ruby_memprofiler_pprof/extconf.rb +72 -0
  6. data/ext/ruby_memprofiler_pprof/pprof.upb.c +170 -0
  7. data/ext/ruby_memprofiler_pprof/pprof.upb.h +848 -0
  8. data/ext/ruby_memprofiler_pprof/pprof_out.c +285 -0
  9. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.c +11 -0
  10. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.h +301 -0
  11. data/ext/ruby_memprofiler_pprof/strtab.c +391 -0
  12. data/ext/ruby_memprofiler_pprof/vendor/upb/BUILD +719 -0
  13. data/ext/ruby_memprofiler_pprof/vendor/upb/CONTRIBUTING.md +37 -0
  14. data/ext/ruby_memprofiler_pprof/vendor/upb/DESIGN.md +201 -0
  15. data/ext/ruby_memprofiler_pprof/vendor/upb/LICENSE +26 -0
  16. data/ext/ruby_memprofiler_pprof/vendor/upb/README.md +78 -0
  17. data/ext/ruby_memprofiler_pprof/vendor/upb/WORKSPACE +58 -0
  18. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/BUILD +53 -0
  19. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/amalgamate.py +129 -0
  20. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/build_defs.bzl +160 -0
  21. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/lua.BUILD +127 -0
  22. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/protobuf.patch +54 -0
  23. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/py_proto_library.bzl +137 -0
  24. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/python_downloads.bzl +84 -0
  25. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/system_python.bzl +101 -0
  26. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/upb_proto_library.bzl +388 -0
  27. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/workspace_deps.bzl +89 -0
  28. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD +252 -0
  29. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD.googleapis +54 -0
  30. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/benchmark.cc +333 -0
  31. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/build_defs.bzl +88 -0
  32. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/compare.py +118 -0
  33. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor.proto +888 -0
  34. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor_sv.proto +890 -0
  35. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/empty.proto +6 -0
  36. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_protobuf_binary_cc.py +64 -0
  37. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_synthetic_protos.py +118 -0
  38. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_upb_binary_c.py +65 -0
  39. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/BUILD.bazel +102 -0
  40. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/README.md +23 -0
  41. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/build_defs.bzl +73 -0
  42. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/make_cmakelists.py +340 -0
  43. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test.py +57 -0
  44. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test_lib.py +186 -0
  45. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/render.py +43 -0
  46. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/style-guide.md +65 -0
  47. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/vs-cpp-protos.md +255 -0
  48. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/wrapping-upb.md +444 -0
  49. data/ext/ruby_memprofiler_pprof/vendor/upb/python/BUILD +216 -0
  50. data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.c +394 -0
  51. data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.h +63 -0
  52. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.c +1694 -0
  53. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.h +80 -0
  54. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.c +704 -0
  55. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.h +114 -0
  56. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.c +650 -0
  57. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.h +48 -0
  58. data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/BUILD.bazel +193 -0
  59. data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/dist.bzl +190 -0
  60. data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.c +247 -0
  61. data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.h +39 -0
  62. data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.c +522 -0
  63. data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.h +66 -0
  64. data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.c +1909 -0
  65. data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.h +101 -0
  66. data/ext/ruby_memprofiler_pprof/vendor/upb/python/minimal_test.py +183 -0
  67. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/BUILD +70 -0
  68. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/README.md +11 -0
  69. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_database_test_wrapper.py +30 -0
  70. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_pool_test_wrapper.py +45 -0
  71. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_test_wrapper.py +46 -0
  72. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/generator_test_wrapper.py +30 -0
  73. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/json_format_test_wrapper.py +30 -0
  74. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/keywords_test_wrapper.py +30 -0
  75. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_factory_test_wrapper.py +37 -0
  76. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_test_wrapper.py +52 -0
  77. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/proto_builder_test_wrapper.py +32 -0
  78. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/pyproto_test_wrapper.bzl +36 -0
  79. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/reflection_test_wrapper.py +45 -0
  80. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/service_reflection_test_wrapper.py +30 -0
  81. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/symbol_database_test_wrapper.py +30 -0
  82. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_encoding_test_wrapper.py +30 -0
  83. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_format_test_wrapper.py +30 -0
  84. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/unknown_fields_test_wrapper.py +30 -0
  85. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/well_known_types_test_wrapper.py +36 -0
  86. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/wire_format_test_wrapper.py +30 -0
  87. data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.c +350 -0
  88. data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.h +230 -0
  89. data/ext/ruby_memprofiler_pprof/vendor/upb/python/py_extension.bzl +55 -0
  90. data/ext/ruby_memprofiler_pprof/vendor/upb/python/python_api.h +61 -0
  91. data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.c +828 -0
  92. data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.h +69 -0
  93. data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.c +404 -0
  94. data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.h +39 -0
  95. data/ext/ruby_memprofiler_pprof/vendor/upb/python/version_script.lds +6 -0
  96. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/LICENSE +32 -0
  97. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/README.google +9 -0
  98. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/console.lua +156 -0
  99. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/lunit.lua +725 -0
  100. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/BUILD +19 -0
  101. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/LICENSE +21 -0
  102. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/naive.c +92 -0
  103. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-neon.c +157 -0
  104. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-sse.c +170 -0
  105. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/utf8_range.h +9 -0
  106. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/BUILD.bazel +129 -0
  107. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/README.md +8 -0
  108. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/def.c +939 -0
  109. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/lua_proto_library.bzl +138 -0
  110. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/main.c +83 -0
  111. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/msg.c +1118 -0
  112. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test.proto +69 -0
  113. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test_upb.lua +846 -0
  114. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.c +258 -0
  115. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.h +132 -0
  116. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.lua +58 -0
  117. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upbc.cc +134 -0
  118. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.c +192 -0
  119. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.h +174 -0
  120. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb.c +346 -0
  121. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb_failures.txt +1 -0
  122. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.c +1221 -0
  123. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.h +94 -0
  124. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.c +1055 -0
  125. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.h +153 -0
  126. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_internal.h +211 -0
  127. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.c +3262 -0
  128. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.h +414 -0
  129. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.hpp +438 -0
  130. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/empty.proto +1 -0
  131. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.c +604 -0
  132. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.h +71 -0
  133. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/BUILD +13 -0
  134. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/file_descriptor_parsenew_fuzzer.cc +43 -0
  135. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.c +1509 -0
  136. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.h +47 -0
  137. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.c +776 -0
  138. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.h +62 -0
  139. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.c +1147 -0
  140. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.h +189 -0
  141. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.hpp +112 -0
  142. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.c +363 -0
  143. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.h +263 -0
  144. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_internal.h +59 -0
  145. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_test.cc +425 -0
  146. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_test.cc +230 -0
  147. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.c +428 -0
  148. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.h +114 -0
  149. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_internal.h +836 -0
  150. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.cc +491 -0
  151. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.proto +195 -0
  152. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_def.inc +261 -0
  153. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_undef.inc +62 -0
  154. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.c +323 -0
  155. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.h +109 -0
  156. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.hpp +37 -0
  157. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table.c +926 -0
  158. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table_internal.h +385 -0
  159. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test.proto +74 -0
  160. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.cc +186 -0
  161. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.proto +12 -0
  162. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_generated_code.cc +977 -0
  163. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_table.cc +580 -0
  164. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.c +472 -0
  165. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.h +64 -0
  166. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.c +362 -0
  167. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.h +378 -0
  168. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.hpp +115 -0
  169. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb_internal.h +68 -0
  170. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/BUILD +121 -0
  171. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/README.md +7 -0
  172. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.c +300 -0
  173. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.h +66 -0
  174. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare_test.cc +236 -0
  175. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.c +572 -0
  176. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.h +62 -0
  177. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_public_import_test.proto +32 -0
  178. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_regular_import_test.proto +36 -0
  179. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.cc +143 -0
  180. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.proto +119 -0
  181. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_weak_import_test.proto +28 -0
  182. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_wweak_import_test.proto +28 -0
  183. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.c +311 -0
  184. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.h +94 -0
  185. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.cc +202 -0
  186. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.proto +48 -0
  187. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/BUILD +78 -0
  188. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.cc +77 -0
  189. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.h +112 -0
  190. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upb.cc +1997 -0
  191. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upbdefs.cc +193 -0
  192. data/lib/ruby_memprofiler_pprof/atfork.rb +77 -0
  193. data/lib/ruby_memprofiler_pprof/block_flusher.rb +61 -0
  194. data/lib/ruby_memprofiler_pprof/file_flusher.rb +45 -0
  195. data/lib/ruby_memprofiler_pprof/profile_app.rb +30 -0
  196. data/lib/ruby_memprofiler_pprof/profile_data.rb +18 -0
  197. data/lib/ruby_memprofiler_pprof/version.rb +5 -0
  198. data/lib/ruby_memprofiler_pprof.rb +8 -0
  199. data/libexec/ruby_memprofiler_pprof_profile +16 -0
  200. metadata +257 -0
@@ -0,0 +1,444 @@
1
+
2
+ <!---
3
+ This document contains embedded graphviz diagrams inside ```dot blocks.
4
+
5
+ To convert it to rendered form using render.py:
6
+ $ ./render.py wrapping-upb.in.md
7
+
8
+ You can also live-preview this document with all diagrams using Markdown Preview Enhanced
9
+ in Visual Studio Code:
10
+ https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced
11
+ --->
12
+
13
+ # Building a protobuf library on upb
14
+
15
+ This is a guide for creating a new protobuf implementation based on upb. It
16
+ starts from the beginning and walks you through the process, highlighting
17
+ some important design choices you will need to make.
18
+
19
+ ## Overview
20
+
21
+ A protobuf implementation consists of two main pieces:
22
+
23
+ 1. a code generator, run at compile time, to turn `.proto` files into source
24
+ files in your language (we will call this "zlang", assuming an extension of ".z").
25
+ 2. a runtime component, which implements the wire format and provides the data
26
+ structures for representing protobuf data and metadata.
27
+
28
+ <br/>
29
+
30
+ ```dot {align="center"}
31
+ digraph {
32
+ rankdir=LR;
33
+ newrank=true;
34
+ node [style="rounded,filled" shape=box]
35
+ "foo.proto" -> protoc;
36
+ "foo.proto" [shape=folder];
37
+ protoc [fillcolor=lightgrey];
38
+ protoc -> "protoc-gen-zlang";
39
+ "protoc-gen-zlang" -> "foo.z";
40
+ "protoc-gen-zlang" [fillcolor=palegreen3];
41
+ "foo.z" [shape=folder];
42
+ labelloc="b";
43
+ label="Compile Time";
44
+ }
45
+ ```
46
+
47
+ <br/>
48
+
49
+ ```dot {align="center"}
50
+ digraph {
51
+ newrank=true;
52
+ node [style="rounded,filled" shape=box fillcolor=lightgrey]
53
+ "foo.z" -> "zlang/upb glue (FFI)";
54
+ "zlang/upb glue (FFI)" -> "upb (C)";
55
+ "zlang/upb glue (FFI)" [fillcolor=palegreen3];
56
+ labelloc="b";
57
+ label="Runtime";
58
+ }
59
+ ```
60
+
61
+ The parts in green are what you will need to implement.
62
+
63
+ Note that your code generator (`protoc-gen-zlang`) does *not* need to generate
64
+ any C code (eg. `foo.c`). While upb itself is written in C, upb's parsers and
65
+ serializers are fully table-driven, which means there is never any need or even
66
+ benefit to generating C code for each proto. upb is capable of full-speed
67
+ parsing even when schema data is loaded at runtime from strings embedded into
68
+ `foo.z`. This is a key benefit of upb compared with C++ protos, which have
69
+ traditionally relied on generated parsers in `foo.pb.cc` files to achieve full
70
+ parsing speed, and suffered a ~10x speed penalty in the parser when the schema
71
+ data was loaded at runtime.
72
+
73
+ ## Prerequisites
74
+
75
+ There are a few things that the language runtime must provide in order to wrap
76
+ upb.
77
+
78
+ 1. **FFI**: To wrap upb, your language must be able to call into a C API
79
+ through a Foreign Function Interface (FFI). Most languages support FFI in
80
+ some form, either through "native extensions" (in which you write some C
81
+ code to implement new methods in your language) or through a direct FFI (in
82
+ which you can call into regular C functions directly from your language
83
+ using a special library).
84
+ 2. **Finalizers, Destructors, or Cleaners**: The runtime must provide
85
+ finalizers or destructors of some sort. There must be a way of triggering a
86
+ call to a C function when the language garbage collects or otherwise
87
+ destroys an object. We don't care much whether it is a finalizer, a
88
+ destructor, or a cleaner, as long as it gets called eventually when the
89
+ object is destroyed. upb allocates memory in C space, and a finalizer is our
90
+ only way of making sure that memory is freed and does not leak.
91
+ 3. **HashMap with weak values**: (optional) This is not a strong requirement,
92
+ but it is sometimes helpful to have a global hashmap with weak values to act
93
+ as a `upb_msg* -> wrapper` object cache. We want the values to be weak (not
94
+ the keys). There is some question about whether we want to continue to use
95
+ this pattern going forward.
96
+
97
+ ## Reflection vs. MiniTables
98
+
99
+ The first key design decision you will need to make is whether your generated
100
+ code will access message data via reflection or minitables. Generally more
101
+ dynamic languages will want to use reflection and more static languages will
102
+ want to use minitables.
103
+
104
+ ### Reflection
105
+
106
+ Reflection-based data access makes the most sense in highly dynamic language
107
+ interpreters, where method dispatch is generally resolved via strings and hash
108
+ table lookups.
109
+
110
+ In such languages, you can often implement a special method like `__getattr__`
111
+ (Python) or `method_missing` (Ruby) that receives the method name as a string.
112
+ Using upb's reflection, you can look up a field name using the method name,
113
+ thereby using a hash table belonging to upb instead of one provided by the
114
+ language.
115
+
116
+ ```python
117
+ class FooMessage:
118
+ # Written in Python for illustration, but in practice we will want to
119
+ # implement this in C for speed.
120
+ def __getattr__(self, name):
121
+ field = FooMessage.descriptor.fields_by_name[name]
122
+ return field.get_value(self)
123
+ ```
124
+
125
+ Using this design, we only need to attach a single `__getattr__` method to each
126
+ message class, instead of defining a getter/setter for each field. In this way
127
+ we can avoid duplicating hash tables between upb and the language interpreter,
128
+ reducing memory usage.
129
+
130
+ Reflection-based access requires loading full reflection at runtime. Your
131
+ generated code will need to embed serialized descriptors (ie. a serialized
132
+ message of `descriptor.proto`), which has some amount of size overhead and
133
+ exposes all message/field names to the binary. It also forces a hash table
134
+ lookup in the critical path of field access. If method calls in your language
135
+ already have this overhead, then this is no added burden, but for statically
136
+ dispatched languages it would cause extra overhead.
137
+
138
+ If we take this path to its logical conclusion, all class creation can be
139
+ performed fully dynamically, using only a binary descriptor as input. The
140
+ "generated code" becomes little more than an embedded descriptor plus a
141
+ library call to load it. Python has recently gone down this path. Generated
142
+ code now looks something like this:
143
+
144
+ ```python
145
+ # main_pb2.py
146
+ from google3.net.proto2.python.internal import builder as _builder
147
+ from google3.net.proto2.python.public import descriptor_pool as _descriptor_pool
148
+
149
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile("<...>")
150
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
151
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'google3.main_pb2', globals())
152
+ ```
153
+
154
+ This is all the runtime needs to create all of the classes for messages defined
155
+ in that serialized descriptor. This code has no pretense of readability, but
156
+ a separate `.pyi` stub file provides a fully expanded and readable list of all
157
+ methods a user can expect to be available:
158
+
159
+ ```python
160
+ # main_pb2.pyi
161
+ from google3.net.proto2.python.public import descriptor as _descriptor
162
+ from google3.net.proto2.python.public import message as _message
163
+ from typing import ClassVar as _ClassVar, Optional as _Optional
164
+
165
+ DESCRIPTOR: _descriptor.FileDescriptor
166
+
167
+ class MyMessage(_message.Message):
168
+ __slots__ = ["my_field"]
169
+ MY_FIELD_FIELD_NUMBER: _ClassVar[int]
170
+ my_field: str
171
+ def __init__(self, my_field: _Optional[str] = ...) -> None: ...
172
+ ```
173
+
174
+ To use reflection-based access:
175
+
176
+ 1. Load and access descriptor data using the interfaces in google3/third_party/upb/upb/def.h.
177
+ 2. Access message data using the interfaces in google3/third_party/upb/upb/reflection.h.
178
+
179
+ ### MiniTables
180
+
181
+ MiniTables are a "lite" schema representation that are much smaller that
182
+ reflection. MiniTables omit names, options, and almost everything else from the
183
+ `.proto` file, retaining only enough information to parse and serialize binary
184
+ format.
185
+
186
+ MiniTables can be loaded into upb through *MiniDescriptors*. MiniDescriptors are
187
+ a byte-oriented format that can be embedded into your generated code and passed
188
+ to upb to construct MiniTables. MiniDescriptors only use printable characters,
189
+ and therefore do not require escaping when embedding them into generated code
190
+ strings. Overall the size savings of MiniDescriptors are ~60x compared with
191
+ regular descriptors.
192
+
193
+ MiniTables and MiniDescriptors are a natural choice for compiled languages that
194
+ resolve method calls at compile time. For languages that are sometimes compiled
195
+ and sometimes interpreted, there might not be an obvious choice. When a method
196
+ call is statically bound, we want to remove as much overhead as possible,
197
+ especially from accessors. In the extreme case, we can use unsafe APIs to read
198
+ raw memory at a known offset:
199
+
200
+ ```java
201
+ // Example of a maximally-optimized generated accessor.
202
+ class FooMessage {
203
+ public long getBarField() {
204
+ // Using Unsafe should give us performance that is comparable to a
205
+ // native member access.
206
+ //
207
+ // The constant "24" is obtained from upb at compile time.
208
+ sun.misc.Unsafe.getLong(this.ptr, 24);
209
+ }
210
+ }
211
+ ```
212
+
213
+ This design is very low-level, and tightly couples the generated code to one
214
+ specific version of the schema and compiler. A slower but safer version would
215
+ look up a field by field number:
216
+
217
+ ```java
218
+ // Example of a more loosely-coupled accessor.
219
+ class FooMessage {
220
+ public long getBarField() {
221
+ // The constant "2" is the field number. Internally this will look
222
+ // up the number "2" in the MiniTable and use that to read the value
223
+ // from the message.
224
+ upb.glue.getLong(this.ptr, 2);
225
+ }
226
+ }
227
+ ```
228
+
229
+ One downside of MiniTables is that they cannot support parsing or serializing
230
+ to JSON or TextFormat, because they do now know the field names. It should be
231
+ possible to generate reflection data "on the side", into separate generated
232
+ code files, so that reflection is only pulled in if it is being used. However
233
+ APIs to do this do not exist yet.
234
+
235
+ To use MiniTable-based access:
236
+
237
+ 1. Load and access MiniDescriptors data using the interfaces in google3/third_party/upb/upb/mini_table.h.
238
+ 2. Access message data using the interfaces in google3/third_party/upb/upb/mini_table_accessors.h.
239
+
240
+ ## Memory Management
241
+
242
+ One of the core design challenges when wrapping upb is memory management. Every
243
+ language runtime will have some memory management system, whether it is
244
+ garbage collection, reference counting, manual memory management, or some hybrid
245
+ of these. upb is written in C and uses arenas for memory management, but upb is
246
+ designed to integrate with a wide variety of memory management schemes, and it
247
+ provides a number of tools for making this integration as smooth as possible.
248
+
249
+ ### Arenas
250
+
251
+ upb defines data structures in C to represent messages, arrays (repeated
252
+ fields), and maps. A protobuf message is a hierarchical tree of these objects.
253
+ For example, a relatively simple protobuf tree might look something like this:
254
+
255
+ ```dot {align="center"}
256
+ digraph G {
257
+ rankdir=LR;
258
+ newrank=true;
259
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
260
+ upb_msg -> upb_msg2;
261
+ upb_msg -> upb_array;
262
+ upb_msg [label="upb Message" fillcolor=1]
263
+ upb_msg2 [label="upb Message"];
264
+ upb_array [label="upb Array"]
265
+ }
266
+ ```
267
+
268
+ All upb objects are allocated from an arena. An arena lets you allocate objects
269
+ individually, but you cannot free individual objects; you can only free the arena
270
+ as a whole. When the arena is freed, all of the individual objects allocated
271
+ from that arena are freed together.
272
+
273
+ ```dot {align="center"}
274
+ digraph G {
275
+ rankdir=LR;
276
+ newrank=true;
277
+ subgraph cluster_0 {
278
+ label = "upb Arena"
279
+ graph[style="rounded,filled" fillcolor=gray]
280
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
281
+ upb_msg -> upb_array;
282
+ upb_msg -> upb_msg2;
283
+ upb_msg [label="upb Message" fillcolor=1]
284
+ upb_msg2 [label="upb Message"];
285
+ upb_array [label="upb Array"];
286
+ }
287
+ }
288
+ ```
289
+
290
+ In simple cases, the entire tree of objects will all live in a single arena.
291
+ This has the nice property that there cannot be any dangling pointers between
292
+ objects, since all objects are freed at the same time.
293
+
294
+ However upb allows you to create links between any two objects, whether or
295
+ not they are in the same arena. The library does not know or care what arenas
296
+ the objects are in when you create links between them.
297
+
298
+ ```dot {align="center"}
299
+ digraph G {
300
+ rankdir=LR;
301
+ newrank=true;
302
+ subgraph cluster_0 {
303
+ label = "upb Arena 1"
304
+ graph[style="rounded,filled" fillcolor=gray]
305
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
306
+ upb_msg -> upb_array;
307
+ upb_msg -> upb_msg2;
308
+ upb_msg [label="upb Message 1" fillcolor=1]
309
+ upb_msg2 [label="upb Message 2"];
310
+ upb_array [label="upb Array"];
311
+ }
312
+ subgraph cluster_1 {
313
+ label = "upb Arena 2"
314
+ graph[style="rounded,filled" fillcolor=gray]
315
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1]
316
+ upb_msg3;
317
+ }
318
+ upb_msg2 -> upb_msg3;
319
+ upb_msg3 [label="upb Message 3"];
320
+ }
321
+ ```
322
+
323
+ When objects are on separate arenas, it is the user's responsibility to ensure
324
+ that there are no dangling pointers. In the example above, this means Arena 2
325
+ must outlive Message 1 and Message 2.
326
+
327
+ ### Integrating GC with upb
328
+
329
+ In languages with automatic memory management, the goal is to handle all of the
330
+ arenas behind the scenes, so that the user does not have to manage them manually
331
+ or even know that they exist.
332
+
333
+ We can achieve this goal if we set up the object graph in a particular way. The
334
+ general strategy is to create wrapper objects around all of the C objects,
335
+ including the arena. Our key goal is to make sure the arena wrapper is not
336
+ GC'd until all of the C objects in that arena have become unreachable.
337
+
338
+ For this example, we will assume we are wrapping upb in Python:
339
+
340
+ ```dot {align="center"}
341
+ digraph G {
342
+ rankdir=LR;
343
+ newrank=true;
344
+ compound=true;
345
+
346
+ subgraph cluster_1 {
347
+ label = "upb Arena"
348
+ graph[style="rounded,filled" fillcolor=gray]
349
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
350
+ upb_msg -> upb_array [style=dashed];
351
+ upb_msg -> upb_msg2 [style=dashed];
352
+ upb_msg [label="upb Message" fillcolor=1]
353
+ upb_msg2 [label="upb Message"];
354
+ upb_array [label="upb Array"]
355
+ dummy [style=invis]
356
+ }
357
+ subgraph cluster_python {
358
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=2]
359
+ peripheries=0
360
+ py_upb_msg [label="Python Message"];
361
+ py_upb_msg2 [label="Python Message"];
362
+ py_upb_arena [label="Python Arena"];
363
+ }
364
+ py_upb_msg -> upb_msg [style=dashed];
365
+ py_upb_msg2->upb_msg2 [style=dashed];
366
+ py_upb_msg2 -> py_upb_arena [color=springgreen4];
367
+ py_upb_msg -> py_upb_arena [color=springgreen4];
368
+ py_upb_arena -> dummy [lhead=cluster_1, color=red];
369
+ {
370
+ rank=same;
371
+ upb_msg;
372
+ py_upb_msg;
373
+ }
374
+ {
375
+ rank=same;
376
+ upb_array;
377
+ upb_msg2;
378
+ py_upb_msg2;
379
+ }
380
+ { rank=same;
381
+ dummy;
382
+ py_upb_arena;
383
+ }
384
+ dummy->upb_array [style=invis];
385
+ dummy->upb_msg2 [style=invis];
386
+
387
+ subgraph cluster_01 {
388
+ node [shape=plaintext]
389
+ peripheries=0
390
+ key [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
391
+ <tr><td align="right" port="i1">raw ptr</td></tr>
392
+ <tr><td align="right" port="i2">unique ptr</td></tr>
393
+ <tr><td align="right" port="i3">shared (GC) ptr</td></tr>
394
+ </table>>]
395
+ key2 [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
396
+ <tr><td port="i1">&nbsp;</td></tr>
397
+ <tr><td port="i2">&nbsp;</td></tr>
398
+ <tr><td port="i3">&nbsp;</td></tr>
399
+ </table>>]
400
+ key:i1:e -> key2:i1:w [style=dashed]
401
+ key:i2:e -> key2:i2:w [color=red]
402
+ key:i3:e -> key2:i3:w [color=springgreen4]
403
+ }
404
+ key2:i1:w -> upb_msg [style=invis];
405
+ {
406
+ rank=same;
407
+ key;
408
+ upb_msg;
409
+ }
410
+ }
411
+ ```
412
+
413
+ In this example we have three different kinds of pointers:
414
+
415
+ * **raw ptr**: This is a pointer that carries no ownership.
416
+ * **unique ptr**: This is a pointer has *unique ownership* of the target. The owner
417
+ will free the target in its destructor (or finalizer, or cleaner). There can
418
+ only be a single unique pointer to a given object.
419
+ * **shared (GC) ptr**: This is a pointer that has *shared ownership* of the
420
+ target. Many objects can point to the target, and the target will be deleted
421
+ only when all such references are gone. In a runtime with automatic memory
422
+ management (GC), this is a reference that participates in GC. In Python such
423
+ references use reference counting, but in other VMs they may use mark and
424
+ sweep or some other form of GC instead.
425
+
426
+ The Python Message wrappers have only raw pointers to the underlying message,
427
+ but they contain a shared pointer to the arena that will ensure that the raw
428
+ pointer remains valid. Only when all message wrapper objects are destroyed
429
+ will the Python Arena become unreachable, and the upb arena ultimately freed.
430
+
431
+ ### Links between arenas with "Fuse"
432
+
433
+ The design given above works well for objects that live in a single arena. But
434
+ what if a user wants to create a link between two objects in different arenas?
435
+
436
+ TODO
437
+
438
+ ## UTF-8 vs. UTF-16
439
+
440
+ TODO
441
+
442
+ ## Object Cache
443
+
444
+ TODO
@@ -0,0 +1,216 @@
1
+ # Copyright (c) 2009-2021, Google LLC
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ # * Redistributions of source code must retain the above copyright
7
+ # notice, this list of conditions and the following disclaimer.
8
+ # * Redistributions in binary form must reproduce the above copyright
9
+ # notice, this list of conditions and the following disclaimer in the
10
+ # documentation and/or other materials provided with the distribution.
11
+ # * Neither the name of Google LLC nor the
12
+ # names of its contributors may be used to endorse or promote products
13
+ # derived from this software without specific prior written permission.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
19
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ # begin:github_only
27
+ load("//python:py_extension.bzl", "py_extension")
28
+ # end:github_only
29
+
30
+ load("@bazel_skylib//lib:selects.bzl", "selects")
31
+ load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag")
32
+ load("//bazel:build_defs.bzl", "UPB_DEFAULT_COPTS")
33
+
34
+ licenses(["notice"])
35
+
36
+ package(
37
+ default_visibility = ["//python/dist:__pkg__"],
38
+ )
39
+
40
+ LIMITED_API_FLAG_SELECT = {
41
+ ":limited_api_3.7": ["-DPy_LIMITED_API=0x03070000"],
42
+ ":limited_api_3.10": ["-DPy_LIMITED_API=0x030a0000"],
43
+ "//conditions:default": [],
44
+ }
45
+
46
+ bool_flag(
47
+ name = "limited_api",
48
+ build_setting_default = False,
49
+ )
50
+
51
+ string_flag(
52
+ name = "python_version",
53
+ build_setting_default = "system",
54
+ values = [
55
+ "system",
56
+ "37",
57
+ "38",
58
+ "39",
59
+ "310",
60
+ ],
61
+ )
62
+
63
+ config_setting(
64
+ name = "limited_api_3.7",
65
+ flag_values = {
66
+ ":limited_api": "True",
67
+ ":python_version": "37",
68
+ },
69
+ )
70
+
71
+ config_setting(
72
+ name = "full_api_3.7_win32",
73
+ flag_values = {
74
+ ":limited_api": "False",
75
+ ":python_version": "37",
76
+ },
77
+ values = {"cpu": "win32"},
78
+ )
79
+
80
+ config_setting(
81
+ name = "full_api_3.7_win64",
82
+ flag_values = {
83
+ ":limited_api": "False",
84
+ ":python_version": "37",
85
+ },
86
+ values = {"cpu": "win64"},
87
+ )
88
+
89
+ selects.config_setting_group(
90
+ name = "full_api_3.7",
91
+ match_any = [
92
+ ":full_api_3.7_win32",
93
+ ":full_api_3.7_win64",
94
+ ],
95
+ )
96
+
97
+ config_setting(
98
+ name = "full_api_3.8_win32",
99
+ flag_values = {
100
+ ":limited_api": "False",
101
+ ":python_version": "38",
102
+ },
103
+ values = {"cpu": "win32"},
104
+ )
105
+
106
+ config_setting(
107
+ name = "full_api_3.8_win64",
108
+ flag_values = {
109
+ ":limited_api": "False",
110
+ ":python_version": "38",
111
+ },
112
+ values = {"cpu": "win64"},
113
+ )
114
+
115
+ selects.config_setting_group(
116
+ name = "full_api_3.8",
117
+ match_any = [
118
+ ":full_api_3.8_win32",
119
+ ":full_api_3.8_win64",
120
+ ],
121
+ )
122
+
123
+ config_setting(
124
+ name = "full_api_3.9_win32",
125
+ flag_values = {
126
+ ":limited_api": "False",
127
+ ":python_version": "39",
128
+ },
129
+ values = {"cpu": "win32"},
130
+ )
131
+
132
+ config_setting(
133
+ name = "full_api_3.9_win64",
134
+ flag_values = {
135
+ ":limited_api": "False",
136
+ ":python_version": "39",
137
+ },
138
+ values = {"cpu": "win64"},
139
+ )
140
+
141
+ selects.config_setting_group(
142
+ name = "full_api_3.9",
143
+ match_any = [
144
+ "full_api_3.9_win32",
145
+ ":full_api_3.9_win64",
146
+ ],
147
+ )
148
+
149
+ config_setting(
150
+ name = "limited_api_3.10_win32",
151
+ flag_values = {
152
+ ":limited_api": "True",
153
+ ":python_version": "310",
154
+ },
155
+ values = {"cpu": "win32"},
156
+ )
157
+
158
+ config_setting(
159
+ name = "limited_api_3.10_win64",
160
+ flag_values = {
161
+ ":limited_api": "True",
162
+ ":python_version": "310",
163
+ },
164
+ values = {"cpu": "win64"},
165
+ )
166
+
167
+ selects.config_setting_group(
168
+ name = "limited_api_3.10",
169
+ match_any = [
170
+ ":limited_api_3.10_win32",
171
+ ":limited_api_3.10_win64",
172
+ ],
173
+ )
174
+
175
+ py_extension(
176
+ name = "_message",
177
+ srcs = [
178
+ "convert.c",
179
+ "convert.h",
180
+ "descriptor.c",
181
+ "descriptor.h",
182
+ "descriptor_containers.c",
183
+ "descriptor_containers.h",
184
+ "descriptor_pool.c",
185
+ "descriptor_pool.h",
186
+ "extension_dict.c",
187
+ "extension_dict.h",
188
+ "map.c",
189
+ "map.h",
190
+ "message.c",
191
+ "message.h",
192
+ "protobuf.c",
193
+ "protobuf.h",
194
+ "python_api.h",
195
+ "repeated.c",
196
+ "repeated.h",
197
+ "unknown_fields.c",
198
+ "unknown_fields.h",
199
+ ],
200
+ copts = UPB_DEFAULT_COPTS + select(LIMITED_API_FLAG_SELECT) + [
201
+ # The Python API requires patterns that are ISO C incompatible, like
202
+ # casts between function pointers and object pointers.
203
+ "-Wno-pedantic",
204
+ ],
205
+ deps = [
206
+ "//:collections",
207
+ "//:descriptor_upb_proto_reflection",
208
+ "//:reflection",
209
+ "//:table",
210
+ "//:textformat",
211
+ "//:upb",
212
+ "//upb/util:compare",
213
+ "//upb/util:def_to_proto",
214
+ "//upb/util:required_fields",
215
+ ],
216
+ )