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.
- kafka/__init__.py +34 -0
- kafka/__main__.py +5 -0
- kafka/admin/__init__.py +29 -0
- kafka/admin/__main__.py +5 -0
- kafka/admin/_acls.py +355 -0
- kafka/admin/_cluster.py +359 -0
- kafka/admin/_configs.py +479 -0
- kafka/admin/_groups.py +754 -0
- kafka/admin/_partitions.py +595 -0
- kafka/admin/_topics.py +281 -0
- kafka/admin/_transactions.py +450 -0
- kafka/admin/_users.py +194 -0
- kafka/admin/client.py +373 -0
- kafka/benchmarks/__init__.py +0 -0
- kafka/benchmarks/consumer_performance.py +138 -0
- kafka/benchmarks/load_example.py +109 -0
- kafka/benchmarks/producer_encode_path.py +201 -0
- kafka/benchmarks/producer_performance.py +161 -0
- kafka/benchmarks/profile_protocol.py +138 -0
- kafka/benchmarks/protocol_old_vs_new.py +447 -0
- kafka/benchmarks/record_batch_compose.py +77 -0
- kafka/benchmarks/record_batch_read.py +82 -0
- kafka/benchmarks/varint_speed.py +426 -0
- kafka/cli/__init__.py +36 -0
- kafka/cli/admin/__init__.py +117 -0
- kafka/cli/admin/acls/__init__.py +9 -0
- kafka/cli/admin/acls/common.py +76 -0
- kafka/cli/admin/acls/create.py +19 -0
- kafka/cli/admin/acls/delete.py +23 -0
- kafka/cli/admin/acls/describe.py +16 -0
- kafka/cli/admin/cluster/__init__.py +14 -0
- kafka/cli/admin/cluster/describe.py +11 -0
- kafka/cli/admin/cluster/describe_quorum.py +11 -0
- kafka/cli/admin/cluster/features.py +52 -0
- kafka/cli/admin/cluster/log_dirs.py +43 -0
- kafka/cli/admin/cluster/versions.py +33 -0
- kafka/cli/admin/configs/__init__.py +10 -0
- kafka/cli/admin/configs/alter.py +43 -0
- kafka/cli/admin/configs/common.py +17 -0
- kafka/cli/admin/configs/describe.py +30 -0
- kafka/cli/admin/configs/list.py +16 -0
- kafka/cli/admin/configs/reset.py +20 -0
- kafka/cli/admin/groups/__init__.py +16 -0
- kafka/cli/admin/groups/alter_offsets.py +30 -0
- kafka/cli/admin/groups/delete.py +11 -0
- kafka/cli/admin/groups/delete_offsets.py +29 -0
- kafka/cli/admin/groups/describe.py +11 -0
- kafka/cli/admin/groups/list.py +28 -0
- kafka/cli/admin/groups/list_offsets.py +29 -0
- kafka/cli/admin/groups/remove_members.py +40 -0
- kafka/cli/admin/groups/reset_offsets.py +139 -0
- kafka/cli/admin/partitions/__init__.py +21 -0
- kafka/cli/admin/partitions/alter_reassignments.py +37 -0
- kafka/cli/admin/partitions/create.py +27 -0
- kafka/cli/admin/partitions/delete_records.py +31 -0
- kafka/cli/admin/partitions/describe.py +36 -0
- kafka/cli/admin/partitions/elect_leaders.py +53 -0
- kafka/cli/admin/partitions/list_offsets.py +88 -0
- kafka/cli/admin/partitions/list_reassignments.py +35 -0
- kafka/cli/admin/topics/__init__.py +10 -0
- kafka/cli/admin/topics/create.py +13 -0
- kafka/cli/admin/topics/delete.py +19 -0
- kafka/cli/admin/topics/describe.py +18 -0
- kafka/cli/admin/topics/list.py +11 -0
- kafka/cli/admin/transactions/__init__.py +17 -0
- kafka/cli/admin/transactions/abort.py +38 -0
- kafka/cli/admin/transactions/describe.py +24 -0
- kafka/cli/admin/transactions/describe_producers.py +29 -0
- kafka/cli/admin/transactions/find_hanging.py +26 -0
- kafka/cli/admin/transactions/list.py +37 -0
- kafka/cli/admin/users/__init__.py +8 -0
- kafka/cli/admin/users/alter_user_scram_credentials.py +34 -0
- kafka/cli/admin/users/describe_user_scram_credentials.py +15 -0
- kafka/cli/common.py +95 -0
- kafka/cli/consumer/__init__.py +63 -0
- kafka/cli/producer/__init__.py +57 -0
- kafka/cluster.py +824 -0
- kafka/codec.py +325 -0
- kafka/consumer/__init__.py +5 -0
- kafka/consumer/__main__.py +5 -0
- kafka/consumer/fetcher.py +2012 -0
- kafka/consumer/group.py +1347 -0
- kafka/consumer/subscription_state.py +897 -0
- kafka/coordinator/__init__.py +0 -0
- kafka/coordinator/assignors/__init__.py +0 -0
- kafka/coordinator/assignors/abstract.py +90 -0
- kafka/coordinator/assignors/cooperative_sticky.py +167 -0
- kafka/coordinator/assignors/range.py +81 -0
- kafka/coordinator/assignors/roundrobin.py +101 -0
- kafka/coordinator/assignors/sticky/StickyAssignorUserData.json +37 -0
- kafka/coordinator/assignors/sticky/__init__.py +0 -0
- kafka/coordinator/assignors/sticky/partition_movements.py +149 -0
- kafka/coordinator/assignors/sticky/sorted_set.py +63 -0
- kafka/coordinator/assignors/sticky/sticky_assignor.py +665 -0
- kafka/coordinator/assignors/sticky/user_data.py +8 -0
- kafka/coordinator/base.py +1215 -0
- kafka/coordinator/consumer.py +1224 -0
- kafka/coordinator/heartbeat.py +82 -0
- kafka/coordinator/subscription.py +34 -0
- kafka/errors.py +1004 -0
- kafka/future.py +166 -0
- kafka/metrics/__init__.py +13 -0
- kafka/metrics/compound_stat.py +33 -0
- kafka/metrics/dict_reporter.py +81 -0
- kafka/metrics/kafka_metric.py +36 -0
- kafka/metrics/measurable.py +27 -0
- kafka/metrics/measurable_stat.py +13 -0
- kafka/metrics/metric_config.py +33 -0
- kafka/metrics/metric_name.py +105 -0
- kafka/metrics/metrics.py +261 -0
- kafka/metrics/metrics_reporter.py +53 -0
- kafka/metrics/quota.py +41 -0
- kafka/metrics/stat.py +19 -0
- kafka/metrics/stats/__init__.py +15 -0
- kafka/metrics/stats/avg.py +24 -0
- kafka/metrics/stats/count.py +17 -0
- kafka/metrics/stats/histogram.py +99 -0
- kafka/metrics/stats/max_stat.py +17 -0
- kafka/metrics/stats/min_stat.py +19 -0
- kafka/metrics/stats/percentile.py +14 -0
- kafka/metrics/stats/percentiles.py +75 -0
- kafka/metrics/stats/rate.py +118 -0
- kafka/metrics/stats/sampled_stat.py +99 -0
- kafka/metrics/stats/sensor.py +136 -0
- kafka/metrics/stats/total.py +15 -0
- kafka/net/__init__.py +19 -0
- kafka/net/compat.py +165 -0
- kafka/net/connection.py +593 -0
- kafka/net/http_connect.py +144 -0
- kafka/net/inet.py +122 -0
- kafka/net/manager.py +451 -0
- kafka/net/metrics.py +149 -0
- kafka/net/sasl/__init__.py +32 -0
- kafka/net/sasl/abc.py +28 -0
- kafka/net/sasl/gssapi.py +95 -0
- kafka/net/sasl/msk.py +245 -0
- kafka/net/sasl/oauth.py +98 -0
- kafka/net/sasl/plain.py +42 -0
- kafka/net/sasl/scram.py +135 -0
- kafka/net/sasl/sspi.py +111 -0
- kafka/net/selector.py +644 -0
- kafka/net/socks5.py +262 -0
- kafka/net/transport.py +415 -0
- kafka/net/wakeup_notifier.py +72 -0
- kafka/partitioner/__init__.py +8 -0
- kafka/partitioner/abc.py +8 -0
- kafka/partitioner/default.py +89 -0
- kafka/partitioner/sticky.py +109 -0
- kafka/producer/__init__.py +5 -0
- kafka/producer/__main__.py +5 -0
- kafka/producer/future.py +101 -0
- kafka/producer/kafka.py +1123 -0
- kafka/producer/producer_batch.py +192 -0
- kafka/producer/record_accumulator.py +647 -0
- kafka/producer/sender.py +884 -0
- kafka/producer/transaction_manager.py +1326 -0
- kafka/protocol/__init__.py +0 -0
- kafka/protocol/admin/__init__.py +29 -0
- kafka/protocol/admin/acl.py +83 -0
- kafka/protocol/admin/acl.pyi +375 -0
- kafka/protocol/admin/client_quotas.py +14 -0
- kafka/protocol/admin/client_quotas.pyi +265 -0
- kafka/protocol/admin/cluster.py +31 -0
- kafka/protocol/admin/cluster.pyi +620 -0
- kafka/protocol/admin/configs.py +22 -0
- kafka/protocol/admin/configs.pyi +437 -0
- kafka/protocol/admin/groups.py +24 -0
- kafka/protocol/admin/groups.pyi +261 -0
- kafka/protocol/admin/topics.py +53 -0
- kafka/protocol/admin/topics.pyi +982 -0
- kafka/protocol/admin/transactions.py +18 -0
- kafka/protocol/admin/transactions.pyi +311 -0
- kafka/protocol/admin/users.py +14 -0
- kafka/protocol/admin/users.pyi +223 -0
- kafka/protocol/api_data.py +125 -0
- kafka/protocol/api_header.py +55 -0
- kafka/protocol/api_key.py +97 -0
- kafka/protocol/api_message.py +277 -0
- kafka/protocol/broker_version_data.py +246 -0
- kafka/protocol/consumer/__init__.py +13 -0
- kafka/protocol/consumer/fetch.py +16 -0
- kafka/protocol/consumer/fetch.pyi +298 -0
- kafka/protocol/consumer/group.py +38 -0
- kafka/protocol/consumer/group.pyi +824 -0
- kafka/protocol/consumer/metadata.py +30 -0
- kafka/protocol/consumer/metadata.pyi +89 -0
- kafka/protocol/consumer/offsets.py +75 -0
- kafka/protocol/consumer/offsets.pyi +288 -0
- kafka/protocol/data_container.py +166 -0
- kafka/protocol/frame.py +30 -0
- kafka/protocol/generate_stubs.py +468 -0
- kafka/protocol/metadata/__init__.py +10 -0
- kafka/protocol/metadata/api_versions.py +41 -0
- kafka/protocol/metadata/api_versions.pyi +128 -0
- kafka/protocol/metadata/find_coordinator.py +19 -0
- kafka/protocol/metadata/find_coordinator.pyi +105 -0
- kafka/protocol/metadata/metadata.py +34 -0
- kafka/protocol/metadata/metadata.pyi +160 -0
- kafka/protocol/old/__init__.py +0 -0
- kafka/protocol/old/abstract.py +17 -0
- kafka/protocol/old/add_offsets_to_txn.py +54 -0
- kafka/protocol/old/add_partitions_to_txn.py +71 -0
- kafka/protocol/old/admin.py +1086 -0
- kafka/protocol/old/api.py +205 -0
- kafka/protocol/old/api_versions.py +133 -0
- kafka/protocol/old/commit.py +355 -0
- kafka/protocol/old/consumer_protocol.py +36 -0
- kafka/protocol/old/end_txn.py +53 -0
- kafka/protocol/old/fetch.py +408 -0
- kafka/protocol/old/find_coordinator.py +72 -0
- kafka/protocol/old/group.py +451 -0
- kafka/protocol/old/init_producer_id.py +42 -0
- kafka/protocol/old/list_offsets.py +186 -0
- kafka/protocol/old/metadata.py +290 -0
- kafka/protocol/old/offset_for_leader_epoch.py +133 -0
- kafka/protocol/old/produce.py +247 -0
- kafka/protocol/old/sasl_authenticate.py +38 -0
- kafka/protocol/old/sasl_handshake.py +39 -0
- kafka/protocol/old/struct.py +87 -0
- kafka/protocol/old/txn_offset_commit.py +73 -0
- kafka/protocol/old/types.py +440 -0
- kafka/protocol/parser.py +191 -0
- kafka/protocol/producer/__init__.py +7 -0
- kafka/protocol/producer/produce.py +17 -0
- kafka/protocol/producer/produce.pyi +197 -0
- kafka/protocol/producer/transaction.py +30 -0
- kafka/protocol/producer/transaction.pyi +663 -0
- kafka/protocol/sasl.py +52 -0
- kafka/protocol/sasl.pyi +126 -0
- kafka/protocol/schemas/__init__.py +7 -0
- kafka/protocol/schemas/fields/__init__.py +7 -0
- kafka/protocol/schemas/fields/array.py +127 -0
- kafka/protocol/schemas/fields/base.py +156 -0
- kafka/protocol/schemas/fields/codecs/__init__.py +12 -0
- kafka/protocol/schemas/fields/codecs/encode_buffer.py +82 -0
- kafka/protocol/schemas/fields/codecs/tagged_fields.py +109 -0
- kafka/protocol/schemas/fields/codecs/types.py +505 -0
- kafka/protocol/schemas/fields/codegen.py +40 -0
- kafka/protocol/schemas/fields/simple.py +127 -0
- kafka/protocol/schemas/fields/struct.py +357 -0
- kafka/protocol/schemas/fields/struct_array.py +142 -0
- kafka/protocol/schemas/load_json.py +42 -0
- kafka/protocol/schemas/resources/AddOffsetsToTxnRequest.json +40 -0
- kafka/protocol/schemas/resources/AddOffsetsToTxnResponse.json +35 -0
- kafka/protocol/schemas/resources/AddPartitionsToTxnRequest.json +65 -0
- kafka/protocol/schemas/resources/AddPartitionsToTxnResponse.json +60 -0
- kafka/protocol/schemas/resources/AlterClientQuotasRequest.json +47 -0
- kafka/protocol/schemas/resources/AlterClientQuotasResponse.json +41 -0
- kafka/protocol/schemas/resources/AlterConfigsRequest.json +43 -0
- kafka/protocol/schemas/resources/AlterConfigsResponse.json +39 -0
- kafka/protocol/schemas/resources/AlterPartitionReassignmentsRequest.json +42 -0
- kafka/protocol/schemas/resources/AlterPartitionReassignmentsResponse.json +47 -0
- kafka/protocol/schemas/resources/AlterReplicaLogDirsRequest.json +41 -0
- kafka/protocol/schemas/resources/AlterReplicaLogDirsResponse.json +41 -0
- kafka/protocol/schemas/resources/AlterUserScramCredentialsRequest.json +45 -0
- kafka/protocol/schemas/resources/AlterUserScramCredentialsResponse.json +35 -0
- kafka/protocol/schemas/resources/ApiVersionsRequest.json +34 -0
- kafka/protocol/schemas/resources/ApiVersionsResponse.json +79 -0
- kafka/protocol/schemas/resources/ConsumerProtocolAssignment.json +42 -0
- kafka/protocol/schemas/resources/ConsumerProtocolSubscription.json +49 -0
- kafka/protocol/schemas/resources/CreateAclsRequest.json +46 -0
- kafka/protocol/schemas/resources/CreateAclsResponse.json +37 -0
- kafka/protocol/schemas/resources/CreatePartitionsRequest.json +47 -0
- kafka/protocol/schemas/resources/CreatePartitionsResponse.json +41 -0
- kafka/protocol/schemas/resources/CreateTopicsRequest.json +65 -0
- kafka/protocol/schemas/resources/CreateTopicsResponse.json +72 -0
- kafka/protocol/schemas/resources/DeleteAclsRequest.json +46 -0
- kafka/protocol/schemas/resources/DeleteAclsResponse.json +59 -0
- kafka/protocol/schemas/resources/DeleteGroupsRequest.json +30 -0
- kafka/protocol/schemas/resources/DeleteGroupsResponse.json +36 -0
- kafka/protocol/schemas/resources/DeleteRecordsRequest.json +42 -0
- kafka/protocol/schemas/resources/DeleteRecordsResponse.json +43 -0
- kafka/protocol/schemas/resources/DeleteTopicsRequest.json +43 -0
- kafka/protocol/schemas/resources/DeleteTopicsResponse.json +52 -0
- kafka/protocol/schemas/resources/DescribeAclsRequest.json +43 -0
- kafka/protocol/schemas/resources/DescribeAclsResponse.json +55 -0
- kafka/protocol/schemas/resources/DescribeClientQuotasRequest.json +37 -0
- kafka/protocol/schemas/resources/DescribeClientQuotasResponse.json +47 -0
- kafka/protocol/schemas/resources/DescribeClusterRequest.json +35 -0
- kafka/protocol/schemas/resources/DescribeClusterResponse.json +56 -0
- kafka/protocol/schemas/resources/DescribeConfigsRequest.json +42 -0
- kafka/protocol/schemas/resources/DescribeConfigsResponse.json +69 -0
- kafka/protocol/schemas/resources/DescribeGroupsRequest.json +38 -0
- kafka/protocol/schemas/resources/DescribeGroupsResponse.json +74 -0
- kafka/protocol/schemas/resources/DescribeLogDirsRequest.json +38 -0
- kafka/protocol/schemas/resources/DescribeLogDirsResponse.json +65 -0
- kafka/protocol/schemas/resources/DescribeProducersRequest.json +32 -0
- kafka/protocol/schemas/resources/DescribeProducersResponse.json +55 -0
- kafka/protocol/schemas/resources/DescribeQuorumRequest.json +39 -0
- kafka/protocol/schemas/resources/DescribeQuorumResponse.json +82 -0
- kafka/protocol/schemas/resources/DescribeTopicPartitionsRequest.json +40 -0
- kafka/protocol/schemas/resources/DescribeTopicPartitionsResponse.json +66 -0
- kafka/protocol/schemas/resources/DescribeTransactionsRequest.json +27 -0
- kafka/protocol/schemas/resources/DescribeTransactionsResponse.json +52 -0
- kafka/protocol/schemas/resources/DescribeUserScramCredentialsRequest.json +30 -0
- kafka/protocol/schemas/resources/DescribeUserScramCredentialsResponse.json +45 -0
- kafka/protocol/schemas/resources/ElectLeadersRequest.json +41 -0
- kafka/protocol/schemas/resources/ElectLeadersResponse.json +45 -0
- kafka/protocol/schemas/resources/EndTxnRequest.json +43 -0
- kafka/protocol/schemas/resources/EndTxnResponse.json +41 -0
- kafka/protocol/schemas/resources/FetchRequest.json +125 -0
- kafka/protocol/schemas/resources/FetchResponse.json +124 -0
- kafka/protocol/schemas/resources/FindCoordinatorRequest.json +43 -0
- kafka/protocol/schemas/resources/FindCoordinatorResponse.json +58 -0
- kafka/protocol/schemas/resources/HeartbeatRequest.json +39 -0
- kafka/protocol/schemas/resources/HeartbeatResponse.json +35 -0
- kafka/protocol/schemas/resources/IncrementalAlterConfigsRequest.json +44 -0
- kafka/protocol/schemas/resources/IncrementalAlterConfigsResponse.json +38 -0
- kafka/protocol/schemas/resources/InitProducerIdRequest.json +50 -0
- kafka/protocol/schemas/resources/InitProducerIdResponse.json +47 -0
- kafka/protocol/schemas/resources/JoinGroupRequest.json +63 -0
- kafka/protocol/schemas/resources/JoinGroupResponse.json +69 -0
- kafka/protocol/schemas/resources/LeaveGroupRequest.json +47 -0
- kafka/protocol/schemas/resources/LeaveGroupResponse.json +47 -0
- kafka/protocol/schemas/resources/ListConfigResourcesRequest.json +31 -0
- kafka/protocol/schemas/resources/ListConfigResourcesResponse.json +37 -0
- kafka/protocol/schemas/resources/ListGroupsRequest.json +36 -0
- kafka/protocol/schemas/resources/ListGroupsResponse.json +49 -0
- kafka/protocol/schemas/resources/ListOffsetsRequest.json +72 -0
- kafka/protocol/schemas/resources/ListOffsetsResponse.json +71 -0
- kafka/protocol/schemas/resources/ListPartitionReassignmentsRequest.json +34 -0
- kafka/protocol/schemas/resources/ListPartitionReassignmentsResponse.json +46 -0
- kafka/protocol/schemas/resources/ListTransactionsRequest.json +40 -0
- kafka/protocol/schemas/resources/ListTransactionsResponse.json +42 -0
- kafka/protocol/schemas/resources/MetadataRequest.json +56 -0
- kafka/protocol/schemas/resources/MetadataResponse.json +101 -0
- kafka/protocol/schemas/resources/OffsetCommitRequest.json +76 -0
- kafka/protocol/schemas/resources/OffsetCommitResponse.json +71 -0
- kafka/protocol/schemas/resources/OffsetDeleteRequest.json +39 -0
- kafka/protocol/schemas/resources/OffsetDeleteResponse.json +42 -0
- kafka/protocol/schemas/resources/OffsetFetchRequest.json +76 -0
- kafka/protocol/schemas/resources/OffsetFetchResponse.json +107 -0
- kafka/protocol/schemas/resources/OffsetForLeaderEpochRequest.json +52 -0
- kafka/protocol/schemas/resources/OffsetForLeaderEpochResponse.json +51 -0
- kafka/protocol/schemas/resources/ProduceRequest.json +73 -0
- kafka/protocol/schemas/resources/ProduceResponse.json +96 -0
- kafka/protocol/schemas/resources/RequestHeader.json +44 -0
- kafka/protocol/schemas/resources/ResponseHeader.json +26 -0
- kafka/protocol/schemas/resources/SaslAuthenticateRequest.json +29 -0
- kafka/protocol/schemas/resources/SaslAuthenticateResponse.json +34 -0
- kafka/protocol/schemas/resources/SaslHandshakeRequest.json +31 -0
- kafka/protocol/schemas/resources/SaslHandshakeResponse.json +32 -0
- kafka/protocol/schemas/resources/SyncGroupRequest.json +56 -0
- kafka/protocol/schemas/resources/SyncGroupResponse.json +46 -0
- kafka/protocol/schemas/resources/TxnOffsetCommitRequest.json +68 -0
- kafka/protocol/schemas/resources/TxnOffsetCommitResponse.json +47 -0
- kafka/protocol/schemas/resources/UpdateFeaturesRequest.json +43 -0
- kafka/protocol/schemas/resources/UpdateFeaturesResponse.json +39 -0
- kafka/protocol/schemas/resources/WriteTxnMarkersRequest.json +49 -0
- kafka/protocol/schemas/resources/WriteTxnMarkersResponse.json +45 -0
- kafka/protocol/schemas/resources/__init__.py +0 -0
- kafka/record/__init__.py +3 -0
- kafka/record/_crc32c.py +161 -0
- kafka/record/abc.py +144 -0
- kafka/record/default_records.py +782 -0
- kafka/record/legacy_records.py +587 -0
- kafka/record/memory_records.py +255 -0
- kafka/record/util.py +135 -0
- kafka/serializer/__init__.py +4 -0
- kafka/serializer/abstract.py +20 -0
- kafka/serializer/default.py +16 -0
- kafka/serializer/json.py +17 -0
- kafka/serializer/wrapper.py +21 -0
- kafka/structs.py +69 -0
- kafka/util.py +159 -0
- kafka/vendor/__init__.py +0 -0
- kafka/version.py +1 -0
- kafka_python-3.0.0.dist-info/METADATA +319 -0
- kafka_python-3.0.0.dist-info/RECORD +373 -0
- kafka_python-3.0.0.dist-info/WHEEL +5 -0
- kafka_python-3.0.0.dist-info/entry_points.txt +2 -0
- kafka_python-3.0.0.dist-info/licenses/LICENSE +202 -0
- kafka_python-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Benchmarks for the producer encode hot path.
|
|
3
|
+
|
|
4
|
+
Measures the cost of finalizing a record batch and encoding it into a
|
|
5
|
+
ProduceRequest - the pipeline that runs on every send to the broker.
|
|
6
|
+
|
|
7
|
+
To compare two implementations (e.g. before/after a change) run this
|
|
8
|
+
script twice and diff the output:
|
|
9
|
+
|
|
10
|
+
# baseline
|
|
11
|
+
git stash
|
|
12
|
+
python -m kafka.benchmarks.producer_encode_path -o baseline.json
|
|
13
|
+
git stash pop
|
|
14
|
+
|
|
15
|
+
# new
|
|
16
|
+
python -m kafka.benchmarks.producer_encode_path -o new.json
|
|
17
|
+
|
|
18
|
+
pyperf compare_to baseline.json new.json
|
|
19
|
+
|
|
20
|
+
For an allocation count (tracemalloc) run with --allocations, which is
|
|
21
|
+
a separate mode (not a timing benchmark).
|
|
22
|
+
"""
|
|
23
|
+
import argparse
|
|
24
|
+
import sys
|
|
25
|
+
import tracemalloc
|
|
26
|
+
|
|
27
|
+
import pyperf
|
|
28
|
+
|
|
29
|
+
from kafka.producer.producer_batch import ProducerBatch
|
|
30
|
+
from kafka.record.memory_records import MemoryRecordsBuilder
|
|
31
|
+
from kafka.structs import TopicPartition
|
|
32
|
+
from kafka.protocol.producer import ProduceRequest
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
DEFAULT_RECORDS_PER_BATCH = 100
|
|
36
|
+
DEFAULT_VALUE_SIZE = 128
|
|
37
|
+
DEFAULT_BATCH_SIZE = 1 << 20 # 1 MiB - big enough to hold the largest case
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _build_unclosed_batch(num_records, value_size):
|
|
41
|
+
tp = TopicPartition('bench', 0)
|
|
42
|
+
records = MemoryRecordsBuilder(
|
|
43
|
+
magic=2, compression_type=0, batch_size=DEFAULT_BATCH_SIZE)
|
|
44
|
+
batch = ProducerBatch(tp, records)
|
|
45
|
+
value = b'x' * value_size
|
|
46
|
+
for i in range(num_records):
|
|
47
|
+
future = batch.try_append(i, None, value, [])
|
|
48
|
+
assert future is not None, 'batch too small for %d records' % num_records
|
|
49
|
+
return batch
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _build_closed_batch(num_records, value_size):
|
|
53
|
+
batch = _build_unclosed_batch(num_records, value_size)
|
|
54
|
+
batch.records.close()
|
|
55
|
+
return batch
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def bench_build_and_close(loops, num_records, value_size):
|
|
59
|
+
"""Time build + close - isolates the batch-finalization path.
|
|
60
|
+
|
|
61
|
+
close() is fast enough that pyperf would need many thousands of loops
|
|
62
|
+
to measure it directly, so we include the build cost and rely on the
|
|
63
|
+
per-run diff to expose the close() delta.
|
|
64
|
+
"""
|
|
65
|
+
value = b'x' * value_size
|
|
66
|
+
tp = TopicPartition('bench', 0)
|
|
67
|
+
|
|
68
|
+
t0 = pyperf.perf_counter()
|
|
69
|
+
for _ in range(loops):
|
|
70
|
+
records = MemoryRecordsBuilder(
|
|
71
|
+
magic=2, compression_type=0, batch_size=DEFAULT_BATCH_SIZE)
|
|
72
|
+
batch = ProducerBatch(tp, records)
|
|
73
|
+
for i in range(num_records):
|
|
74
|
+
batch.try_append(i, None, value, [])
|
|
75
|
+
batch.records.close()
|
|
76
|
+
return pyperf.perf_counter() - t0
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def bench_encode(loops, num_records, value_size):
|
|
80
|
+
"""Time ProduceRequest.encode() with a pre-closed batch.
|
|
81
|
+
|
|
82
|
+
Isolates the protocol encoding cost from batch finalization.
|
|
83
|
+
"""
|
|
84
|
+
batch = _build_closed_batch(num_records, value_size)
|
|
85
|
+
buf = batch.records.buffer()
|
|
86
|
+
topic_data = [('bench', [(0, buf)])]
|
|
87
|
+
|
|
88
|
+
t0 = pyperf.perf_counter()
|
|
89
|
+
for _ in range(loops):
|
|
90
|
+
req = ProduceRequest[8](
|
|
91
|
+
transactional_id=None,
|
|
92
|
+
acks=1,
|
|
93
|
+
timeout_ms=30000,
|
|
94
|
+
topic_data=topic_data,
|
|
95
|
+
)
|
|
96
|
+
req.with_header(correlation_id=1, client_id='bench')
|
|
97
|
+
req.encode(framed=True, header=True)
|
|
98
|
+
return pyperf.perf_counter() - t0
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def bench_full_pipeline(loops, num_records, value_size):
|
|
102
|
+
"""Time the full producer hot path: append -> close -> encode.
|
|
103
|
+
|
|
104
|
+
Mirrors what the Sender thread does for each drained batch.
|
|
105
|
+
"""
|
|
106
|
+
value = b'x' * value_size
|
|
107
|
+
tp = TopicPartition('bench', 0)
|
|
108
|
+
|
|
109
|
+
t0 = pyperf.perf_counter()
|
|
110
|
+
for _ in range(loops):
|
|
111
|
+
records = MemoryRecordsBuilder(
|
|
112
|
+
magic=2, compression_type=0, batch_size=DEFAULT_BATCH_SIZE)
|
|
113
|
+
batch = ProducerBatch(tp, records)
|
|
114
|
+
for i in range(num_records):
|
|
115
|
+
batch.try_append(i, None, value, [])
|
|
116
|
+
batch.records.close()
|
|
117
|
+
req = ProduceRequest[8](
|
|
118
|
+
transactional_id=None,
|
|
119
|
+
acks=1,
|
|
120
|
+
timeout_ms=30000,
|
|
121
|
+
topic_data=[('bench', [(0, batch.records.buffer())])],
|
|
122
|
+
)
|
|
123
|
+
req.with_header(correlation_id=1, client_id='bench')
|
|
124
|
+
req.encode(framed=True, header=True)
|
|
125
|
+
return pyperf.perf_counter() - t0
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def report_allocations(num_records, value_size):
|
|
129
|
+
"""Use tracemalloc to count bytes allocated during a single encode."""
|
|
130
|
+
# Pre-build so we only measure the encode path.
|
|
131
|
+
batch = _build_closed_batch(num_records, value_size)
|
|
132
|
+
buf = batch.records.buffer()
|
|
133
|
+
topic_data = [('bench', [(0, buf)])]
|
|
134
|
+
req = ProduceRequest[8](
|
|
135
|
+
transactional_id=None,
|
|
136
|
+
acks=1,
|
|
137
|
+
timeout_ms=30000,
|
|
138
|
+
topic_data=topic_data,
|
|
139
|
+
)
|
|
140
|
+
req.with_header(correlation_id=1, client_id='bench')
|
|
141
|
+
|
|
142
|
+
# Warmup - populate the compiled-encoder cache so we don't count its
|
|
143
|
+
# one-time allocations.
|
|
144
|
+
req.encode(framed=True, header=True)
|
|
145
|
+
|
|
146
|
+
tracemalloc.start()
|
|
147
|
+
snap_before = tracemalloc.take_snapshot()
|
|
148
|
+
data = req.encode(framed=True, header=True)
|
|
149
|
+
snap_after = tracemalloc.take_snapshot()
|
|
150
|
+
tracemalloc.stop()
|
|
151
|
+
|
|
152
|
+
stats = snap_after.compare_to(snap_before, 'lineno')
|
|
153
|
+
total_bytes = sum(max(0, s.size_diff) for s in stats)
|
|
154
|
+
total_allocs = sum(max(0, s.count_diff) for s in stats)
|
|
155
|
+
|
|
156
|
+
print('Config : %d records x %d bytes' % (num_records, value_size))
|
|
157
|
+
print('Wire bytes : %d' % len(data))
|
|
158
|
+
print('Allocated : %d bytes across %d allocations' % (total_bytes, total_allocs))
|
|
159
|
+
print()
|
|
160
|
+
print('Top allocation sites:')
|
|
161
|
+
for s in sorted(stats, key=lambda s: s.size_diff, reverse=True)[:10]:
|
|
162
|
+
if s.size_diff <= 0:
|
|
163
|
+
continue
|
|
164
|
+
frame = s.traceback[0]
|
|
165
|
+
loc = '%s:%d' % (frame.filename.split('/workspace/')[-1], frame.lineno)
|
|
166
|
+
print(' %8d bytes / %3d allocs %s' % (s.size_diff, s.count_diff, loc))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def main():
|
|
170
|
+
p = argparse.ArgumentParser(description=__doc__,
|
|
171
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
172
|
+
p.add_argument('--records', type=int, default=DEFAULT_RECORDS_PER_BATCH,
|
|
173
|
+
help='records per batch (default: %(default)d)')
|
|
174
|
+
p.add_argument('--value-size', type=int, default=DEFAULT_VALUE_SIZE,
|
|
175
|
+
help='record value size in bytes (default: %(default)d)')
|
|
176
|
+
p.add_argument('--allocations', action='store_true',
|
|
177
|
+
help='report tracemalloc allocations for one encode (not a timing run)')
|
|
178
|
+
|
|
179
|
+
# Let pyperf parse its own arguments (--output, --rigorous, etc).
|
|
180
|
+
args, pyperf_args = p.parse_known_args()
|
|
181
|
+
|
|
182
|
+
if args.allocations:
|
|
183
|
+
report_allocations(args.records, args.value_size)
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
# Rebuild sys.argv so pyperf sees only its own arguments.
|
|
187
|
+
sys.argv = [sys.argv[0]] + pyperf_args
|
|
188
|
+
|
|
189
|
+
runner = pyperf.Runner()
|
|
190
|
+
runner.metadata['records_per_batch'] = args.records
|
|
191
|
+
runner.metadata['value_size_bytes'] = args.value_size
|
|
192
|
+
runner.bench_time_func(
|
|
193
|
+
'build_and_close', bench_build_and_close, args.records, args.value_size)
|
|
194
|
+
runner.bench_time_func(
|
|
195
|
+
'encode', bench_encode, args.records, args.value_size)
|
|
196
|
+
runner.bench_time_func(
|
|
197
|
+
'full_pipeline', bench_full_pipeline, args.records, args.value_size)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
if __name__ == '__main__':
|
|
201
|
+
main()
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Adapted from https://github.com/mrafayaleem/kafka-jython
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import pprint
|
|
6
|
+
import sys
|
|
7
|
+
import threading
|
|
8
|
+
import time
|
|
9
|
+
import traceback
|
|
10
|
+
|
|
11
|
+
from kafka import KafkaProducer
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ProducerPerformance:
|
|
15
|
+
@staticmethod
|
|
16
|
+
def run(args):
|
|
17
|
+
try:
|
|
18
|
+
props = {}
|
|
19
|
+
for prop in args.producer_config:
|
|
20
|
+
k, v = prop.split('=')
|
|
21
|
+
try:
|
|
22
|
+
v = int(v)
|
|
23
|
+
except ValueError:
|
|
24
|
+
pass
|
|
25
|
+
if v == 'None':
|
|
26
|
+
v = None
|
|
27
|
+
elif v == 'False':
|
|
28
|
+
v = False
|
|
29
|
+
elif v == 'True':
|
|
30
|
+
v = True
|
|
31
|
+
props[k] = v
|
|
32
|
+
|
|
33
|
+
print('Initializing producer...')
|
|
34
|
+
props['bootstrap_servers'] = args.bootstrap_servers
|
|
35
|
+
record = bytes(bytearray(args.record_size))
|
|
36
|
+
props['metrics_sample_window_ms'] = args.stats_interval * 1000
|
|
37
|
+
|
|
38
|
+
producer = KafkaProducer(**props)
|
|
39
|
+
for k, v in props.items():
|
|
40
|
+
print('---> {0}={1}'.format(k, v))
|
|
41
|
+
print('---> topic={0}'.format(args.topic))
|
|
42
|
+
print('---> send {0} byte records'.format(args.record_size))
|
|
43
|
+
print('---> report stats every {0} secs'.format(args.stats_interval))
|
|
44
|
+
print('---> raw metrics? {0}'.format(args.raw_metrics))
|
|
45
|
+
timer_stop = threading.Event()
|
|
46
|
+
timer = StatsReporter(args.stats_interval, producer,
|
|
47
|
+
event=timer_stop,
|
|
48
|
+
raw_metrics=args.raw_metrics)
|
|
49
|
+
timer.start()
|
|
50
|
+
print('-> OK!')
|
|
51
|
+
print()
|
|
52
|
+
|
|
53
|
+
def _benchmark():
|
|
54
|
+
# Hoist attribute lookups and use positional args to minimize
|
|
55
|
+
# per-iteration harness overhead. With a well-optimized
|
|
56
|
+
# producer.send(), kwargs dict packing and repeated attribute
|
|
57
|
+
# dereference on `args`/`producer` dominate main-thread CPU
|
|
58
|
+
# inside this loop and mask the library's true throughput.
|
|
59
|
+
results = []
|
|
60
|
+
send = producer.send
|
|
61
|
+
append = results.append
|
|
62
|
+
topic = args.topic
|
|
63
|
+
num_records = args.num_records
|
|
64
|
+
for _ in range(num_records):
|
|
65
|
+
append(send(topic, record))
|
|
66
|
+
print("Send complete...")
|
|
67
|
+
producer.flush()
|
|
68
|
+
producer.close()
|
|
69
|
+
count_success, count_failure = 0, 0
|
|
70
|
+
for r in results:
|
|
71
|
+
if r.succeeded():
|
|
72
|
+
count_success += 1
|
|
73
|
+
elif r.failed():
|
|
74
|
+
count_failure += 1
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError(r)
|
|
77
|
+
print("%d suceeded, %d failed" % (count_success, count_failure))
|
|
78
|
+
|
|
79
|
+
start_time = time.monotonic()
|
|
80
|
+
_benchmark()
|
|
81
|
+
end_time = time.monotonic()
|
|
82
|
+
timer_stop.set()
|
|
83
|
+
timer.join()
|
|
84
|
+
print('Execution time:', end_time - start_time, 'secs')
|
|
85
|
+
|
|
86
|
+
except Exception:
|
|
87
|
+
exc_info = sys.exc_info()
|
|
88
|
+
traceback.print_exception(*exc_info)
|
|
89
|
+
sys.exit(1)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class StatsReporter(threading.Thread):
|
|
93
|
+
def __init__(self, interval, producer, event=None, raw_metrics=False):
|
|
94
|
+
super().__init__()
|
|
95
|
+
self.interval = interval
|
|
96
|
+
self.producer = producer
|
|
97
|
+
self.event = event
|
|
98
|
+
self.raw_metrics = raw_metrics
|
|
99
|
+
|
|
100
|
+
def print_stats(self):
|
|
101
|
+
metrics = self.producer.metrics()
|
|
102
|
+
if not metrics:
|
|
103
|
+
return
|
|
104
|
+
if self.raw_metrics:
|
|
105
|
+
pprint.pprint(metrics)
|
|
106
|
+
else:
|
|
107
|
+
print('{record-send-rate:.0f} records/sec ({byte-rate:.0f} B/sec),'
|
|
108
|
+
' {request-rate:.0f} avg requests/sec,'
|
|
109
|
+
' {request-latency-avg:.0f}ms avg latency,'
|
|
110
|
+
' {throttle-time-max:.0f}ms max throttle,'
|
|
111
|
+
' {record-size-avg:.0f} avg record size,'
|
|
112
|
+
' {batch-size-avg:.0f} avg batch size,'
|
|
113
|
+
' {records-per-request-avg:.0f} avg records/req'
|
|
114
|
+
.format(**metrics['producer-metrics']))
|
|
115
|
+
|
|
116
|
+
def print_final(self):
|
|
117
|
+
self.print_stats()
|
|
118
|
+
|
|
119
|
+
def run(self):
|
|
120
|
+
while self.event and not self.event.wait(self.interval):
|
|
121
|
+
self.print_stats()
|
|
122
|
+
else:
|
|
123
|
+
self.print_final()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_args_parser():
|
|
127
|
+
parser = argparse.ArgumentParser(
|
|
128
|
+
description='This tool is used to verify the producer performance.')
|
|
129
|
+
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
'-b', '--bootstrap-servers', type=str, nargs='+', default=(),
|
|
132
|
+
help='host:port for cluster bootstrap server')
|
|
133
|
+
parser.add_argument(
|
|
134
|
+
'-t', '--topic', type=str,
|
|
135
|
+
help='Topic name for test (default: kafka-python-benchmark-test)',
|
|
136
|
+
default='kafka-python-benchmark-test')
|
|
137
|
+
parser.add_argument(
|
|
138
|
+
'--num-records', type=int,
|
|
139
|
+
help='number of messages to produce (default: 1000000)',
|
|
140
|
+
default=1000000)
|
|
141
|
+
parser.add_argument(
|
|
142
|
+
'--record-size', type=int,
|
|
143
|
+
help='message size in bytes (default: 100)',
|
|
144
|
+
default=100)
|
|
145
|
+
parser.add_argument(
|
|
146
|
+
'-c', '--producer-config', type=str, nargs='+', default=(),
|
|
147
|
+
help='kafka producer related configuaration properties like '
|
|
148
|
+
'bootstrap_servers,client_id etc..')
|
|
149
|
+
parser.add_argument(
|
|
150
|
+
'--stats-interval', type=int,
|
|
151
|
+
help='Interval in seconds for stats reporting to console (default: 5)',
|
|
152
|
+
default=5)
|
|
153
|
+
parser.add_argument(
|
|
154
|
+
'--raw-metrics', action='store_true',
|
|
155
|
+
help='Enable this flag to print full metrics dict on each interval')
|
|
156
|
+
return parser
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
if __name__ == '__main__':
|
|
160
|
+
args = get_args_parser().parse_args()
|
|
161
|
+
ProducerPerformance.run(args)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Per-function and per-line profiling of new protocol encode/decode hot methods.
|
|
3
|
+
|
|
4
|
+
Uses cProfile for call-level breakdown and a targeted manual timer
|
|
5
|
+
for line-level insight into the key hot methods.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python kafka/benchmarks/profile_protocol.py [encode|decode|create] [N]
|
|
9
|
+
|
|
10
|
+
encode - profile encode path (default)
|
|
11
|
+
decode - profile decode path
|
|
12
|
+
create - profile object creation path
|
|
13
|
+
N - number of iterations (default: 1000)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import cProfile
|
|
17
|
+
import io
|
|
18
|
+
import pstats
|
|
19
|
+
import sys
|
|
20
|
+
import time
|
|
21
|
+
|
|
22
|
+
from kafka.protocol.metadata.metadata import MetadataResponse as NewMetadataResp
|
|
23
|
+
from kafka.protocol.consumer.fetch import FetchResponse as NewFetchResp
|
|
24
|
+
|
|
25
|
+
# === Test data (same as benchmark script) ===
|
|
26
|
+
_BROKERS = [(i, 'broker-%d.example.com' % i, 9092 + i) for i in range(3)]
|
|
27
|
+
_PARTITIONS = [(0, p, p % 3, [0, 1, 2], [0, 1]) for p in range(3)]
|
|
28
|
+
_TOPICS = [(0, 'test-topic-%d' % t, _PARTITIONS) for t in range(5)]
|
|
29
|
+
|
|
30
|
+
_RECORDS_BYTES = b'\x00' * 1024
|
|
31
|
+
_FETCH_TOPICS = [
|
|
32
|
+
('test-topic-%d' % t, [
|
|
33
|
+
(p, 0, 1000 + p, 999 + p, None, _RECORDS_BYTES)
|
|
34
|
+
for p in range(3)
|
|
35
|
+
])
|
|
36
|
+
for t in range(2)
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def profile_encode(n):
|
|
41
|
+
"""Profile the encode path for MetadataResponse and FetchResponse."""
|
|
42
|
+
obj_meta = NewMetadataResp(version=0, brokers=_BROKERS, topics=_TOPICS)
|
|
43
|
+
obj_fetch = NewFetchResp(version=4, throttle_time_ms=0, responses=_FETCH_TOPICS)
|
|
44
|
+
|
|
45
|
+
# Warmup
|
|
46
|
+
obj_meta.encode(version=0)
|
|
47
|
+
obj_fetch.encode(version=4)
|
|
48
|
+
|
|
49
|
+
pr = cProfile.Profile()
|
|
50
|
+
pr.enable()
|
|
51
|
+
for _ in range(n):
|
|
52
|
+
obj_meta.encode(version=0)
|
|
53
|
+
obj_fetch.encode(version=4)
|
|
54
|
+
pr.disable()
|
|
55
|
+
|
|
56
|
+
print("=" * 80)
|
|
57
|
+
print("ENCODE PROFILE (%d iterations: MetadataResponse v0 + FetchResponse v4)" % n)
|
|
58
|
+
print("=" * 80)
|
|
59
|
+
stats = pstats.Stats(pr)
|
|
60
|
+
stats.sort_stats('cumulative')
|
|
61
|
+
stats.print_stats(40)
|
|
62
|
+
print()
|
|
63
|
+
stats.sort_stats('tottime')
|
|
64
|
+
stats.print_stats(40)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def profile_decode(n):
|
|
68
|
+
"""Profile the decode path for MetadataResponse and FetchResponse."""
|
|
69
|
+
obj_meta = NewMetadataResp(version=0, brokers=_BROKERS, topics=_TOPICS)
|
|
70
|
+
obj_fetch = NewFetchResp(version=4, throttle_time_ms=0, responses=_FETCH_TOPICS)
|
|
71
|
+
encoded_meta = obj_meta.encode(version=0)
|
|
72
|
+
encoded_fetch = obj_fetch.encode(version=4)
|
|
73
|
+
|
|
74
|
+
# Warmup
|
|
75
|
+
NewMetadataResp.decode(io.BytesIO(encoded_meta), version=0)
|
|
76
|
+
NewFetchResp.decode(io.BytesIO(encoded_fetch), version=4)
|
|
77
|
+
|
|
78
|
+
pr = cProfile.Profile()
|
|
79
|
+
pr.enable()
|
|
80
|
+
for _ in range(n):
|
|
81
|
+
NewMetadataResp.decode(io.BytesIO(encoded_meta), version=0)
|
|
82
|
+
NewFetchResp.decode(io.BytesIO(encoded_fetch), version=4)
|
|
83
|
+
pr.disable()
|
|
84
|
+
|
|
85
|
+
print("=" * 80)
|
|
86
|
+
print("DECODE PROFILE (%d iterations: MetadataResponse v0 + FetchResponse v4)" % n)
|
|
87
|
+
print("=" * 80)
|
|
88
|
+
stats = pstats.Stats(pr)
|
|
89
|
+
stats.sort_stats('cumulative')
|
|
90
|
+
stats.print_stats(40)
|
|
91
|
+
print()
|
|
92
|
+
stats.sort_stats('tottime')
|
|
93
|
+
stats.print_stats(40)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def profile_create(n):
|
|
97
|
+
"""Profile the object creation path."""
|
|
98
|
+
# Warmup
|
|
99
|
+
NewMetadataResp(version=0, brokers=_BROKERS, topics=_TOPICS)
|
|
100
|
+
NewFetchResp(version=4, throttle_time_ms=0, responses=_FETCH_TOPICS)
|
|
101
|
+
|
|
102
|
+
pr = cProfile.Profile()
|
|
103
|
+
pr.enable()
|
|
104
|
+
for _ in range(n):
|
|
105
|
+
NewMetadataResp(version=0, brokers=_BROKERS, topics=_TOPICS)
|
|
106
|
+
NewFetchResp(version=4, throttle_time_ms=0, responses=_FETCH_TOPICS)
|
|
107
|
+
pr.disable()
|
|
108
|
+
|
|
109
|
+
print("=" * 80)
|
|
110
|
+
print("CREATE PROFILE (%d iterations: MetadataResponse v0 + FetchResponse v4)" % n)
|
|
111
|
+
print("=" * 80)
|
|
112
|
+
stats = pstats.Stats(pr)
|
|
113
|
+
stats.sort_stats('cumulative')
|
|
114
|
+
stats.print_stats(40)
|
|
115
|
+
print()
|
|
116
|
+
stats.sort_stats('tottime')
|
|
117
|
+
stats.print_stats(40)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if __name__ == '__main__':
|
|
121
|
+
mode = sys.argv[1] if len(sys.argv) > 1 else 'encode'
|
|
122
|
+
iterations = int(sys.argv[2]) if len(sys.argv) > 2 else 1000
|
|
123
|
+
|
|
124
|
+
if mode == 'encode':
|
|
125
|
+
profile_encode(iterations)
|
|
126
|
+
elif mode == 'decode':
|
|
127
|
+
profile_decode(iterations)
|
|
128
|
+
elif mode == 'create':
|
|
129
|
+
profile_create(iterations)
|
|
130
|
+
elif mode == 'all':
|
|
131
|
+
profile_encode(iterations)
|
|
132
|
+
print("\n\n")
|
|
133
|
+
profile_decode(iterations)
|
|
134
|
+
print("\n\n")
|
|
135
|
+
profile_create(iterations)
|
|
136
|
+
else:
|
|
137
|
+
print("Usage: python profile_protocol.py [encode|decode|create|all] [N]")
|
|
138
|
+
sys.exit(1)
|