mirror of https://github.com/grpc/grpc.git
pull/12399/head
commit
3cdc6fb17e
101 changed files with 3150 additions and 1128 deletions
@ -0,0 +1,35 @@ |
||||
client_calls_created_per_iteration:FLOAT, |
||||
server_calls_created_per_iteration:FLOAT, |
||||
syscall_poll_per_iteration:FLOAT, |
||||
syscall_wait_per_iteration:FLOAT, |
||||
histogram_slow_lookups_per_iteration:FLOAT, |
||||
syscall_write_per_iteration:FLOAT, |
||||
syscall_read_per_iteration:FLOAT, |
||||
tcp_backup_pollers_created_per_iteration:FLOAT, |
||||
tcp_backup_poller_polls_per_iteration:FLOAT, |
||||
http2_op_batches_per_iteration:FLOAT, |
||||
http2_op_cancel_per_iteration:FLOAT, |
||||
http2_op_send_initial_metadata_per_iteration:FLOAT, |
||||
http2_op_send_message_per_iteration:FLOAT, |
||||
http2_op_send_trailing_metadata_per_iteration:FLOAT, |
||||
http2_op_recv_initial_metadata_per_iteration:FLOAT, |
||||
http2_op_recv_message_per_iteration:FLOAT, |
||||
http2_op_recv_trailing_metadata_per_iteration:FLOAT, |
||||
http2_settings_writes_per_iteration:FLOAT, |
||||
http2_pings_sent_per_iteration:FLOAT, |
||||
http2_writes_begun_per_iteration:FLOAT, |
||||
http2_writes_offloaded_per_iteration:FLOAT, |
||||
http2_writes_continued_per_iteration:FLOAT, |
||||
http2_partial_writes_per_iteration:FLOAT, |
||||
combiner_locks_initiated_per_iteration:FLOAT, |
||||
combiner_locks_scheduled_items_per_iteration:FLOAT, |
||||
combiner_locks_scheduled_final_items_per_iteration:FLOAT, |
||||
combiner_locks_offloaded_per_iteration:FLOAT, |
||||
executor_scheduled_short_items_per_iteration:FLOAT, |
||||
executor_scheduled_long_items_per_iteration:FLOAT, |
||||
executor_scheduled_to_self_per_iteration:FLOAT, |
||||
executor_wakeup_initiated_per_iteration:FLOAT, |
||||
executor_queue_drained_per_iteration:FLOAT, |
||||
executor_push_retries_per_iteration:FLOAT, |
||||
server_requested_calls_per_iteration:FLOAT, |
||||
server_slowpath_requests_queued_per_iteration:FLOAT |
@ -0,0 +1,118 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""Common utilities for tests of the Cython layer of gRPC Python.""" |
||||
|
||||
import collections |
||||
import threading |
||||
|
||||
from grpc._cython import cygrpc |
||||
|
||||
RPC_COUNT = 4000 |
||||
|
||||
INFINITE_FUTURE = cygrpc.Timespec(float('+inf')) |
||||
EMPTY_FLAGS = 0 |
||||
|
||||
INVOCATION_METADATA = cygrpc.Metadata( |
||||
(cygrpc.Metadatum(b'client-md-key', b'client-md-key'), |
||||
cygrpc.Metadatum(b'client-md-key-bin', b'\x00\x01' * 3000),)) |
||||
|
||||
INITIAL_METADATA = cygrpc.Metadata( |
||||
(cygrpc.Metadatum(b'server-initial-md-key', b'server-initial-md-value'), |
||||
cygrpc.Metadatum(b'server-initial-md-key-bin', b'\x00\x02' * 3000),)) |
||||
|
||||
TRAILING_METADATA = cygrpc.Metadata( |
||||
(cygrpc.Metadatum(b'server-trailing-md-key', b'server-trailing-md-value'), |
||||
cygrpc.Metadatum(b'server-trailing-md-key-bin', b'\x00\x03' * 3000),)) |
||||
|
||||
|
||||
class QueueDriver(object): |
||||
|
||||
def __init__(self, condition, completion_queue): |
||||
self._condition = condition |
||||
self._completion_queue = completion_queue |
||||
self._due = collections.defaultdict(int) |
||||
self._events = collections.defaultdict(list) |
||||
|
||||
def add_due(self, tags): |
||||
if not self._due: |
||||
|
||||
def in_thread(): |
||||
while True: |
||||
event = self._completion_queue.poll() |
||||
with self._condition: |
||||
self._events[event.tag].append(event) |
||||
self._due[event.tag] -= 1 |
||||
self._condition.notify_all() |
||||
if self._due[event.tag] <= 0: |
||||
self._due.pop(event.tag) |
||||
if not self._due: |
||||
return |
||||
|
||||
thread = threading.Thread(target=in_thread) |
||||
thread.start() |
||||
for tag in tags: |
||||
self._due[tag] += 1 |
||||
|
||||
def event_with_tag(self, tag): |
||||
with self._condition: |
||||
while True: |
||||
if self._events[tag]: |
||||
return self._events[tag].pop(0) |
||||
else: |
||||
self._condition.wait() |
||||
|
||||
|
||||
def execute_many_times(behavior): |
||||
return tuple(behavior() for _ in range(RPC_COUNT)) |
||||
|
||||
|
||||
class OperationResult( |
||||
collections.namedtuple('OperationResult', ( |
||||
'start_batch_result', 'completion_type', 'success',))): |
||||
pass |
||||
|
||||
|
||||
SUCCESSFUL_OPERATION_RESULT = OperationResult( |
||||
cygrpc.CallError.ok, cygrpc.CompletionType.operation_complete, True) |
||||
|
||||
|
||||
class RpcTest(object): |
||||
|
||||
def setUp(self): |
||||
self.server_completion_queue = cygrpc.CompletionQueue() |
||||
self.server = cygrpc.Server(cygrpc.ChannelArgs([])) |
||||
self.server.register_completion_queue(self.server_completion_queue) |
||||
port = self.server.add_http2_port(b'[::]:0') |
||||
self.server.start() |
||||
self.channel = cygrpc.Channel('localhost:{}'.format(port).encode(), |
||||
cygrpc.ChannelArgs([])) |
||||
|
||||
self._server_shutdown_tag = 'server_shutdown_tag' |
||||
self.server_condition = threading.Condition() |
||||
self.server_driver = QueueDriver(self.server_condition, |
||||
self.server_completion_queue) |
||||
with self.server_condition: |
||||
self.server_driver.add_due({ |
||||
self._server_shutdown_tag, |
||||
}) |
||||
|
||||
self.client_condition = threading.Condition() |
||||
self.client_completion_queue = cygrpc.CompletionQueue() |
||||
self.client_driver = QueueDriver(self.client_condition, |
||||
self.client_completion_queue) |
||||
|
||||
def tearDown(self): |
||||
self.server.shutdown(self.server_completion_queue, |
||||
self._server_shutdown_tag) |
||||
self.server.cancel_all_calls() |
@ -0,0 +1,131 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""Test a corner-case at the level of the Cython API.""" |
||||
|
||||
import threading |
||||
import unittest |
||||
|
||||
from grpc._cython import cygrpc |
||||
|
||||
from tests.unit._cython import _common |
||||
|
||||
|
||||
class Test(_common.RpcTest, unittest.TestCase): |
||||
|
||||
def _do_rpcs(self): |
||||
server_call_condition = threading.Condition() |
||||
server_call_completion_queue = cygrpc.CompletionQueue() |
||||
server_call_driver = _common.QueueDriver(server_call_condition, |
||||
server_call_completion_queue) |
||||
|
||||
server_request_call_tag = 'server_request_call_tag' |
||||
server_send_initial_metadata_tag = 'server_send_initial_metadata_tag' |
||||
server_complete_rpc_tag = 'server_complete_rpc_tag' |
||||
|
||||
with self.server_condition: |
||||
server_request_call_start_batch_result = self.server.request_call( |
||||
server_call_completion_queue, self.server_completion_queue, |
||||
server_request_call_tag) |
||||
self.server_driver.add_due({ |
||||
server_request_call_tag, |
||||
}) |
||||
|
||||
client_call = self.channel.create_call( |
||||
None, _common.EMPTY_FLAGS, self.client_completion_queue, |
||||
b'/twinkies', None, _common.INFINITE_FUTURE) |
||||
client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag' |
||||
client_complete_rpc_tag = 'client_complete_rpc_tag' |
||||
with self.client_condition: |
||||
client_receive_initial_metadata_start_batch_result = ( |
||||
client_call.start_client_batch( |
||||
cygrpc.Operations([ |
||||
cygrpc.operation_receive_initial_metadata( |
||||
_common.EMPTY_FLAGS), |
||||
]), client_receive_initial_metadata_tag)) |
||||
client_complete_rpc_start_batch_result = client_call.start_client_batch( |
||||
cygrpc.Operations([ |
||||
cygrpc.operation_send_initial_metadata( |
||||
_common.INVOCATION_METADATA, _common.EMPTY_FLAGS), |
||||
cygrpc.operation_send_close_from_client( |
||||
_common.EMPTY_FLAGS), |
||||
cygrpc.operation_receive_status_on_client( |
||||
_common.EMPTY_FLAGS), |
||||
]), client_complete_rpc_tag) |
||||
self.client_driver.add_due({ |
||||
client_receive_initial_metadata_tag, |
||||
client_complete_rpc_tag, |
||||
}) |
||||
|
||||
server_request_call_event = self.server_driver.event_with_tag( |
||||
server_request_call_tag) |
||||
|
||||
with server_call_condition: |
||||
server_send_initial_metadata_start_batch_result = ( |
||||
server_request_call_event.operation_call.start_server_batch([ |
||||
cygrpc.operation_send_initial_metadata( |
||||
_common.INITIAL_METADATA, _common.EMPTY_FLAGS), |
||||
], server_send_initial_metadata_tag)) |
||||
server_call_driver.add_due({ |
||||
server_send_initial_metadata_tag, |
||||
}) |
||||
server_send_initial_metadata_event = server_call_driver.event_with_tag( |
||||
server_send_initial_metadata_tag) |
||||
|
||||
with server_call_condition: |
||||
server_complete_rpc_start_batch_result = ( |
||||
server_request_call_event.operation_call.start_server_batch([ |
||||
cygrpc.operation_receive_close_on_server( |
||||
_common.EMPTY_FLAGS), |
||||
cygrpc.operation_send_status_from_server( |
||||
_common.TRAILING_METADATA, cygrpc.StatusCode.ok, |
||||
b'test details', _common.EMPTY_FLAGS), |
||||
], server_complete_rpc_tag)) |
||||
server_call_driver.add_due({ |
||||
server_complete_rpc_tag, |
||||
}) |
||||
server_complete_rpc_event = server_call_driver.event_with_tag( |
||||
server_complete_rpc_tag) |
||||
|
||||
client_receive_initial_metadata_event = self.client_driver.event_with_tag( |
||||
client_receive_initial_metadata_tag) |
||||
client_complete_rpc_event = self.client_driver.event_with_tag( |
||||
client_complete_rpc_tag) |
||||
|
||||
return (_common.OperationResult(server_request_call_start_batch_result, |
||||
server_request_call_event.type, |
||||
server_request_call_event.success), |
||||
_common.OperationResult( |
||||
client_receive_initial_metadata_start_batch_result, |
||||
client_receive_initial_metadata_event.type, |
||||
client_receive_initial_metadata_event.success), |
||||
_common.OperationResult(client_complete_rpc_start_batch_result, |
||||
client_complete_rpc_event.type, |
||||
client_complete_rpc_event.success), |
||||
_common.OperationResult( |
||||
server_send_initial_metadata_start_batch_result, |
||||
server_send_initial_metadata_event.type, |
||||
server_send_initial_metadata_event.success), |
||||
_common.OperationResult(server_complete_rpc_start_batch_result, |
||||
server_complete_rpc_event.type, |
||||
server_complete_rpc_event.success),) |
||||
|
||||
def test_rpcs(self): |
||||
expecteds = [(_common.SUCCESSFUL_OPERATION_RESULT,) * |
||||
5] * _common.RPC_COUNT |
||||
actuallys = _common.execute_many_times(self._do_rpcs) |
||||
self.assertSequenceEqual(expecteds, actuallys) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
unittest.main(verbosity=2) |
@ -0,0 +1,126 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""Test a corner-case at the level of the Cython API.""" |
||||
|
||||
import threading |
||||
import unittest |
||||
|
||||
from grpc._cython import cygrpc |
||||
|
||||
from tests.unit._cython import _common |
||||
|
||||
|
||||
class Test(_common.RpcTest, unittest.TestCase): |
||||
|
||||
def _do_rpcs(self): |
||||
server_request_call_tag = 'server_request_call_tag' |
||||
server_send_initial_metadata_tag = 'server_send_initial_metadata_tag' |
||||
server_complete_rpc_tag = 'server_complete_rpc_tag' |
||||
|
||||
with self.server_condition: |
||||
server_request_call_start_batch_result = self.server.request_call( |
||||
self.server_completion_queue, self.server_completion_queue, |
||||
server_request_call_tag) |
||||
self.server_driver.add_due({ |
||||
server_request_call_tag, |
||||
}) |
||||
|
||||
client_call = self.channel.create_call( |
||||
None, _common.EMPTY_FLAGS, self.client_completion_queue, |
||||
b'/twinkies', None, _common.INFINITE_FUTURE) |
||||
client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag' |
||||
client_complete_rpc_tag = 'client_complete_rpc_tag' |
||||
with self.client_condition: |
||||
client_receive_initial_metadata_start_batch_result = ( |
||||
client_call.start_client_batch( |
||||
cygrpc.Operations([ |
||||
cygrpc.operation_receive_initial_metadata( |
||||
_common.EMPTY_FLAGS), |
||||
]), client_receive_initial_metadata_tag)) |
||||
client_complete_rpc_start_batch_result = client_call.start_client_batch( |
||||
cygrpc.Operations([ |
||||
cygrpc.operation_send_initial_metadata( |
||||
_common.INVOCATION_METADATA, _common.EMPTY_FLAGS), |
||||
cygrpc.operation_send_close_from_client( |
||||
_common.EMPTY_FLAGS), |
||||
cygrpc.operation_receive_status_on_client( |
||||
_common.EMPTY_FLAGS), |
||||
]), client_complete_rpc_tag) |
||||
self.client_driver.add_due({ |
||||
client_receive_initial_metadata_tag, |
||||
client_complete_rpc_tag, |
||||
}) |
||||
|
||||
server_request_call_event = self.server_driver.event_with_tag( |
||||
server_request_call_tag) |
||||
|
||||
with self.server_condition: |
||||
server_send_initial_metadata_start_batch_result = ( |
||||
server_request_call_event.operation_call.start_server_batch([ |
||||
cygrpc.operation_send_initial_metadata( |
||||
_common.INITIAL_METADATA, _common.EMPTY_FLAGS), |
||||
], server_send_initial_metadata_tag)) |
||||
self.server_driver.add_due({ |
||||
server_send_initial_metadata_tag, |
||||
}) |
||||
server_send_initial_metadata_event = self.server_driver.event_with_tag( |
||||
server_send_initial_metadata_tag) |
||||
|
||||
with self.server_condition: |
||||
server_complete_rpc_start_batch_result = ( |
||||
server_request_call_event.operation_call.start_server_batch([ |
||||
cygrpc.operation_receive_close_on_server( |
||||
_common.EMPTY_FLAGS), |
||||
cygrpc.operation_send_status_from_server( |
||||
_common.TRAILING_METADATA, cygrpc.StatusCode.ok, |
||||
b'test details', _common.EMPTY_FLAGS), |
||||
], server_complete_rpc_tag)) |
||||
self.server_driver.add_due({ |
||||
server_complete_rpc_tag, |
||||
}) |
||||
server_complete_rpc_event = self.server_driver.event_with_tag( |
||||
server_complete_rpc_tag) |
||||
|
||||
client_receive_initial_metadata_event = self.client_driver.event_with_tag( |
||||
client_receive_initial_metadata_tag) |
||||
client_complete_rpc_event = self.client_driver.event_with_tag( |
||||
client_complete_rpc_tag) |
||||
|
||||
return (_common.OperationResult(server_request_call_start_batch_result, |
||||
server_request_call_event.type, |
||||
server_request_call_event.success), |
||||
_common.OperationResult( |
||||
client_receive_initial_metadata_start_batch_result, |
||||
client_receive_initial_metadata_event.type, |
||||
client_receive_initial_metadata_event.success), |
||||
_common.OperationResult(client_complete_rpc_start_batch_result, |
||||
client_complete_rpc_event.type, |
||||
client_complete_rpc_event.success), |
||||
_common.OperationResult( |
||||
server_send_initial_metadata_start_batch_result, |
||||
server_send_initial_metadata_event.type, |
||||
server_send_initial_metadata_event.success), |
||||
_common.OperationResult(server_complete_rpc_start_batch_result, |
||||
server_complete_rpc_event.type, |
||||
server_complete_rpc_event.success),) |
||||
|
||||
def test_rpcs(self): |
||||
expecteds = [(_common.SUCCESSFUL_OPERATION_RESULT,) * |
||||
5] * _common.RPC_COUNT |
||||
actuallys = _common.execute_many_times(self._do_rpcs) |
||||
self.assertSequenceEqual(expecteds, actuallys) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
unittest.main(verbosity=2) |
@ -0,0 +1,67 @@ |
||||
#!/bin/bash |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
set -ex |
||||
|
||||
cd $(dirname $0)/../../.. |
||||
|
||||
echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list |
||||
apt-get update |
||||
#apt-get install -t jessie-backports -y libc-ares-dev # we need specifically version 1.12 |
||||
apt-get install -t jessie-backports -y libssl-dev |
||||
|
||||
# Install c-ares |
||||
cd third_party/cares/cares |
||||
git fetch origin |
||||
git checkout cares-1_13_0 |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -DCMAKE_BUILD_TYPE=Release ../.. |
||||
make -j4 install |
||||
cd ../../../../.. |
||||
rm -rf third_party/cares/cares # wipe out to prevent influencing the grpc build |
||||
|
||||
# Install zlib |
||||
cd third_party/zlib |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -DCMAKE_BUILD_TYPE=Release ../.. |
||||
make -j4 install |
||||
cd ../../../.. |
||||
rm -rf third_party/zlib # wipe out to prevent influencing the grpc build |
||||
|
||||
# Install protobuf |
||||
cd third_party/protobuf |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -Dprotobuf_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release .. |
||||
make -j4 install |
||||
cd ../../../.. |
||||
rm -rf third_party/protobuf # wipe out to prevent influencing the grpc build |
||||
|
||||
# Install gRPC |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DgRPC_PROTOBUF_PROVIDER=package -DgRPC_ZLIB_PROVIDER=package -DgRPC_CARES_PROVIDER=package -DgRPC_SSL_PROVIDER=package -DCMAKE_BUILD_TYPE=Release ../.. |
||||
make -j4 install |
||||
cd ../.. |
||||
|
||||
# Build helloworld example using cmake |
||||
cd examples/cpp/helloworld |
||||
mkdir -p cmake/build |
||||
cd cmake/build |
||||
cmake ../.. |
||||
make |
||||
|
@ -0,0 +1,123 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# Autogenerated by tools/codegen/core/gen_stats_data.py |
||||
|
||||
import massage_qps_stats_helpers |
||||
def massage_qps_stats(scenario_result): |
||||
for stats in scenario_result["serverStats"] + scenario_result["clientStats"]: |
||||
if "coreStats" not in stats: return |
||||
core_stats = stats["coreStats"] |
||||
del stats["coreStats"] |
||||
stats["core_client_calls_created"] = massage_qps_stats_helpers.counter(core_stats, "client_calls_created") |
||||
stats["core_server_calls_created"] = massage_qps_stats_helpers.counter(core_stats, "server_calls_created") |
||||
stats["core_syscall_poll"] = massage_qps_stats_helpers.counter(core_stats, "syscall_poll") |
||||
stats["core_syscall_wait"] = massage_qps_stats_helpers.counter(core_stats, "syscall_wait") |
||||
stats["core_histogram_slow_lookups"] = massage_qps_stats_helpers.counter(core_stats, "histogram_slow_lookups") |
||||
stats["core_syscall_write"] = massage_qps_stats_helpers.counter(core_stats, "syscall_write") |
||||
stats["core_syscall_read"] = massage_qps_stats_helpers.counter(core_stats, "syscall_read") |
||||
stats["core_tcp_backup_pollers_created"] = massage_qps_stats_helpers.counter(core_stats, "tcp_backup_pollers_created") |
||||
stats["core_tcp_backup_poller_polls"] = massage_qps_stats_helpers.counter(core_stats, "tcp_backup_poller_polls") |
||||
stats["core_http2_op_batches"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_batches") |
||||
stats["core_http2_op_cancel"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_cancel") |
||||
stats["core_http2_op_send_initial_metadata"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_send_initial_metadata") |
||||
stats["core_http2_op_send_message"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_send_message") |
||||
stats["core_http2_op_send_trailing_metadata"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_send_trailing_metadata") |
||||
stats["core_http2_op_recv_initial_metadata"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_recv_initial_metadata") |
||||
stats["core_http2_op_recv_message"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_recv_message") |
||||
stats["core_http2_op_recv_trailing_metadata"] = massage_qps_stats_helpers.counter(core_stats, "http2_op_recv_trailing_metadata") |
||||
stats["core_http2_settings_writes"] = massage_qps_stats_helpers.counter(core_stats, "http2_settings_writes") |
||||
stats["core_http2_pings_sent"] = massage_qps_stats_helpers.counter(core_stats, "http2_pings_sent") |
||||
stats["core_http2_writes_begun"] = massage_qps_stats_helpers.counter(core_stats, "http2_writes_begun") |
||||
stats["core_http2_writes_offloaded"] = massage_qps_stats_helpers.counter(core_stats, "http2_writes_offloaded") |
||||
stats["core_http2_writes_continued"] = massage_qps_stats_helpers.counter(core_stats, "http2_writes_continued") |
||||
stats["core_http2_partial_writes"] = massage_qps_stats_helpers.counter(core_stats, "http2_partial_writes") |
||||
stats["core_combiner_locks_initiated"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_initiated") |
||||
stats["core_combiner_locks_scheduled_items"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_scheduled_items") |
||||
stats["core_combiner_locks_scheduled_final_items"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_scheduled_final_items") |
||||
stats["core_combiner_locks_offloaded"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_offloaded") |
||||
stats["core_executor_scheduled_short_items"] = massage_qps_stats_helpers.counter(core_stats, "executor_scheduled_short_items") |
||||
stats["core_executor_scheduled_long_items"] = massage_qps_stats_helpers.counter(core_stats, "executor_scheduled_long_items") |
||||
stats["core_executor_scheduled_to_self"] = massage_qps_stats_helpers.counter(core_stats, "executor_scheduled_to_self") |
||||
stats["core_executor_wakeup_initiated"] = massage_qps_stats_helpers.counter(core_stats, "executor_wakeup_initiated") |
||||
stats["core_executor_queue_drained"] = massage_qps_stats_helpers.counter(core_stats, "executor_queue_drained") |
||||
stats["core_executor_push_retries"] = massage_qps_stats_helpers.counter(core_stats, "executor_push_retries") |
||||
stats["core_server_requested_calls"] = massage_qps_stats_helpers.counter(core_stats, "server_requested_calls") |
||||
stats["core_server_slowpath_requests_queued"] = massage_qps_stats_helpers.counter(core_stats, "server_slowpath_requests_queued") |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "tcp_write_size") |
||||
stats["core_tcp_write_size"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_tcp_write_size_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_tcp_write_size_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_tcp_write_size_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_tcp_write_size_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "tcp_write_iov_size") |
||||
stats["core_tcp_write_iov_size"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_tcp_write_iov_size_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_tcp_write_iov_size_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_tcp_write_iov_size_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_tcp_write_iov_size_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "tcp_read_size") |
||||
stats["core_tcp_read_size"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_tcp_read_size_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_tcp_read_size_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_tcp_read_size_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_tcp_read_size_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "tcp_read_offer") |
||||
stats["core_tcp_read_offer"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_tcp_read_offer_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_tcp_read_offer_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_tcp_read_offer_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_tcp_read_offer_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "tcp_read_offer_iov_size") |
||||
stats["core_tcp_read_offer_iov_size"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_tcp_read_offer_iov_size_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_tcp_read_offer_iov_size_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_tcp_read_offer_iov_size_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_tcp_read_offer_iov_size_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "http2_send_message_size") |
||||
stats["core_http2_send_message_size"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_http2_send_message_size_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_http2_send_message_size_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_http2_send_message_size_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_http2_send_message_size_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "http2_send_initial_metadata_per_write") |
||||
stats["core_http2_send_initial_metadata_per_write"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_http2_send_initial_metadata_per_write_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_http2_send_initial_metadata_per_write_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_http2_send_initial_metadata_per_write_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_http2_send_initial_metadata_per_write_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "http2_send_message_per_write") |
||||
stats["core_http2_send_message_per_write"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_http2_send_message_per_write_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_http2_send_message_per_write_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_http2_send_message_per_write_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_http2_send_message_per_write_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "http2_send_trailing_metadata_per_write") |
||||
stats["core_http2_send_trailing_metadata_per_write"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_http2_send_trailing_metadata_per_write_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_http2_send_trailing_metadata_per_write_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_http2_send_trailing_metadata_per_write_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_http2_send_trailing_metadata_per_write_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "http2_send_flowctl_per_write") |
||||
stats["core_http2_send_flowctl_per_write"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_http2_send_flowctl_per_write_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_http2_send_flowctl_per_write_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_http2_send_flowctl_per_write_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_http2_send_flowctl_per_write_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
||||
h = massage_qps_stats_helpers.histogram(core_stats, "server_cqs_checked") |
||||
stats["core_server_cqs_checked"] = ",".join("%f" % x for x in h.buckets) |
||||
stats["core_server_cqs_checked_bkts"] = ",".join("%f" % x for x in h.boundaries) |
||||
stats["core_server_cqs_checked_50p"] = massage_qps_stats_helpers.percentile(h.buckets, 50, h.boundaries) |
||||
stats["core_server_cqs_checked_95p"] = massage_qps_stats_helpers.percentile(h.buckets, 95, h.boundaries) |
||||
stats["core_server_cqs_checked_99p"] = massage_qps_stats_helpers.percentile(h.buckets, 99, h.boundaries) |
@ -0,0 +1,57 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
import collections |
||||
|
||||
def _threshold_for_count_below(buckets, boundaries, count_below): |
||||
count_so_far = 0 |
||||
for lower_idx in range(0, len(buckets)): |
||||
count_so_far += buckets[lower_idx] |
||||
if count_so_far >= count_below: |
||||
break |
||||
if count_so_far == count_below: |
||||
# this bucket hits the threshold exactly... we should be midway through |
||||
# any run of zero values following the bucket |
||||
for upper_idx in range(lower_idx + 1, len(buckets)): |
||||
if buckets[upper_idx] != 0: |
||||
break |
||||
return (boundaries[lower_idx] + boundaries[upper_idx]) / 2.0 |
||||
else: |
||||
# treat values as uniform throughout the bucket, and find where this value |
||||
# should lie |
||||
lower_bound = boundaries[lower_idx] |
||||
upper_bound = boundaries[lower_idx + 1] |
||||
return (upper_bound - |
||||
(upper_bound - lower_bound) * (count_so_far - count_below) / |
||||
float(buckets[lower_idx])) |
||||
|
||||
def percentile(buckets, pctl, boundaries): |
||||
return _threshold_for_count_below( |
||||
buckets, boundaries, sum(buckets) * pctl / 100.0) |
||||
|
||||
def counter(core_stats, name): |
||||
for stat in core_stats['metrics']: |
||||
if stat['name'] == name: |
||||
return int(stat.get('count', 0)) |
||||
|
||||
Histogram = collections.namedtuple('Histogram', 'buckets boundaries') |
||||
def histogram(core_stats, name): |
||||
for stat in core_stats['metrics']: |
||||
if stat['name'] == name: |
||||
buckets = [] |
||||
boundaries = [] |
||||
for b in stat['histogram']['buckets']: |
||||
buckets.append(int(b.get('count', 0))) |
||||
boundaries.append(int(b.get('start', 0))) |
||||
return Histogram(buckets=buckets, boundaries=boundaries) |
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue