kafka-python 3.0.0__py3-none-any.whl

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 (373) hide show
  1. kafka/__init__.py +34 -0
  2. kafka/__main__.py +5 -0
  3. kafka/admin/__init__.py +29 -0
  4. kafka/admin/__main__.py +5 -0
  5. kafka/admin/_acls.py +355 -0
  6. kafka/admin/_cluster.py +359 -0
  7. kafka/admin/_configs.py +479 -0
  8. kafka/admin/_groups.py +754 -0
  9. kafka/admin/_partitions.py +595 -0
  10. kafka/admin/_topics.py +281 -0
  11. kafka/admin/_transactions.py +450 -0
  12. kafka/admin/_users.py +194 -0
  13. kafka/admin/client.py +373 -0
  14. kafka/benchmarks/__init__.py +0 -0
  15. kafka/benchmarks/consumer_performance.py +138 -0
  16. kafka/benchmarks/load_example.py +109 -0
  17. kafka/benchmarks/producer_encode_path.py +201 -0
  18. kafka/benchmarks/producer_performance.py +161 -0
  19. kafka/benchmarks/profile_protocol.py +138 -0
  20. kafka/benchmarks/protocol_old_vs_new.py +447 -0
  21. kafka/benchmarks/record_batch_compose.py +77 -0
  22. kafka/benchmarks/record_batch_read.py +82 -0
  23. kafka/benchmarks/varint_speed.py +426 -0
  24. kafka/cli/__init__.py +36 -0
  25. kafka/cli/admin/__init__.py +117 -0
  26. kafka/cli/admin/acls/__init__.py +9 -0
  27. kafka/cli/admin/acls/common.py +76 -0
  28. kafka/cli/admin/acls/create.py +19 -0
  29. kafka/cli/admin/acls/delete.py +23 -0
  30. kafka/cli/admin/acls/describe.py +16 -0
  31. kafka/cli/admin/cluster/__init__.py +14 -0
  32. kafka/cli/admin/cluster/describe.py +11 -0
  33. kafka/cli/admin/cluster/describe_quorum.py +11 -0
  34. kafka/cli/admin/cluster/features.py +52 -0
  35. kafka/cli/admin/cluster/log_dirs.py +43 -0
  36. kafka/cli/admin/cluster/versions.py +33 -0
  37. kafka/cli/admin/configs/__init__.py +10 -0
  38. kafka/cli/admin/configs/alter.py +43 -0
  39. kafka/cli/admin/configs/common.py +17 -0
  40. kafka/cli/admin/configs/describe.py +30 -0
  41. kafka/cli/admin/configs/list.py +16 -0
  42. kafka/cli/admin/configs/reset.py +20 -0
  43. kafka/cli/admin/groups/__init__.py +16 -0
  44. kafka/cli/admin/groups/alter_offsets.py +30 -0
  45. kafka/cli/admin/groups/delete.py +11 -0
  46. kafka/cli/admin/groups/delete_offsets.py +29 -0
  47. kafka/cli/admin/groups/describe.py +11 -0
  48. kafka/cli/admin/groups/list.py +28 -0
  49. kafka/cli/admin/groups/list_offsets.py +29 -0
  50. kafka/cli/admin/groups/remove_members.py +40 -0
  51. kafka/cli/admin/groups/reset_offsets.py +139 -0
  52. kafka/cli/admin/partitions/__init__.py +21 -0
  53. kafka/cli/admin/partitions/alter_reassignments.py +37 -0
  54. kafka/cli/admin/partitions/create.py +27 -0
  55. kafka/cli/admin/partitions/delete_records.py +31 -0
  56. kafka/cli/admin/partitions/describe.py +36 -0
  57. kafka/cli/admin/partitions/elect_leaders.py +53 -0
  58. kafka/cli/admin/partitions/list_offsets.py +88 -0
  59. kafka/cli/admin/partitions/list_reassignments.py +35 -0
  60. kafka/cli/admin/topics/__init__.py +10 -0
  61. kafka/cli/admin/topics/create.py +13 -0
  62. kafka/cli/admin/topics/delete.py +19 -0
  63. kafka/cli/admin/topics/describe.py +18 -0
  64. kafka/cli/admin/topics/list.py +11 -0
  65. kafka/cli/admin/transactions/__init__.py +17 -0
  66. kafka/cli/admin/transactions/abort.py +38 -0
  67. kafka/cli/admin/transactions/describe.py +24 -0
  68. kafka/cli/admin/transactions/describe_producers.py +29 -0
  69. kafka/cli/admin/transactions/find_hanging.py +26 -0
  70. kafka/cli/admin/transactions/list.py +37 -0
  71. kafka/cli/admin/users/__init__.py +8 -0
  72. kafka/cli/admin/users/alter_user_scram_credentials.py +34 -0
  73. kafka/cli/admin/users/describe_user_scram_credentials.py +15 -0
  74. kafka/cli/common.py +95 -0
  75. kafka/cli/consumer/__init__.py +63 -0
  76. kafka/cli/producer/__init__.py +57 -0
  77. kafka/cluster.py +824 -0
  78. kafka/codec.py +325 -0
  79. kafka/consumer/__init__.py +5 -0
  80. kafka/consumer/__main__.py +5 -0
  81. kafka/consumer/fetcher.py +2012 -0
  82. kafka/consumer/group.py +1347 -0
  83. kafka/consumer/subscription_state.py +897 -0
  84. kafka/coordinator/__init__.py +0 -0
  85. kafka/coordinator/assignors/__init__.py +0 -0
  86. kafka/coordinator/assignors/abstract.py +90 -0
  87. kafka/coordinator/assignors/cooperative_sticky.py +167 -0
  88. kafka/coordinator/assignors/range.py +81 -0
  89. kafka/coordinator/assignors/roundrobin.py +101 -0
  90. kafka/coordinator/assignors/sticky/StickyAssignorUserData.json +37 -0
  91. kafka/coordinator/assignors/sticky/__init__.py +0 -0
  92. kafka/coordinator/assignors/sticky/partition_movements.py +149 -0
  93. kafka/coordinator/assignors/sticky/sorted_set.py +63 -0
  94. kafka/coordinator/assignors/sticky/sticky_assignor.py +665 -0
  95. kafka/coordinator/assignors/sticky/user_data.py +8 -0
  96. kafka/coordinator/base.py +1215 -0
  97. kafka/coordinator/consumer.py +1224 -0
  98. kafka/coordinator/heartbeat.py +82 -0
  99. kafka/coordinator/subscription.py +34 -0
  100. kafka/errors.py +1004 -0
  101. kafka/future.py +166 -0
  102. kafka/metrics/__init__.py +13 -0
  103. kafka/metrics/compound_stat.py +33 -0
  104. kafka/metrics/dict_reporter.py +81 -0
  105. kafka/metrics/kafka_metric.py +36 -0
  106. kafka/metrics/measurable.py +27 -0
  107. kafka/metrics/measurable_stat.py +13 -0
  108. kafka/metrics/metric_config.py +33 -0
  109. kafka/metrics/metric_name.py +105 -0
  110. kafka/metrics/metrics.py +261 -0
  111. kafka/metrics/metrics_reporter.py +53 -0
  112. kafka/metrics/quota.py +41 -0
  113. kafka/metrics/stat.py +19 -0
  114. kafka/metrics/stats/__init__.py +15 -0
  115. kafka/metrics/stats/avg.py +24 -0
  116. kafka/metrics/stats/count.py +17 -0
  117. kafka/metrics/stats/histogram.py +99 -0
  118. kafka/metrics/stats/max_stat.py +17 -0
  119. kafka/metrics/stats/min_stat.py +19 -0
  120. kafka/metrics/stats/percentile.py +14 -0
  121. kafka/metrics/stats/percentiles.py +75 -0
  122. kafka/metrics/stats/rate.py +118 -0
  123. kafka/metrics/stats/sampled_stat.py +99 -0
  124. kafka/metrics/stats/sensor.py +136 -0
  125. kafka/metrics/stats/total.py +15 -0
  126. kafka/net/__init__.py +19 -0
  127. kafka/net/compat.py +165 -0
  128. kafka/net/connection.py +593 -0
  129. kafka/net/http_connect.py +144 -0
  130. kafka/net/inet.py +122 -0
  131. kafka/net/manager.py +451 -0
  132. kafka/net/metrics.py +149 -0
  133. kafka/net/sasl/__init__.py +32 -0
  134. kafka/net/sasl/abc.py +28 -0
  135. kafka/net/sasl/gssapi.py +95 -0
  136. kafka/net/sasl/msk.py +245 -0
  137. kafka/net/sasl/oauth.py +98 -0
  138. kafka/net/sasl/plain.py +42 -0
  139. kafka/net/sasl/scram.py +135 -0
  140. kafka/net/sasl/sspi.py +111 -0
  141. kafka/net/selector.py +644 -0
  142. kafka/net/socks5.py +262 -0
  143. kafka/net/transport.py +415 -0
  144. kafka/net/wakeup_notifier.py +72 -0
  145. kafka/partitioner/__init__.py +8 -0
  146. kafka/partitioner/abc.py +8 -0
  147. kafka/partitioner/default.py +89 -0
  148. kafka/partitioner/sticky.py +109 -0
  149. kafka/producer/__init__.py +5 -0
  150. kafka/producer/__main__.py +5 -0
  151. kafka/producer/future.py +101 -0
  152. kafka/producer/kafka.py +1123 -0
  153. kafka/producer/producer_batch.py +192 -0
  154. kafka/producer/record_accumulator.py +647 -0
  155. kafka/producer/sender.py +884 -0
  156. kafka/producer/transaction_manager.py +1326 -0
  157. kafka/protocol/__init__.py +0 -0
  158. kafka/protocol/admin/__init__.py +29 -0
  159. kafka/protocol/admin/acl.py +83 -0
  160. kafka/protocol/admin/acl.pyi +375 -0
  161. kafka/protocol/admin/client_quotas.py +14 -0
  162. kafka/protocol/admin/client_quotas.pyi +265 -0
  163. kafka/protocol/admin/cluster.py +31 -0
  164. kafka/protocol/admin/cluster.pyi +620 -0
  165. kafka/protocol/admin/configs.py +22 -0
  166. kafka/protocol/admin/configs.pyi +437 -0
  167. kafka/protocol/admin/groups.py +24 -0
  168. kafka/protocol/admin/groups.pyi +261 -0
  169. kafka/protocol/admin/topics.py +53 -0
  170. kafka/protocol/admin/topics.pyi +982 -0
  171. kafka/protocol/admin/transactions.py +18 -0
  172. kafka/protocol/admin/transactions.pyi +311 -0
  173. kafka/protocol/admin/users.py +14 -0
  174. kafka/protocol/admin/users.pyi +223 -0
  175. kafka/protocol/api_data.py +125 -0
  176. kafka/protocol/api_header.py +55 -0
  177. kafka/protocol/api_key.py +97 -0
  178. kafka/protocol/api_message.py +277 -0
  179. kafka/protocol/broker_version_data.py +246 -0
  180. kafka/protocol/consumer/__init__.py +13 -0
  181. kafka/protocol/consumer/fetch.py +16 -0
  182. kafka/protocol/consumer/fetch.pyi +298 -0
  183. kafka/protocol/consumer/group.py +38 -0
  184. kafka/protocol/consumer/group.pyi +824 -0
  185. kafka/protocol/consumer/metadata.py +30 -0
  186. kafka/protocol/consumer/metadata.pyi +89 -0
  187. kafka/protocol/consumer/offsets.py +75 -0
  188. kafka/protocol/consumer/offsets.pyi +288 -0
  189. kafka/protocol/data_container.py +166 -0
  190. kafka/protocol/frame.py +30 -0
  191. kafka/protocol/generate_stubs.py +468 -0
  192. kafka/protocol/metadata/__init__.py +10 -0
  193. kafka/protocol/metadata/api_versions.py +41 -0
  194. kafka/protocol/metadata/api_versions.pyi +128 -0
  195. kafka/protocol/metadata/find_coordinator.py +19 -0
  196. kafka/protocol/metadata/find_coordinator.pyi +105 -0
  197. kafka/protocol/metadata/metadata.py +34 -0
  198. kafka/protocol/metadata/metadata.pyi +160 -0
  199. kafka/protocol/old/__init__.py +0 -0
  200. kafka/protocol/old/abstract.py +17 -0
  201. kafka/protocol/old/add_offsets_to_txn.py +54 -0
  202. kafka/protocol/old/add_partitions_to_txn.py +71 -0
  203. kafka/protocol/old/admin.py +1086 -0
  204. kafka/protocol/old/api.py +205 -0
  205. kafka/protocol/old/api_versions.py +133 -0
  206. kafka/protocol/old/commit.py +355 -0
  207. kafka/protocol/old/consumer_protocol.py +36 -0
  208. kafka/protocol/old/end_txn.py +53 -0
  209. kafka/protocol/old/fetch.py +408 -0
  210. kafka/protocol/old/find_coordinator.py +72 -0
  211. kafka/protocol/old/group.py +451 -0
  212. kafka/protocol/old/init_producer_id.py +42 -0
  213. kafka/protocol/old/list_offsets.py +186 -0
  214. kafka/protocol/old/metadata.py +290 -0
  215. kafka/protocol/old/offset_for_leader_epoch.py +133 -0
  216. kafka/protocol/old/produce.py +247 -0
  217. kafka/protocol/old/sasl_authenticate.py +38 -0
  218. kafka/protocol/old/sasl_handshake.py +39 -0
  219. kafka/protocol/old/struct.py +87 -0
  220. kafka/protocol/old/txn_offset_commit.py +73 -0
  221. kafka/protocol/old/types.py +440 -0
  222. kafka/protocol/parser.py +191 -0
  223. kafka/protocol/producer/__init__.py +7 -0
  224. kafka/protocol/producer/produce.py +17 -0
  225. kafka/protocol/producer/produce.pyi +197 -0
  226. kafka/protocol/producer/transaction.py +30 -0
  227. kafka/protocol/producer/transaction.pyi +663 -0
  228. kafka/protocol/sasl.py +52 -0
  229. kafka/protocol/sasl.pyi +126 -0
  230. kafka/protocol/schemas/__init__.py +7 -0
  231. kafka/protocol/schemas/fields/__init__.py +7 -0
  232. kafka/protocol/schemas/fields/array.py +127 -0
  233. kafka/protocol/schemas/fields/base.py +156 -0
  234. kafka/protocol/schemas/fields/codecs/__init__.py +12 -0
  235. kafka/protocol/schemas/fields/codecs/encode_buffer.py +82 -0
  236. kafka/protocol/schemas/fields/codecs/tagged_fields.py +109 -0
  237. kafka/protocol/schemas/fields/codecs/types.py +505 -0
  238. kafka/protocol/schemas/fields/codegen.py +40 -0
  239. kafka/protocol/schemas/fields/simple.py +127 -0
  240. kafka/protocol/schemas/fields/struct.py +357 -0
  241. kafka/protocol/schemas/fields/struct_array.py +142 -0
  242. kafka/protocol/schemas/load_json.py +42 -0
  243. kafka/protocol/schemas/resources/AddOffsetsToTxnRequest.json +40 -0
  244. kafka/protocol/schemas/resources/AddOffsetsToTxnResponse.json +35 -0
  245. kafka/protocol/schemas/resources/AddPartitionsToTxnRequest.json +65 -0
  246. kafka/protocol/schemas/resources/AddPartitionsToTxnResponse.json +60 -0
  247. kafka/protocol/schemas/resources/AlterClientQuotasRequest.json +47 -0
  248. kafka/protocol/schemas/resources/AlterClientQuotasResponse.json +41 -0
  249. kafka/protocol/schemas/resources/AlterConfigsRequest.json +43 -0
  250. kafka/protocol/schemas/resources/AlterConfigsResponse.json +39 -0
  251. kafka/protocol/schemas/resources/AlterPartitionReassignmentsRequest.json +42 -0
  252. kafka/protocol/schemas/resources/AlterPartitionReassignmentsResponse.json +47 -0
  253. kafka/protocol/schemas/resources/AlterReplicaLogDirsRequest.json +41 -0
  254. kafka/protocol/schemas/resources/AlterReplicaLogDirsResponse.json +41 -0
  255. kafka/protocol/schemas/resources/AlterUserScramCredentialsRequest.json +45 -0
  256. kafka/protocol/schemas/resources/AlterUserScramCredentialsResponse.json +35 -0
  257. kafka/protocol/schemas/resources/ApiVersionsRequest.json +34 -0
  258. kafka/protocol/schemas/resources/ApiVersionsResponse.json +79 -0
  259. kafka/protocol/schemas/resources/ConsumerProtocolAssignment.json +42 -0
  260. kafka/protocol/schemas/resources/ConsumerProtocolSubscription.json +49 -0
  261. kafka/protocol/schemas/resources/CreateAclsRequest.json +46 -0
  262. kafka/protocol/schemas/resources/CreateAclsResponse.json +37 -0
  263. kafka/protocol/schemas/resources/CreatePartitionsRequest.json +47 -0
  264. kafka/protocol/schemas/resources/CreatePartitionsResponse.json +41 -0
  265. kafka/protocol/schemas/resources/CreateTopicsRequest.json +65 -0
  266. kafka/protocol/schemas/resources/CreateTopicsResponse.json +72 -0
  267. kafka/protocol/schemas/resources/DeleteAclsRequest.json +46 -0
  268. kafka/protocol/schemas/resources/DeleteAclsResponse.json +59 -0
  269. kafka/protocol/schemas/resources/DeleteGroupsRequest.json +30 -0
  270. kafka/protocol/schemas/resources/DeleteGroupsResponse.json +36 -0
  271. kafka/protocol/schemas/resources/DeleteRecordsRequest.json +42 -0
  272. kafka/protocol/schemas/resources/DeleteRecordsResponse.json +43 -0
  273. kafka/protocol/schemas/resources/DeleteTopicsRequest.json +43 -0
  274. kafka/protocol/schemas/resources/DeleteTopicsResponse.json +52 -0
  275. kafka/protocol/schemas/resources/DescribeAclsRequest.json +43 -0
  276. kafka/protocol/schemas/resources/DescribeAclsResponse.json +55 -0
  277. kafka/protocol/schemas/resources/DescribeClientQuotasRequest.json +37 -0
  278. kafka/protocol/schemas/resources/DescribeClientQuotasResponse.json +47 -0
  279. kafka/protocol/schemas/resources/DescribeClusterRequest.json +35 -0
  280. kafka/protocol/schemas/resources/DescribeClusterResponse.json +56 -0
  281. kafka/protocol/schemas/resources/DescribeConfigsRequest.json +42 -0
  282. kafka/protocol/schemas/resources/DescribeConfigsResponse.json +69 -0
  283. kafka/protocol/schemas/resources/DescribeGroupsRequest.json +38 -0
  284. kafka/protocol/schemas/resources/DescribeGroupsResponse.json +74 -0
  285. kafka/protocol/schemas/resources/DescribeLogDirsRequest.json +38 -0
  286. kafka/protocol/schemas/resources/DescribeLogDirsResponse.json +65 -0
  287. kafka/protocol/schemas/resources/DescribeProducersRequest.json +32 -0
  288. kafka/protocol/schemas/resources/DescribeProducersResponse.json +55 -0
  289. kafka/protocol/schemas/resources/DescribeQuorumRequest.json +39 -0
  290. kafka/protocol/schemas/resources/DescribeQuorumResponse.json +82 -0
  291. kafka/protocol/schemas/resources/DescribeTopicPartitionsRequest.json +40 -0
  292. kafka/protocol/schemas/resources/DescribeTopicPartitionsResponse.json +66 -0
  293. kafka/protocol/schemas/resources/DescribeTransactionsRequest.json +27 -0
  294. kafka/protocol/schemas/resources/DescribeTransactionsResponse.json +52 -0
  295. kafka/protocol/schemas/resources/DescribeUserScramCredentialsRequest.json +30 -0
  296. kafka/protocol/schemas/resources/DescribeUserScramCredentialsResponse.json +45 -0
  297. kafka/protocol/schemas/resources/ElectLeadersRequest.json +41 -0
  298. kafka/protocol/schemas/resources/ElectLeadersResponse.json +45 -0
  299. kafka/protocol/schemas/resources/EndTxnRequest.json +43 -0
  300. kafka/protocol/schemas/resources/EndTxnResponse.json +41 -0
  301. kafka/protocol/schemas/resources/FetchRequest.json +125 -0
  302. kafka/protocol/schemas/resources/FetchResponse.json +124 -0
  303. kafka/protocol/schemas/resources/FindCoordinatorRequest.json +43 -0
  304. kafka/protocol/schemas/resources/FindCoordinatorResponse.json +58 -0
  305. kafka/protocol/schemas/resources/HeartbeatRequest.json +39 -0
  306. kafka/protocol/schemas/resources/HeartbeatResponse.json +35 -0
  307. kafka/protocol/schemas/resources/IncrementalAlterConfigsRequest.json +44 -0
  308. kafka/protocol/schemas/resources/IncrementalAlterConfigsResponse.json +38 -0
  309. kafka/protocol/schemas/resources/InitProducerIdRequest.json +50 -0
  310. kafka/protocol/schemas/resources/InitProducerIdResponse.json +47 -0
  311. kafka/protocol/schemas/resources/JoinGroupRequest.json +63 -0
  312. kafka/protocol/schemas/resources/JoinGroupResponse.json +69 -0
  313. kafka/protocol/schemas/resources/LeaveGroupRequest.json +47 -0
  314. kafka/protocol/schemas/resources/LeaveGroupResponse.json +47 -0
  315. kafka/protocol/schemas/resources/ListConfigResourcesRequest.json +31 -0
  316. kafka/protocol/schemas/resources/ListConfigResourcesResponse.json +37 -0
  317. kafka/protocol/schemas/resources/ListGroupsRequest.json +36 -0
  318. kafka/protocol/schemas/resources/ListGroupsResponse.json +49 -0
  319. kafka/protocol/schemas/resources/ListOffsetsRequest.json +72 -0
  320. kafka/protocol/schemas/resources/ListOffsetsResponse.json +71 -0
  321. kafka/protocol/schemas/resources/ListPartitionReassignmentsRequest.json +34 -0
  322. kafka/protocol/schemas/resources/ListPartitionReassignmentsResponse.json +46 -0
  323. kafka/protocol/schemas/resources/ListTransactionsRequest.json +40 -0
  324. kafka/protocol/schemas/resources/ListTransactionsResponse.json +42 -0
  325. kafka/protocol/schemas/resources/MetadataRequest.json +56 -0
  326. kafka/protocol/schemas/resources/MetadataResponse.json +101 -0
  327. kafka/protocol/schemas/resources/OffsetCommitRequest.json +76 -0
  328. kafka/protocol/schemas/resources/OffsetCommitResponse.json +71 -0
  329. kafka/protocol/schemas/resources/OffsetDeleteRequest.json +39 -0
  330. kafka/protocol/schemas/resources/OffsetDeleteResponse.json +42 -0
  331. kafka/protocol/schemas/resources/OffsetFetchRequest.json +76 -0
  332. kafka/protocol/schemas/resources/OffsetFetchResponse.json +107 -0
  333. kafka/protocol/schemas/resources/OffsetForLeaderEpochRequest.json +52 -0
  334. kafka/protocol/schemas/resources/OffsetForLeaderEpochResponse.json +51 -0
  335. kafka/protocol/schemas/resources/ProduceRequest.json +73 -0
  336. kafka/protocol/schemas/resources/ProduceResponse.json +96 -0
  337. kafka/protocol/schemas/resources/RequestHeader.json +44 -0
  338. kafka/protocol/schemas/resources/ResponseHeader.json +26 -0
  339. kafka/protocol/schemas/resources/SaslAuthenticateRequest.json +29 -0
  340. kafka/protocol/schemas/resources/SaslAuthenticateResponse.json +34 -0
  341. kafka/protocol/schemas/resources/SaslHandshakeRequest.json +31 -0
  342. kafka/protocol/schemas/resources/SaslHandshakeResponse.json +32 -0
  343. kafka/protocol/schemas/resources/SyncGroupRequest.json +56 -0
  344. kafka/protocol/schemas/resources/SyncGroupResponse.json +46 -0
  345. kafka/protocol/schemas/resources/TxnOffsetCommitRequest.json +68 -0
  346. kafka/protocol/schemas/resources/TxnOffsetCommitResponse.json +47 -0
  347. kafka/protocol/schemas/resources/UpdateFeaturesRequest.json +43 -0
  348. kafka/protocol/schemas/resources/UpdateFeaturesResponse.json +39 -0
  349. kafka/protocol/schemas/resources/WriteTxnMarkersRequest.json +49 -0
  350. kafka/protocol/schemas/resources/WriteTxnMarkersResponse.json +45 -0
  351. kafka/protocol/schemas/resources/__init__.py +0 -0
  352. kafka/record/__init__.py +3 -0
  353. kafka/record/_crc32c.py +161 -0
  354. kafka/record/abc.py +144 -0
  355. kafka/record/default_records.py +782 -0
  356. kafka/record/legacy_records.py +587 -0
  357. kafka/record/memory_records.py +255 -0
  358. kafka/record/util.py +135 -0
  359. kafka/serializer/__init__.py +4 -0
  360. kafka/serializer/abstract.py +20 -0
  361. kafka/serializer/default.py +16 -0
  362. kafka/serializer/json.py +17 -0
  363. kafka/serializer/wrapper.py +21 -0
  364. kafka/structs.py +69 -0
  365. kafka/util.py +159 -0
  366. kafka/vendor/__init__.py +0 -0
  367. kafka/version.py +1 -0
  368. kafka_python-3.0.0.dist-info/METADATA +319 -0
  369. kafka_python-3.0.0.dist-info/RECORD +373 -0
  370. kafka_python-3.0.0.dist-info/WHEEL +5 -0
  371. kafka_python-3.0.0.dist-info/entry_points.txt +2 -0
  372. kafka_python-3.0.0.dist-info/licenses/LICENSE +202 -0
  373. kafka_python-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,447 @@
1
+ #!/usr/bin/env python3
2
+ """Benchmark old (Struct-based) vs new (JSON/ApiMessage-based) protocol encode/decode.
3
+
4
+ Benchmarks focus on realistic client operations:
5
+ - Encode: Request objects (what the client sends)
6
+ - Decode: Response objects (what the client receives)
7
+
8
+ Usage:
9
+ python kafka/benchmarks/protocol_old_vs_new.py [--fast] [--quiet]
10
+
11
+ --fast Use pyperf fast mode (fewer iterations, less stable)
12
+ --quiet Suppress per-benchmark warnings
13
+
14
+ Comparison tables are printed after all benchmarks complete.
15
+ """
16
+
17
+ import io
18
+ import sys
19
+
20
+ import pyperf
21
+
22
+ # === Old system imports ===
23
+ from kafka.protocol.old.api_versions import (
24
+ ApiVersionsRequest_v0 as OldApiVersionsReq_v0,
25
+ ApiVersionsRequest_v3 as OldApiVersionsReq_v3,
26
+ ApiVersionsResponse_v0 as OldApiVersionsResp_v0,
27
+ )
28
+ from kafka.protocol.old.fetch import (
29
+ FetchRequest_v4 as OldFetchReq_v4,
30
+ FetchResponse_v4 as OldFetchResp_v4,
31
+ )
32
+ from kafka.protocol.old.produce import (
33
+ ProduceRequest_v3 as OldProduceReq_v3,
34
+ ProduceResponse_v3 as OldProduceResp_v3,
35
+ )
36
+
37
+ # === New system imports ===
38
+ from kafka.protocol.metadata.api_versions import (
39
+ ApiVersionsRequest as NewApiVersionsReq,
40
+ ApiVersionsResponse as NewApiVersionsResp,
41
+ )
42
+ from kafka.protocol.consumer.fetch import (
43
+ FetchRequest as NewFetchReq,
44
+ FetchResponse as NewFetchResp,
45
+ )
46
+ from kafka.protocol.producer.produce import (
47
+ ProduceRequest as NewProduceReq,
48
+ ProduceResponse as NewProduceResp,
49
+ )
50
+
51
+
52
+ # ---------------------------------------------------------------------------
53
+ # Test data
54
+ # ---------------------------------------------------------------------------
55
+
56
+ _RECORDS_BYTES = b'\x00' * 1024
57
+
58
+ # FetchRequest v4: 5 topics, 3 partitions each
59
+ _FETCH_REQ_TOPICS_V4 = [
60
+ ('test-topic-%d' % t, [
61
+ (p, p * 1000, 1048576) # partition, fetch_offset, partition_max_bytes
62
+ for p in range(3)
63
+ ])
64
+ for t in range(5)
65
+ ]
66
+
67
+ # FetchRequest v12 (flexible): 5 topics, 3 partitions each
68
+ _FetchPartition = NewFetchReq.FetchTopic.FetchPartition
69
+ _FETCH_REQ_TOPICS_V12 = [
70
+ NewFetchReq.FetchTopic(version=12, topic='test-topic-%d' % t, partitions=[
71
+ _FetchPartition(version=12, partition=p, current_leader_epoch=-1,
72
+ fetch_offset=p * 1000, last_fetched_epoch=-1,
73
+ log_start_offset=0, partition_max_bytes=1048576)
74
+ for p in range(3)
75
+ ])
76
+ for t in range(5)
77
+ ]
78
+
79
+ # ProduceRequest v3: 5 topics, 3 partitions each, 1KB records per partition
80
+ _PRODUCE_REQ_TOPICS = [
81
+ ('test-topic-%d' % t, [
82
+ (p, _RECORDS_BYTES) # index, records
83
+ for p in range(3)
84
+ ])
85
+ for t in range(5)
86
+ ]
87
+
88
+ # FetchResponse v4: 5 topics, 3 partitions each, 1KB records per partition
89
+ _FETCH_RESP_TOPICS_V4 = [
90
+ ('test-topic-%d' % t, [
91
+ (p, 0, 1000 + p, 999 + p, None, _RECORDS_BYTES)
92
+ for p in range(3)
93
+ ])
94
+ for t in range(5)
95
+ ]
96
+
97
+ # FetchResponse v12 (flexible): 5 topics, 3 partitions each, 1KB records per partition
98
+ _FetchRespTopic = NewFetchResp.FetchableTopicResponse
99
+ _FetchRespPart = _FetchRespTopic.PartitionData
100
+ _FETCH_RESP_TOPICS_V12 = [
101
+ _FetchRespTopic(version=12, topic='test-topic-%d' % t, partitions=[
102
+ _FetchRespPart(version=12, partition_index=p, error_code=0,
103
+ high_watermark=1000 + p, last_stable_offset=999 + p,
104
+ log_start_offset=0, aborted_transactions=[],
105
+ records=_RECORDS_BYTES, preferred_read_replica=-1)
106
+ for p in range(3)
107
+ ])
108
+ for t in range(5)
109
+ ]
110
+
111
+ # ProduceResponse v3: 5 topics, 3 partitions each
112
+ _PRODUCE_RESP_TOPICS_V3 = [
113
+ ('test-topic-%d' % t, [
114
+ (p, 0, p * 1000, -1) # index, error_code, base_offset, log_append_time_ms
115
+ for p in range(3)
116
+ ])
117
+ for t in range(5)
118
+ ]
119
+
120
+ # ProduceResponse v9 (flexible): 5 topics, 3 partitions each
121
+ _ProduceRespTopic = NewProduceResp.TopicProduceResponse
122
+ _ProduceRespPart = _ProduceRespTopic.PartitionProduceResponse
123
+ _PRODUCE_RESP_TOPICS_V9 = [
124
+ _ProduceRespTopic(version=9, name='test-topic-%d' % t, partition_responses=[
125
+ _ProduceRespPart(version=9, index=p, error_code=0, base_offset=p * 1000,
126
+ log_append_time_ms=-1, log_start_offset=p * 500,
127
+ record_errors=[], error_message=None)
128
+ for p in range(3)
129
+ ])
130
+ for t in range(5)
131
+ ]
132
+
133
+ # ApiVersions: 50 api keys
134
+ _API_KEYS_DATA = [(i, 0, i + 3) for i in range(50)]
135
+
136
+
137
+ # ---------------------------------------------------------------------------
138
+ # Encode objects (Requests)
139
+ # ---------------------------------------------------------------------------
140
+
141
+ OLD_APIVER_REQ_V0 = OldApiVersionsReq_v0()
142
+ NEW_APIVER_REQ_V0 = NewApiVersionsReq(version=0)
143
+
144
+ OLD_APIVER_REQ_V3 = OldApiVersionsReq_v3(
145
+ client_software_name='kafka-python',
146
+ client_software_version='3.0.0',
147
+ )
148
+ NEW_APIVER_REQ_V3 = NewApiVersionsReq(
149
+ version=3,
150
+ client_software_name='kafka-python',
151
+ client_software_version='3.0.0',
152
+ )
153
+
154
+ OLD_FETCH_REQ_V4 = OldFetchReq_v4(
155
+ replica_id=-1,
156
+ max_wait_ms=500,
157
+ min_bytes=1,
158
+ max_bytes=10485760,
159
+ isolation_level=0,
160
+ topics=_FETCH_REQ_TOPICS_V4,
161
+ )
162
+ NEW_FETCH_REQ_V4 = NewFetchReq(
163
+ version=4,
164
+ replica_id=-1,
165
+ max_wait_ms=500,
166
+ min_bytes=1,
167
+ max_bytes=10485760,
168
+ isolation_level=0,
169
+ topics=_FETCH_REQ_TOPICS_V4,
170
+ )
171
+ NEW_FETCH_REQ_V12 = NewFetchReq(
172
+ version=12,
173
+ max_wait_ms=500,
174
+ min_bytes=1,
175
+ max_bytes=10485760,
176
+ isolation_level=0,
177
+ session_id=0,
178
+ session_epoch=-1,
179
+ topics=_FETCH_REQ_TOPICS_V12,
180
+ forgotten_topics_data=[],
181
+ rack_id='',
182
+ )
183
+
184
+ OLD_PRODUCE_REQ_V3 = OldProduceReq_v3(
185
+ transactional_id=None,
186
+ acks=-1,
187
+ timeout_ms=30000,
188
+ topic_data=_PRODUCE_REQ_TOPICS,
189
+ )
190
+ NEW_PRODUCE_REQ_V3 = NewProduceReq(
191
+ version=3,
192
+ transactional_id=None,
193
+ acks=-1,
194
+ timeout_ms=30000,
195
+ topic_data=_PRODUCE_REQ_TOPICS,
196
+ )
197
+ NEW_PRODUCE_REQ_V9 = NewProduceReq(
198
+ version=9,
199
+ transactional_id=None,
200
+ acks=-1,
201
+ timeout_ms=30000,
202
+ topic_data=_PRODUCE_REQ_TOPICS,
203
+ )
204
+
205
+
206
+ # ---------------------------------------------------------------------------
207
+ # Decode objects (Responses) - pre-encode bytes from old system
208
+ # ---------------------------------------------------------------------------
209
+
210
+ OLD_APIVER_RESP_V0 = OldApiVersionsResp_v0(
211
+ error_code=0,
212
+ api_keys=_API_KEYS_DATA,
213
+ )
214
+ NEW_APIVER_RESP_V0 = NewApiVersionsResp(
215
+ version=0,
216
+ error_code=0,
217
+ api_keys=_API_KEYS_DATA,
218
+ )
219
+
220
+ OLD_FETCH_RESP_V4 = OldFetchResp_v4(
221
+ throttle_time_ms=0,
222
+ responses=_FETCH_RESP_TOPICS_V4,
223
+ )
224
+ NEW_FETCH_RESP_V4 = NewFetchResp(
225
+ version=4,
226
+ throttle_time_ms=0,
227
+ responses=_FETCH_RESP_TOPICS_V4,
228
+ )
229
+ NEW_FETCH_RESP_V12 = NewFetchResp(
230
+ version=12,
231
+ throttle_time_ms=0,
232
+ error_code=0,
233
+ session_id=0,
234
+ responses=_FETCH_RESP_TOPICS_V12,
235
+ )
236
+
237
+ OLD_PRODUCE_RESP_V3 = OldProduceResp_v3(
238
+ responses=_PRODUCE_RESP_TOPICS_V3,
239
+ throttle_time_ms=0,
240
+ )
241
+ NEW_PRODUCE_RESP_V3 = NewProduceResp(
242
+ version=3,
243
+ responses=_PRODUCE_RESP_TOPICS_V3,
244
+ throttle_time_ms=0,
245
+ )
246
+ NEW_PRODUCE_RESP_V9 = NewProduceResp(
247
+ version=9,
248
+ responses=_PRODUCE_RESP_TOPICS_V9,
249
+ throttle_time_ms=0,
250
+ )
251
+
252
+ ENCODED_APIVER_RESP_V0 = OLD_APIVER_RESP_V0.encode()
253
+ ENCODED_FETCH_RESP_V4 = OLD_FETCH_RESP_V4.encode()
254
+ ENCODED_PRODUCE_RESP_V3 = OLD_PRODUCE_RESP_V3.encode()
255
+ ENCODED_FETCH_RESP_V12 = NEW_FETCH_RESP_V12.encode(version=12)
256
+ ENCODED_PRODUCE_RESP_V9 = NEW_PRODUCE_RESP_V9.encode(version=9)
257
+
258
+
259
+ # ---------------------------------------------------------------------------
260
+ # Correctness assertions
261
+ # ---------------------------------------------------------------------------
262
+
263
+ assert OLD_APIVER_REQ_V0.encode() == NEW_APIVER_REQ_V0.encode(version=0), \
264
+ "ApiVersionsRequest v0 encode mismatch!"
265
+ assert OLD_APIVER_REQ_V3.encode() == NEW_APIVER_REQ_V3.encode(version=3), \
266
+ "ApiVersionsRequest v3 encode mismatch!"
267
+ assert OLD_FETCH_REQ_V4.encode() == NEW_FETCH_REQ_V4.encode(version=4), \
268
+ "FetchRequest v4 encode mismatch!"
269
+ assert OLD_PRODUCE_REQ_V3.encode() == NEW_PRODUCE_REQ_V3.encode(version=3), \
270
+ "ProduceRequest v3 encode mismatch!"
271
+ assert OLD_APIVER_RESP_V0.encode() == NEW_APIVER_RESP_V0.encode(version=0), \
272
+ "ApiVersionsResponse v0 encode mismatch!"
273
+ assert OLD_FETCH_RESP_V4.encode() == NEW_FETCH_RESP_V4.encode(version=4), \
274
+ "FetchResponse v4 encode mismatch!"
275
+ assert OLD_PRODUCE_RESP_V3.encode() == NEW_PRODUCE_RESP_V3.encode(version=3), \
276
+ "ProduceResponse v3 encode mismatch!"
277
+
278
+
279
+ # ---------------------------------------------------------------------------
280
+ # bench_time_func helpers
281
+ # ---------------------------------------------------------------------------
282
+
283
+ def _make_bench_func(func, *args, **kwargs):
284
+ def bench(loops):
285
+ t0 = pyperf.perf_counter()
286
+ for _ in range(loops):
287
+ func(*args, **kwargs)
288
+ return pyperf.perf_counter() - t0
289
+ return bench
290
+
291
+
292
+ def _make_decode_func(cls, encoded, **kwargs):
293
+ def bench(loops):
294
+ t0 = pyperf.perf_counter()
295
+ for _ in range(loops):
296
+ cls.decode(io.BytesIO(encoded), **kwargs)
297
+ return pyperf.perf_counter() - t0
298
+ return bench
299
+
300
+
301
+ # ---------------------------------------------------------------------------
302
+ # Benchmark definitions
303
+ # ---------------------------------------------------------------------------
304
+
305
+ BENCHMARKS = {
306
+ 'encode (requests)': [
307
+ ('ApiVersionsReq v0 (simple)',
308
+ 'encode_ApiVersionsReq_v0_old', _make_bench_func(OLD_APIVER_REQ_V0.encode),
309
+ 'encode_ApiVersionsReq_v0_new', _make_bench_func(NEW_APIVER_REQ_V0.encode, version=0)),
310
+ ('ApiVersionsReq v3 (flexible)',
311
+ 'encode_ApiVersionsReq_v3_old', _make_bench_func(OLD_APIVER_REQ_V3.encode),
312
+ 'encode_ApiVersionsReq_v3_new', _make_bench_func(NEW_APIVER_REQ_V3.encode, version=3)),
313
+ ('FetchReq v4',
314
+ 'encode_FetchReq_v4_old', _make_bench_func(OLD_FETCH_REQ_V4.encode),
315
+ 'encode_FetchReq_v4_new', _make_bench_func(NEW_FETCH_REQ_V4.encode, version=4)),
316
+ ('FetchReq v12 (flexible)',
317
+ None, None,
318
+ 'encode_FetchReq_v12_new', _make_bench_func(NEW_FETCH_REQ_V12.encode, version=12)),
319
+ ('ProduceReq v3',
320
+ 'encode_ProduceReq_v3_old', _make_bench_func(OLD_PRODUCE_REQ_V3.encode),
321
+ 'encode_ProduceReq_v3_new', _make_bench_func(NEW_PRODUCE_REQ_V3.encode, version=3)),
322
+ ('ProduceReq v9 (flexible)',
323
+ None, None,
324
+ 'encode_ProduceReq_v9_new', _make_bench_func(NEW_PRODUCE_REQ_V9.encode, version=9)),
325
+ ],
326
+ 'decode (responses)': [
327
+ ('ApiVersionsResp v0 (simple)',
328
+ 'decode_ApiVersionsResp_v0_old', _make_decode_func(OldApiVersionsResp_v0, ENCODED_APIVER_RESP_V0),
329
+ 'decode_ApiVersionsResp_v0_new', _make_decode_func(NewApiVersionsResp, ENCODED_APIVER_RESP_V0, version=0)),
330
+ ('ProduceResp v3',
331
+ 'decode_ProduceResp_v3_old', _make_decode_func(OldProduceResp_v3, ENCODED_PRODUCE_RESP_V3),
332
+ 'decode_ProduceResp_v3_new', _make_decode_func(NewProduceResp, ENCODED_PRODUCE_RESP_V3, version=3)),
333
+ ('ProduceResp v9 (flexible)',
334
+ None, None,
335
+ 'decode_ProduceResp_v9_new', _make_decode_func(NewProduceResp, ENCODED_PRODUCE_RESP_V9, version=9)),
336
+ ('FetchResp v4',
337
+ 'decode_FetchResp_v4_old', _make_decode_func(OldFetchResp_v4, ENCODED_FETCH_RESP_V4),
338
+ 'decode_FetchResp_v4_new', _make_decode_func(NewFetchResp, ENCODED_FETCH_RESP_V4, version=4)),
339
+ ('FetchResp v12 (flexible)',
340
+ None, None,
341
+ 'decode_FetchResp_v12_new', _make_decode_func(NewFetchResp, ENCODED_FETCH_RESP_V12, version=12)),
342
+ ],
343
+ }
344
+
345
+
346
+ # ---------------------------------------------------------------------------
347
+ # Formatting helpers
348
+ # ---------------------------------------------------------------------------
349
+
350
+ def _format_time(seconds):
351
+ """Format seconds into a human-readable string with appropriate unit."""
352
+ us = seconds * 1e6
353
+ if us >= 1000:
354
+ return '%.0f us' % us
355
+ elif us >= 100:
356
+ return '%.0f us' % us
357
+ elif us >= 10:
358
+ return '%.1f us' % us
359
+ else:
360
+ return '%.2f us' % us
361
+
362
+
363
+ def _print_table(title, rows):
364
+ """Print a markdown-style table."""
365
+ print()
366
+ print('### %s' % title)
367
+ print()
368
+ col1 = max(len(r[0]) for r in rows)
369
+ col1 = max(col1, len('Message'))
370
+ header = '| %-*s | %10s | %10s | %5s |' % (col1, 'Message', 'Old', 'New', 'Ratio')
371
+ sep = '|%s|%s|%s|%s|' % ('-' * (col1 + 2), '-' * 12, '-' * 12, '-' * 7)
372
+ print(header)
373
+ print(sep)
374
+ for desc, old_mean, new_mean in rows:
375
+ if old_mean is not None:
376
+ ratio = new_mean / old_mean if old_mean > 0 else float('inf')
377
+ print('| %-*s | %10s | %10s | %5.1fx |' % (
378
+ col1, desc,
379
+ _format_time(old_mean),
380
+ _format_time(new_mean),
381
+ ratio))
382
+ else:
383
+ print('| %-*s | %10s | %10s | %5s |' % (
384
+ col1, desc, 'n/a', _format_time(new_mean), 'n/a'))
385
+
386
+
387
+ def _print_summary(results):
388
+ """Print comparison tables from collected benchmark results."""
389
+ print()
390
+ print('=' * 70)
391
+ print('Protocol Benchmark: Old (Struct) vs New (ApiMessage)')
392
+ print('=' * 70)
393
+
394
+ for category, bench_defs in BENCHMARKS.items():
395
+ rows = []
396
+ for entry in bench_defs:
397
+ desc, old_name, _, new_name, _ = entry
398
+ if new_name in results:
399
+ old_val = results.get(old_name) if old_name else None
400
+ rows.append((desc, old_val, results[new_name]))
401
+ if rows:
402
+ _print_table(category.capitalize(), rows)
403
+
404
+ print()
405
+ print('### Summary')
406
+ print()
407
+ for category in BENCHMARKS:
408
+ ratios = []
409
+ for entry in BENCHMARKS[category]:
410
+ desc, old_name, _, new_name, _ = entry
411
+ if old_name and old_name in results and new_name in results:
412
+ old_val = results[old_name]
413
+ new_val = results[new_name]
414
+ ratios.append(new_val / old_val if old_val > 0 else float('inf'))
415
+ if ratios:
416
+ min_r = min(ratios)
417
+ max_r = max(ratios)
418
+ print('- **%s**: %.1fx - %.1fx (new / old)' % (
419
+ category.capitalize(), min_r, max_r))
420
+ print()
421
+
422
+
423
+ # ---------------------------------------------------------------------------
424
+ # Main
425
+ # ---------------------------------------------------------------------------
426
+
427
+ if __name__ == '__main__':
428
+ runner = pyperf.Runner()
429
+ results = {}
430
+
431
+ def _record(name, bench):
432
+ if bench is not None:
433
+ try:
434
+ results[name] = bench.mean()
435
+ except Exception:
436
+ pass
437
+
438
+ for category, bench_defs in BENCHMARKS.items():
439
+ for entry in bench_defs:
440
+ desc, old_name, old_func, new_name, new_func = entry
441
+ if old_name is not None:
442
+ _record(old_name, runner.bench_time_func(old_name, old_func))
443
+ _record(new_name, runner.bench_time_func(new_name, new_func))
444
+
445
+ # Only print summary in the manager process (workers have --worker in argv)
446
+ if results and '--worker' not in sys.argv:
447
+ _print_summary(results)
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env python3
2
+ import hashlib
3
+ import itertools
4
+ import os
5
+ import random
6
+
7
+ import pyperf
8
+
9
+ from kafka.record.memory_records import MemoryRecordsBuilder
10
+
11
+
12
+ DEFAULT_BATCH_SIZE = 1600 * 1024
13
+ KEY_SIZE = 6
14
+ VALUE_SIZE = 60
15
+ TIMESTAMP_RANGE = [1505824130000, 1505824140000]
16
+
17
+ # With values above v1 record is 100 bytes, so 10 000 bytes for 100 messages
18
+ MESSAGES_PER_BATCH = 100
19
+
20
+
21
+ def random_bytes(length):
22
+ buffer = bytearray(length)
23
+ for i in range(length):
24
+ buffer[i] = random.randint(0, 255)
25
+ return bytes(buffer)
26
+
27
+
28
+ def prepare():
29
+ return iter(itertools.cycle([
30
+ (random_bytes(KEY_SIZE),
31
+ random_bytes(VALUE_SIZE),
32
+ random.randint(*TIMESTAMP_RANGE)
33
+ )
34
+ for _ in range(int(MESSAGES_PER_BATCH * 1.94))
35
+ ]))
36
+
37
+
38
+ def finalize(results):
39
+ # Just some strange code to make sure PyPy does execute the main code
40
+ # properly, without optimizing it away
41
+ hash_val = hashlib.md5()
42
+ for buf in results:
43
+ hash_val.update(buf)
44
+ print(hash_val, file=open(os.devnull, "w"))
45
+
46
+
47
+ def func(loops, magic):
48
+ # Jit can optimize out the whole function if the result is the same each
49
+ # time, so we need some randomized input data )
50
+ precomputed_samples = prepare()
51
+ results = []
52
+
53
+ # Main benchmark code.
54
+ t0 = pyperf.perf_counter()
55
+ for _ in range(loops):
56
+ batch = MemoryRecordsBuilder(
57
+ magic, batch_size=DEFAULT_BATCH_SIZE, compression_type=0)
58
+ for _ in range(MESSAGES_PER_BATCH):
59
+ key, value, timestamp = next(precomputed_samples)
60
+ size = batch.append(
61
+ timestamp=timestamp, key=key, value=value)
62
+ assert size
63
+ batch.close()
64
+ results.append(batch.buffer())
65
+
66
+ res = pyperf.perf_counter() - t0
67
+
68
+ finalize(results)
69
+
70
+ return res
71
+
72
+
73
+ if __name__ == '__main__':
74
+ runner = pyperf.Runner()
75
+ runner.bench_time_func('batch_append_v0', func, 0)
76
+ runner.bench_time_func('batch_append_v1', func, 1)
77
+ runner.bench_time_func('batch_append_v2', func, 2)
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python
2
+ import hashlib
3
+ import itertools
4
+ import os
5
+ import random
6
+
7
+ import pyperf
8
+
9
+ from kafka.record.memory_records import MemoryRecords, MemoryRecordsBuilder
10
+
11
+
12
+ DEFAULT_BATCH_SIZE = 1600 * 1024
13
+ KEY_SIZE = 6
14
+ VALUE_SIZE = 60
15
+ TIMESTAMP_RANGE = [1505824130000, 1505824140000]
16
+
17
+ BATCH_SAMPLES = 5
18
+ MESSAGES_PER_BATCH = 100
19
+
20
+
21
+ def random_bytes(length):
22
+ buffer = bytearray(length)
23
+ for i in range(length):
24
+ buffer[i] = random.randint(0, 255)
25
+ return bytes(buffer)
26
+
27
+
28
+ def prepare(magic):
29
+ samples = []
30
+ for _ in range(BATCH_SAMPLES):
31
+ batch = MemoryRecordsBuilder(
32
+ magic, batch_size=DEFAULT_BATCH_SIZE, compression_type=0)
33
+ for _ in range(MESSAGES_PER_BATCH):
34
+ size = batch.append(
35
+ random.randint(*TIMESTAMP_RANGE),
36
+ random_bytes(KEY_SIZE),
37
+ random_bytes(VALUE_SIZE),
38
+ headers=[])
39
+ assert size
40
+ batch.close()
41
+ samples.append(bytes(batch.buffer()))
42
+
43
+ return iter(itertools.cycle(samples))
44
+
45
+
46
+ def finalize(results):
47
+ # Just some strange code to make sure PyPy does execute the code above
48
+ # properly
49
+ hash_val = hashlib.md5()
50
+ for buf in results:
51
+ hash_val.update(buf)
52
+ print(hash_val, file=open(os.devnull, "w"))
53
+
54
+
55
+ def func(loops, magic):
56
+ # Jit can optimize out the whole function if the result is the same each
57
+ # time, so we need some randomized input data )
58
+ precomputed_samples = prepare(magic)
59
+ results = []
60
+
61
+ # Main benchmark code.
62
+ batch_data = next(precomputed_samples)
63
+ t0 = pyperf.perf_counter()
64
+ for _ in range(loops):
65
+ records = MemoryRecords(batch_data)
66
+ while records.has_next():
67
+ batch = records.next_batch()
68
+ batch.validate_crc()
69
+ for record in batch:
70
+ results.append(record.value)
71
+
72
+ res = pyperf.perf_counter() - t0
73
+ finalize(results)
74
+
75
+ return res
76
+
77
+
78
+ if __name__ == '__main__':
79
+ runner = pyperf.Runner()
80
+ runner.bench_time_func('batch_read_v0', func, 0)
81
+ runner.bench_time_func('batch_read_v1', func, 1)
82
+ runner.bench_time_func('batch_read_v2', func, 2)