Merge branch 'master' into no-after-2

pull/37038/head
Craig Tiller 8 months ago
commit 1012172dfa
  1. 96
      CMakeLists.txt
  2. 2
      bazel/experiments.bzl
  3. 74
      build_autogenerated.yaml
  4. 6
      doc/interop-test-descriptions.md
  5. 6
      doc/xds-test-descriptions.md
  6. 1
      src/core/BUILD
  7. 1
      src/core/ext/transport/chaotic_good/client_transport.cc
  8. 4
      src/core/ext/transport/chaotic_good/server_transport.cc
  9. 4
      src/core/lib/debug/trace_impl.h
  10. 32
      src/core/lib/experiments/config.cc
  11. 56
      src/core/lib/experiments/config.h
  12. 17
      src/core/lib/experiments/experiments.cc
  13. 50
      src/core/lib/experiments/experiments.h
  14. 1
      src/core/lib/experiments/rollouts.yaml
  15. 10
      src/core/lib/surface/channel_init.cc
  16. 1
      src/core/load_balancing/grpclb/client_load_reporting_filter.h
  17. 5
      src/core/util/useful.h
  18. 4
      test/core/call/client_call_test.cc
  19. 4
      test/core/call/corpus/client_call/clusterfuzz-testcase-minimized-client_call_fuzzer-4634405960482816
  20. 2
      test/core/experiments/bm_experiments.cc
  21. 8
      test/core/experiments/fixtures/experiments.h
  22. 12
      test/core/test_util/BUILD
  23. 131
      test/core/test_util/passthrough_endpoint.cc
  24. 95
      test/core/test_util/passthrough_endpoint.h
  25. 48
      test/core/transport/benchmarks/BUILD
  26. 93
      test/core/transport/benchmarks/bm_chaotic_good.cc
  27. 83
      test/core/transport/benchmarks/bm_inproc.cc
  28. 83
      test/core/transport/call_spine_benchmarks.h
  29. 2
      test/core/util/useful_test.cc
  30. 695
      test/core/xds/xds_client_test.cc
  31. 2
      tools/codegen/core/experiments_compiler.py
  32. 1
      tools/distrib/python/grpcio_tools/MANIFEST.in
  33. 64
      tools/distrib/python/grpcio_tools/_spawn_patch.py
  34. 2
      tools/distrib/python/grpcio_tools/setup.py
  35. 44
      tools/run_tests/generated/tests.json
  36. 15
      tools/run_tests/sanity/banned_functions.py

96
CMakeLists.txt generated

@ -889,6 +889,9 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c bm_call_spine)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c bm_chaotic_good)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c bm_client_call)
endif()
@ -901,6 +904,9 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c bm_http_client_filter)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c bm_inproc)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c bm_party)
endif()
@ -5869,6 +5875,51 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
)
endif()
endif()
if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_executable(bm_chaotic_good
src/core/ext/transport/chaotic_good/client_transport.cc
src/core/ext/transport/chaotic_good/frame.cc
src/core/ext/transport/chaotic_good/frame_header.cc
src/core/ext/transport/chaotic_good/server_transport.cc
src/core/lib/transport/promise_endpoint.cc
test/core/test_util/passthrough_endpoint.cc
test/core/transport/benchmarks/bm_chaotic_good.cc
)
if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS)
target_compile_definitions(bm_chaotic_good
PRIVATE
"GPR_DLL_IMPORTS"
"GRPC_DLL_IMPORTS"
)
endif()
endif()
target_compile_features(bm_chaotic_good PUBLIC cxx_std_14)
target_include_directories(bm_chaotic_good
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
)
target_link_libraries(bm_chaotic_good
${_gRPC_ALLTARGETS_LIBRARIES}
${_gRPC_BENCHMARK_LIBRARIES}
grpc
)
endif()
endif()
if(gRPC_BUILD_TESTS)
@ -6025,6 +6076,51 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
)
endif()
endif()
if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
add_executable(bm_inproc
src/core/ext/transport/chaotic_good/client_transport.cc
src/core/ext/transport/chaotic_good/frame.cc
src/core/ext/transport/chaotic_good/frame_header.cc
src/core/ext/transport/chaotic_good/server_transport.cc
src/core/lib/transport/promise_endpoint.cc
test/core/test_util/passthrough_endpoint.cc
test/core/transport/benchmarks/bm_inproc.cc
)
if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS)
target_compile_definitions(bm_inproc
PRIVATE
"GPR_DLL_IMPORTS"
"GRPC_DLL_IMPORTS"
)
endif()
endif()
target_compile_features(bm_inproc PUBLIC cxx_std_14)
target_include_directories(bm_inproc
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
)
target_link_libraries(bm_inproc
${_gRPC_ALLTARGETS_LIBRARIES}
${_gRPC_BENCHMARK_LIBRARIES}
grpc
)
endif()
endif()
if(gRPC_BUILD_TESTS)

@ -41,7 +41,7 @@ EXPERIMENT_ENABLES = {
"trace_record_callops": "trace_record_callops",
"unconstrained_max_quota_buffer_size": "unconstrained_max_quota_buffer_size",
"work_serializer_clears_time_cache": "work_serializer_clears_time_cache",
"work_serializer_dispatch": "event_engine_client,work_serializer_dispatch",
"work_serializer_dispatch": "work_serializer_dispatch",
}
EXPERIMENT_POLLERS = [

@ -5157,6 +5157,43 @@ targets:
- linux
- posix
uses_polling: false
- name: bm_chaotic_good
build: test
language: c
headers:
- src/core/ext/transport/chaotic_good/chaotic_good_transport.h
- src/core/ext/transport/chaotic_good/client_transport.h
- src/core/ext/transport/chaotic_good/frame.h
- src/core/ext/transport/chaotic_good/frame_header.h
- src/core/ext/transport/chaotic_good/server_transport.h
- src/core/lib/promise/event_engine_wakeup_scheduler.h
- src/core/lib/promise/inter_activity_latch.h
- src/core/lib/promise/inter_activity_pipe.h
- src/core/lib/promise/mpsc.h
- src/core/lib/promise/switch.h
- src/core/lib/promise/wait_set.h
- src/core/lib/transport/promise_endpoint.h
- test/core/test_util/passthrough_endpoint.h
- test/core/transport/call_spine_benchmarks.h
src:
- src/core/ext/transport/chaotic_good/client_transport.cc
- src/core/ext/transport/chaotic_good/frame.cc
- src/core/ext/transport/chaotic_good/frame_header.cc
- src/core/ext/transport/chaotic_good/server_transport.cc
- src/core/lib/transport/promise_endpoint.cc
- test/core/test_util/passthrough_endpoint.cc
- test/core/transport/benchmarks/bm_chaotic_good.cc
deps:
- benchmark
- grpc
args:
- --benchmark_min_time=0.001s
benchmark: true
defaults: benchmark
platforms:
- linux
- posix
uses_polling: false
- name: bm_client_call
build: test
language: c
@ -5227,6 +5264,43 @@ targets:
- linux
- posix
uses_polling: false
- name: bm_inproc
build: test
language: c
headers:
- src/core/ext/transport/chaotic_good/chaotic_good_transport.h
- src/core/ext/transport/chaotic_good/client_transport.h
- src/core/ext/transport/chaotic_good/frame.h
- src/core/ext/transport/chaotic_good/frame_header.h
- src/core/ext/transport/chaotic_good/server_transport.h
- src/core/lib/promise/event_engine_wakeup_scheduler.h
- src/core/lib/promise/inter_activity_latch.h
- src/core/lib/promise/inter_activity_pipe.h
- src/core/lib/promise/mpsc.h
- src/core/lib/promise/switch.h
- src/core/lib/promise/wait_set.h
- src/core/lib/transport/promise_endpoint.h
- test/core/test_util/passthrough_endpoint.h
- test/core/transport/call_spine_benchmarks.h
src:
- src/core/ext/transport/chaotic_good/client_transport.cc
- src/core/ext/transport/chaotic_good/frame.cc
- src/core/ext/transport/chaotic_good/frame_header.cc
- src/core/ext/transport/chaotic_good/server_transport.cc
- src/core/lib/transport/promise_endpoint.cc
- test/core/test_util/passthrough_endpoint.cc
- test/core/transport/benchmarks/bm_inproc.cc
deps:
- benchmark
- grpc
args:
- --benchmark_min_time=0.001s
benchmark: true
defaults: benchmark
platforms:
- linux
- posix
uses_polling: false
- name: bm_party
build: test
language: c

@ -1287,6 +1287,12 @@ Servers should accept these arguments:
* Whether to use a plaintext or encrypted connection
Servers that want to be used for dual stack testing must accept this argument:
* --address_type=IPV4|IPV6|IPV4_IPV6
* What type of addresses to listen on. Default IPV4_IPV6
Servers must support TLS with ALPN. They should use
[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/server1.pem)
for their certificate.

@ -17,6 +17,12 @@ Server should accept these arguments:
* When set to true it uses XdsServerCredentials with the test server for security test cases.
In case of secure mode, port and maintenance_port should be different.
Servers that want to support dual stack testing (like Java) should also accept:
* --address_type=IPV4|IPV6|IPV4_IPV6
* Type of IP address to bind to. IPV4_IPV6 will use the wildcard address.
IPV4 and IPV6 will cause server to bind to one non-localhost and the localhost address of the appropriate type
In addition, when handling requests, if the initial request metadata contains the `rpc-behavior` key, it should modify its handling of the request as follows:
- If the value matches `sleep-<int>`, the server should wait the specified number of seconds before resuming behavior matching and RPC processing.

@ -242,6 +242,7 @@ grpc_cc_library(
name = "useful",
hdrs = ["util/useful.h"],
external_deps = [
"absl/log:check",
"absl/strings",
"absl/types:variant",
],

@ -58,7 +58,6 @@ namespace grpc_core {
namespace chaotic_good {
void ChaoticGoodClientTransport::Orphan() {
LOG(INFO) << "ChaoticGoodClientTransport::Orphan";
AbortWithError();
ActivityPtr writer;
ActivityPtr reader;

@ -323,9 +323,7 @@ auto ChaoticGoodServerTransport::ReadOneFrame(ChaoticGoodTransport& transport) {
return absl::OkStatus();
});
},
[]() -> absl::Status {
return absl::InternalError("Unexpected cancel frame");
});
[]() -> absl::Status { return absl::OkStatus(); });
}),
Default([frame_header]() {
return absl::InternalError(

@ -25,6 +25,10 @@
#include <grpc/support/port_platform.h>
#ifdef _WIN32
#undef ERROR
#endif
void grpc_tracer_init();
void grpc_tracer_shutdown(void);

@ -170,6 +170,7 @@ Experiments& ExperimentsSingleton() {
} // namespace
void TestOnlyReloadExperimentsFromConfigVariables() {
ExperimentFlags::TestOnlyClear();
ExperimentsSingleton() = LoadExperimentsFromConfigVariable();
PrintExperimentsList();
}
@ -180,8 +181,35 @@ void LoadTestOnlyExperimentsFromMetadata(
new TestExperiments(experiment_metadata, num_experiments);
}
bool IsExperimentEnabled(size_t experiment_id) {
return ExperimentsSingleton().enabled[experiment_id];
std::atomic<uint64_t>
ExperimentFlags::experiment_flags_[kNumExperimentFlagsWords];
bool ExperimentFlags::LoadFlagsAndCheck(size_t experiment_id) {
static_assert(kNumExperiments < kNumExperimentFlagsWords * kFlagsPerWord,
"kNumExperiments must be less than "
"kNumExperimentFlagsWords*kFlagsPerWord; if this fails then "
"make kNumExperimentFlagsWords bigger.");
const auto& experiments = ExperimentsSingleton();
uint64_t building[kNumExperimentFlagsWords];
for (size_t i = 0; i < kNumExperimentFlagsWords; i++) {
building[i] = kLoadedFlag;
}
for (size_t i = 0; i < kNumExperiments; i++) {
if (!experiments.enabled[i]) continue;
auto bit = i % kFlagsPerWord;
auto word = i / kFlagsPerWord;
building[word] |= 1ull << bit;
}
for (size_t i = 0; i < kNumExperimentFlagsWords; i++) {
experiment_flags_[i].store(building[i], std::memory_order_relaxed);
}
return experiments.enabled[experiment_id];
}
void ExperimentFlags::TestOnlyClear() {
for (size_t i = 0; i < kNumExperimentFlagsWords; i++) {
experiment_flags_[i].store(0, std::memory_order_relaxed);
}
}
bool IsExperimentEnabledInConfiguration(size_t experiment_id) {

@ -18,6 +18,8 @@
#include <stddef.h>
#include <stdint.h>
#include <atomic>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
@ -38,16 +40,68 @@ struct ExperimentMetadata {
};
#ifndef GRPC_EXPERIMENTS_ARE_FINAL
class ExperimentFlags {
public:
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static bool IsExperimentEnabled(
size_t experiment_id) {
auto bit = experiment_id % kFlagsPerWord;
auto word = experiment_id / kFlagsPerWord;
auto cur = experiment_flags_[word].load(std::memory_order_relaxed);
if (cur & (1ull << bit)) return true;
if (cur & kLoadedFlag) return false;
return LoadFlagsAndCheck(experiment_id);
}
template <size_t kExperimentId>
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static bool IsExperimentEnabled() {
auto bit = kExperimentId % kFlagsPerWord;
auto word = kExperimentId / kFlagsPerWord;
auto cur = experiment_flags_[word].load(std::memory_order_relaxed);
if (cur & (1ull << bit)) return true;
if (cur & kLoadedFlag) return false;
return LoadFlagsAndCheck(kExperimentId);
}
static void TestOnlyClear();
private:
static bool LoadFlagsAndCheck(size_t experiment_id);
// We layout experiment flags in groups of 63... each 64 bit word contains
// 63 enablement flags (one per experiment), and the high bit which indicates
// whether the flags have been loaded from the configuration.
// Consequently, with one load, we can tell if the experiment is definitely
// enabled (the bit is set), or definitely disabled (the bit is clear, and the
// loaded flag is set), or if we need to load the flags and re-check.
static constexpr size_t kNumExperimentFlagsWords = 8;
static constexpr size_t kFlagsPerWord = 63;
static constexpr uint64_t kLoadedFlag = 0x8000000000000000ull;
static std::atomic<uint64_t> experiment_flags_[kNumExperimentFlagsWords];
};
// Return true if experiment \a experiment_id is enabled.
// Experiments are numbered by their order in the g_experiment_metadata array
// declared in experiments.h.
bool IsExperimentEnabled(size_t experiment_id);
inline bool IsExperimentEnabled(size_t experiment_id) {
return ExperimentFlags::IsExperimentEnabled(experiment_id);
}
template <size_t kExperimentId>
inline bool IsExperimentEnabled() {
return ExperimentFlags::IsExperimentEnabled<kExperimentId>();
}
// Given a test experiment id, returns true if the test experiment is enabled.
// Test experiments can be loaded using the LoadTestOnlyExperimentsFromMetadata
// method.
bool IsTestExperimentEnabled(size_t experiment_id);
template <size_t kExperimentId>
inline bool IsTestExperimentEnabled() {
return IsTestExperimentEnabled(kExperimentId);
}
// Slow check for if a named experiment is enabled.
// Parses the configuration and looks up the experiment in that, so it does not
// affect any global state, but it does require parsing the configuration every

@ -16,8 +16,6 @@
#include "src/core/lib/experiments/experiments.h"
#include <stdint.h>
#include <grpc/support/port_platform.h>
#ifndef GRPC_EXPERIMENTS_ARE_FINAL
@ -114,8 +112,6 @@ const char* const description_work_serializer_dispatch =
"callback, instead of running things inline in the first thread that "
"successfully enqueues work.";
const char* const additional_constraints_work_serializer_dispatch = "{}";
const uint8_t required_experiments_work_serializer_dispatch[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient)};
} // namespace
namespace grpc_core {
@ -181,8 +177,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
true},
{"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch,
required_experiments_work_serializer_dispatch, 1, false, true},
additional_constraints_work_serializer_dispatch, nullptr, 0, false, true},
};
} // namespace grpc_core
@ -279,8 +274,6 @@ const char* const description_work_serializer_dispatch =
"callback, instead of running things inline in the first thread that "
"successfully enqueues work.";
const char* const additional_constraints_work_serializer_dispatch = "{}";
const uint8_t required_experiments_work_serializer_dispatch[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient)};
} // namespace
namespace grpc_core {
@ -346,8 +339,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
true},
{"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch,
required_experiments_work_serializer_dispatch, 1, false, true},
additional_constraints_work_serializer_dispatch, nullptr, 0, false, true},
};
} // namespace grpc_core
@ -444,8 +436,6 @@ const char* const description_work_serializer_dispatch =
"callback, instead of running things inline in the first thread that "
"successfully enqueues work.";
const char* const additional_constraints_work_serializer_dispatch = "{}";
const uint8_t required_experiments_work_serializer_dispatch[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient)};
} // namespace
namespace grpc_core {
@ -511,8 +501,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
true},
{"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch,
required_experiments_work_serializer_dispatch, 1, true, true},
additional_constraints_work_serializer_dispatch, nullptr, 0, true, true},
};
} // namespace grpc_core

@ -193,103 +193,103 @@ enum ExperimentIds {
};
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
inline bool IsCallStatusOverrideOnCancellationEnabled() {
return IsExperimentEnabled(kExperimentIdCallStatusOverrideOnCancellation);
return IsExperimentEnabled<kExperimentIdCallStatusOverrideOnCancellation>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CANARY_CLIENT_PRIVACY
inline bool IsCanaryClientPrivacyEnabled() {
return IsExperimentEnabled(kExperimentIdCanaryClientPrivacy);
return IsExperimentEnabled<kExperimentIdCanaryClientPrivacy>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CLIENT_PRIVACY
inline bool IsClientPrivacyEnabled() {
return IsExperimentEnabled(kExperimentIdClientPrivacy);
return IsExperimentEnabled<kExperimentIdClientPrivacy>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_CLIENT
inline bool IsEventEngineClientEnabled() {
return IsExperimentEnabled(kExperimentIdEventEngineClient);
return IsExperimentEnabled<kExperimentIdEventEngineClient>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_DNS
inline bool IsEventEngineDnsEnabled() {
return IsExperimentEnabled(kExperimentIdEventEngineDns);
return IsExperimentEnabled<kExperimentIdEventEngineDns>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
inline bool IsEventEngineListenerEnabled() {
return IsExperimentEnabled(kExperimentIdEventEngineListener);
return IsExperimentEnabled<kExperimentIdEventEngineListener>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_FREE_LARGE_ALLOCATOR
inline bool IsFreeLargeAllocatorEnabled() {
return IsExperimentEnabled(kExperimentIdFreeLargeAllocator);
return IsExperimentEnabled<kExperimentIdFreeLargeAllocator>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_HTTP2_STATS_FIX
inline bool IsHttp2StatsFixEnabled() {
return IsExperimentEnabled(kExperimentIdHttp2StatsFix);
return IsExperimentEnabled<kExperimentIdHttp2StatsFix>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_KEEPALIVE_FIX
inline bool IsKeepaliveFixEnabled() {
return IsExperimentEnabled(kExperimentIdKeepaliveFix);
return IsExperimentEnabled<kExperimentIdKeepaliveFix>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_KEEPALIVE_SERVER_FIX
inline bool IsKeepaliveServerFixEnabled() {
return IsExperimentEnabled(kExperimentIdKeepaliveServerFix);
return IsExperimentEnabled<kExperimentIdKeepaliveServerFix>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_MAX_PINGS_WO_DATA_THROTTLE
inline bool IsMaxPingsWoDataThrottleEnabled() {
return IsExperimentEnabled(kExperimentIdMaxPingsWoDataThrottle);
return IsExperimentEnabled<kExperimentIdMaxPingsWoDataThrottle>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_MONITORING_EXPERIMENT
inline bool IsMonitoringExperimentEnabled() {
return IsExperimentEnabled(kExperimentIdMonitoringExperiment);
return IsExperimentEnabled<kExperimentIdMonitoringExperiment>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_MULTIPING
inline bool IsMultipingEnabled() {
return IsExperimentEnabled(kExperimentIdMultiping);
return IsExperimentEnabled<kExperimentIdMultiping>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_PEER_STATE_BASED_FRAMING
inline bool IsPeerStateBasedFramingEnabled() {
return IsExperimentEnabled(kExperimentIdPeerStateBasedFraming);
return IsExperimentEnabled<kExperimentIdPeerStateBasedFraming>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() {
return IsExperimentEnabled(kExperimentIdPickFirstNew);
return IsExperimentEnabled<kExperimentIdPickFirstNew>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_INPROC_TRANSPORT
inline bool IsPromiseBasedInprocTransportEnabled() {
return IsExperimentEnabled(kExperimentIdPromiseBasedInprocTransport);
return IsExperimentEnabled<kExperimentIdPromiseBasedInprocTransport>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_RSTPIT
inline bool IsRstpitEnabled() {
return IsExperimentEnabled(kExperimentIdRstpit);
return IsExperimentEnabled<kExperimentIdRstpit>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_SCHEDULE_CANCELLATION_OVER_WRITE
inline bool IsScheduleCancellationOverWriteEnabled() {
return IsExperimentEnabled(kExperimentIdScheduleCancellationOverWrite);
return IsExperimentEnabled<kExperimentIdScheduleCancellationOverWrite>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_SERVER_PRIVACY
inline bool IsServerPrivacyEnabled() {
return IsExperimentEnabled(kExperimentIdServerPrivacy);
return IsExperimentEnabled<kExperimentIdServerPrivacy>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_TCP_FRAME_SIZE_TUNING
inline bool IsTcpFrameSizeTuningEnabled() {
return IsExperimentEnabled(kExperimentIdTcpFrameSizeTuning);
return IsExperimentEnabled<kExperimentIdTcpFrameSizeTuning>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_TCP_RCV_LOWAT
inline bool IsTcpRcvLowatEnabled() {
return IsExperimentEnabled(kExperimentIdTcpRcvLowat);
return IsExperimentEnabled<kExperimentIdTcpRcvLowat>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS
inline bool IsTraceRecordCallopsEnabled() {
return IsExperimentEnabled(kExperimentIdTraceRecordCallops);
return IsExperimentEnabled<kExperimentIdTraceRecordCallops>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_UNCONSTRAINED_MAX_QUOTA_BUFFER_SIZE
inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() {
return IsExperimentEnabled(kExperimentIdUnconstrainedMaxQuotaBufferSize);
return IsExperimentEnabled<kExperimentIdUnconstrainedMaxQuotaBufferSize>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() {
return IsExperimentEnabled(kExperimentIdWorkSerializerClearsTimeCache);
return IsExperimentEnabled<kExperimentIdWorkSerializerClearsTimeCache>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_DISPATCH
inline bool IsWorkSerializerDispatchEnabled() {
return IsExperimentEnabled(kExperimentIdWorkSerializerDispatch);
return IsExperimentEnabled<kExperimentIdWorkSerializerDispatch>();
}
extern const ExperimentMetadata g_experiment_metadata[kNumExperiments];

@ -111,7 +111,6 @@
- name: work_serializer_clears_time_cache
default: true
- name: work_serializer_dispatch
requires: ["event_engine_client"]
default:
# TODO(ysseung): Not fully tested.
ios: broken

@ -126,13 +126,15 @@ class ChannelInit::DependencyTracker {
auto it_a = nodes_.find(a);
auto it_b = nodes_.find(b);
if (it_a == nodes_.end()) {
LOG(ERROR) << "gRPC Filter " << a.name()
<< " was not declared before adding an edge to " << b.name();
GRPC_TRACE_LOG(channel_stack, INFO)
<< "gRPC Filter " << a.name()
<< " was not declared before adding an edge to " << b.name();
return;
}
if (it_b == nodes_.end()) {
LOG(ERROR) << "gRPC Filter " << b.name()
<< " was not declared before adding an edge from " << a.name();
GRPC_TRACE_LOG(channel_stack, INFO)
<< "gRPC Filter " << b.name()
<< " was not declared before adding an edge from " << a.name();
return;
}
auto& node_a = it_a->second;

@ -28,6 +28,7 @@
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/load_balancing/grpclb/grpclb_client_stats.h"
namespace grpc_core {

@ -23,6 +23,7 @@
#include <cstddef>
#include "absl/log/check.h"
#include "absl/strings/string_view.h"
#include "absl/types/variant.h"
@ -115,19 +116,23 @@ GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline constexpr uint32_t BitCount(
#if GRPC_HAS_BUILTIN(__builtin_ctz)
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline constexpr uint32_t
CountTrailingZeros(uint32_t i) {
DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0
return __builtin_ctz(i);
}
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline constexpr uint32_t
CountTrailingZeros(uint64_t i) {
DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0
return __builtin_ctzll(i);
}
#else
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline constexpr uint32_t
CountTrailingZeros(uint32_t i) {
DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0
return BitCount((i & -i) - 1);
}
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline constexpr uint32_t
CountTrailingZeros(uint64_t i) {
DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0
return BitCount((i & -i) - 1);
}
#endif

@ -217,7 +217,9 @@ CLIENT_CALL_TEST(SendInitialMetadataAndReceiveStatusAfterTimeout) {
ExecCtx::Get()->InvalidateNow();
auto now = Timestamp::Now();
EXPECT_GE(now - start, Duration::Seconds(1)) << GRPC_DUMP_ARGS(now, start);
EXPECT_LE(now - start, Duration::Seconds(5)) << GRPC_DUMP_ARGS(now, start);
EXPECT_LE(now - start,
g_yodel_fuzzing ? Duration::Minutes(10) : Duration::Seconds(5))
<< GRPC_DUMP_ARGS(now, start);
WaitForAllPendingWork();
}

@ -0,0 +1,4 @@
test_id: 178
event_engine_actions {
run_delay: 261993005056
}

@ -18,7 +18,7 @@
static void BM_IsExperimentEnabled(benchmark::State& state) {
for (auto _ : state) {
grpc_core::IsMonitoringExperimentEnabled();
benchmark::DoNotOptimize(grpc_core::IsMonitoringExperimentEnabled());
}
}
BENCHMARK(BM_IsExperimentEnabled);

@ -133,19 +133,19 @@ enum ExperimentIds {
};
#define GRPC_EXPERIMENT_IS_INCLUDED_TEST_EXPERIMENT_1
inline bool IsTestExperiment1Enabled() {
return IsTestExperimentEnabled(kExperimentIdTestExperiment1);
return IsTestExperimentEnabled<kExperimentIdTestExperiment1>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_TEST_EXPERIMENT_2
inline bool IsTestExperiment2Enabled() {
return IsTestExperimentEnabled(kExperimentIdTestExperiment2);
return IsTestExperimentEnabled<kExperimentIdTestExperiment2>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_TEST_EXPERIMENT_3
inline bool IsTestExperiment3Enabled() {
return IsTestExperimentEnabled(kExperimentIdTestExperiment3);
return IsTestExperimentEnabled<kExperimentIdTestExperiment3>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_TEST_EXPERIMENT_4
inline bool IsTestExperiment4Enabled() {
return IsTestExperimentEnabled(kExperimentIdTestExperiment4);
return IsTestExperimentEnabled<kExperimentIdTestExperiment4>();
}
extern const ExperimentMetadata g_test_experiment_metadata[kNumTestExperiments];

@ -535,3 +535,15 @@ grpc_cc_library(
"//src/core:metrics",
],
)
grpc_cc_library(
name = "passthrough_endpoint",
testonly = True,
srcs = ["passthrough_endpoint.cc"],
hdrs = ["passthrough_endpoint.h"],
external_deps = [
],
deps = [
"//:grpc",
],
)

@ -0,0 +1,131 @@
// Copyright 2024 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.
#include "test/core/test_util/passthrough_endpoint.h"
namespace grpc_event_engine {
namespace experimental {
class PassthroughEndpoint::CallbackHelper {
public:
CallbackHelper(EventEngine* event_engine, bool allow_inline_callbacks)
: event_engine_(allow_inline_callbacks ? nullptr : event_engine) {}
template <typename F>
void AddCallback(F&& callback) {
if (event_engine_ != nullptr) {
event_engine_->Run(std::forward<F>(callback));
} else {
callbacks_.emplace_back(std::forward<F>(callback));
}
}
~CallbackHelper() {
for (auto& callback : callbacks_) {
callback();
}
}
private:
EventEngine* event_engine_;
absl::InlinedVector<absl::AnyInvocable<void()>, 4> callbacks_;
};
PassthroughEndpoint::PassthroughEndpointPair
PassthroughEndpoint::MakePassthroughEndpoint(int client_port, int server_port,
bool allow_inline_callbacks) {
auto send_middle =
grpc_core::MakeRefCounted<PassthroughEndpoint::Middle>(client_port);
auto recv_middle =
grpc_core::MakeRefCounted<PassthroughEndpoint::Middle>(server_port);
auto client = std::unique_ptr<PassthroughEndpoint>(new PassthroughEndpoint(
send_middle, recv_middle, allow_inline_callbacks));
auto server = std::unique_ptr<PassthroughEndpoint>(new PassthroughEndpoint(
recv_middle, send_middle, allow_inline_callbacks));
return {std::move(client), std::move(server)};
}
PassthroughEndpoint::~PassthroughEndpoint() {
CallbackHelper callback_helper(event_engine_.get(), allow_inline_callbacks_);
send_middle_->Close(callback_helper);
recv_middle_->Close(callback_helper);
}
bool PassthroughEndpoint::Read(absl::AnyInvocable<void(absl::Status)> on_read,
SliceBuffer* buffer, const ReadArgs*) {
CallbackHelper callback_helper(event_engine_.get(), allow_inline_callbacks_);
grpc_core::MutexLock lock(&recv_middle_->mu);
if (recv_middle_->closed) {
callback_helper.AddCallback([on_read = std::move(on_read)]() mutable {
on_read(absl::CancelledError());
});
return false;
}
if (recv_middle_->on_write != nullptr) {
*buffer = std::move(*recv_middle_->write_buffer);
callback_helper.AddCallback(
[on_write = std::move(recv_middle_->on_write)]() mutable {
on_write(absl::OkStatus());
});
recv_middle_->on_write = nullptr;
return true;
}
recv_middle_->read_buffer = buffer;
recv_middle_->on_read = std::move(on_read);
return false;
}
bool PassthroughEndpoint::Write(absl::AnyInvocable<void(absl::Status)> on_write,
SliceBuffer* buffer, const WriteArgs*) {
CallbackHelper callback_helper(event_engine_.get(), allow_inline_callbacks_);
grpc_core::MutexLock lock(&send_middle_->mu);
if (send_middle_->closed) {
callback_helper.AddCallback([on_write = std::move(on_write)]() mutable {
on_write(absl::CancelledError());
});
return false;
}
if (send_middle_->on_read != nullptr) {
*send_middle_->read_buffer = std::move(*buffer);
callback_helper.AddCallback(
[on_read = std::move(send_middle_->on_read)]() mutable {
on_read(absl::OkStatus());
});
send_middle_->on_read = nullptr;
return true;
}
send_middle_->write_buffer = buffer;
send_middle_->on_write = std::move(on_write);
return false;
}
void PassthroughEndpoint::Middle::Close(CallbackHelper& callback_helper) {
grpc_core::MutexLock lock(&mu);
closed = true;
if (on_read != nullptr) {
callback_helper.AddCallback([on_read = std::move(on_read)]() mutable {
on_read(absl::CancelledError());
});
on_read = nullptr;
}
if (on_write != nullptr) {
callback_helper.AddCallback([on_write = std::move(on_write)]() mutable {
on_write(absl::CancelledError());
});
on_write = nullptr;
}
}
} // namespace experimental
} // namespace grpc_event_engine

@ -0,0 +1,95 @@
// Copyright 2024 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.
#ifndef GRPC_TEST_CORE_TEST_UTIL_PASSTHROUGH_ENDPOINT_H
#define GRPC_TEST_CORE_TEST_UTIL_PASSTHROUGH_ENDPOINT_H
#include <memory>
#include <grpc/event_engine/event_engine.h>
#include "src/core/lib/event_engine/default_event_engine.h"
#include "src/core/lib/event_engine/tcp_socket_utils.h"
#include "src/core/lib/gprpp/ref_counted.h"
namespace grpc_event_engine {
namespace experimental {
class PassthroughEndpoint final : public EventEngine::Endpoint {
public:
struct PassthroughEndpointPair {
std::unique_ptr<PassthroughEndpoint> client;
std::unique_ptr<PassthroughEndpoint> server;
};
// client_port, server_port are markers that are baked into the peer/local
// addresses for debug information.
// allow_inline_callbacks is a flag that allows the endpoint to call the
// on_read/on_write callbacks inline (but outside any PassthroughEndpoint
// locks)
static PassthroughEndpointPair MakePassthroughEndpoint(
int client_port, int server_port, bool allow_inline_callbacks);
~PassthroughEndpoint() override;
bool Read(absl::AnyInvocable<void(absl::Status)> on_read, SliceBuffer* buffer,
const ReadArgs* args) override;
bool Write(absl::AnyInvocable<void(absl::Status)> on_write,
SliceBuffer* buffer, const WriteArgs* args) override;
const EventEngine::ResolvedAddress& GetPeerAddress() const override {
return recv_middle_->address;
}
const EventEngine::ResolvedAddress& GetLocalAddress() const override {
return send_middle_->address;
}
private:
class CallbackHelper;
struct Middle : public grpc_core::RefCounted<Middle> {
explicit Middle(int port)
: address(URIToResolvedAddress(absl::StrCat("ipv4:127.0.0.1:", port))
.value()) {}
void Close(CallbackHelper& callback_helper);
grpc_core::Mutex mu;
bool closed ABSL_GUARDED_BY(mu) = false;
SliceBuffer* read_buffer ABSL_GUARDED_BY(mu) = nullptr;
absl::AnyInvocable<void(absl::Status)> on_read ABSL_GUARDED_BY(mu) =
nullptr;
SliceBuffer* write_buffer ABSL_GUARDED_BY(mu) = nullptr;
absl::AnyInvocable<void(absl::Status)> on_write ABSL_GUARDED_BY(mu) =
nullptr;
EventEngine::ResolvedAddress address;
};
PassthroughEndpoint(grpc_core::RefCountedPtr<Middle> send_middle,
grpc_core::RefCountedPtr<Middle> recv_middle,
bool allow_inline_callbacks)
: send_middle_(std::move(send_middle)),
recv_middle_(std::move(recv_middle)),
allow_inline_callbacks_(allow_inline_callbacks) {}
grpc_core::RefCountedPtr<Middle> send_middle_;
grpc_core::RefCountedPtr<Middle> recv_middle_;
std::shared_ptr<EventEngine> event_engine_ = GetDefaultEventEngine();
bool allow_inline_callbacks_;
};
} // namespace experimental
} // namespace grpc_event_engine
#endif // GRPC_TEST_CORE_TEST_UTIL_PASSTHROUGH_ENDPOINT_H

@ -0,0 +1,48 @@
# Copyright 2021 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.
load("//bazel:grpc_build_system.bzl", "grpc_package")
load("//test/cpp/microbenchmarks:grpc_benchmark_config.bzl", "grpc_cc_benchmark")
licenses(["notice"])
grpc_package(
name = "test/core/transport/benchmarks",
)
grpc_cc_benchmark(
name = "bm_chaotic_good",
srcs = ["bm_chaotic_good.cc"],
deps = [
"//:grpc",
"//src/core:chaotic_good_client_transport",
"//src/core:chaotic_good_server_transport",
"//src/core:default_event_engine",
"//test/core/test_util:passthrough_endpoint",
"//test/core/transport:call_spine_benchmarks",
],
)
grpc_cc_benchmark(
name = "bm_inproc",
srcs = ["bm_inproc.cc"],
deps = [
"//:grpc",
"//src/core:chaotic_good_client_transport",
"//src/core:chaotic_good_server_transport",
"//src/core:default_event_engine",
"//test/core/test_util:passthrough_endpoint",
"//test/core/transport:call_spine_benchmarks",
],
)

@ -0,0 +1,93 @@
// Copyright 2024 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.
#include <benchmark/benchmark.h>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include <grpc/grpc.h>
#include "src/core/ext/transport/chaotic_good/client_transport.h"
#include "src/core/ext/transport/chaotic_good/server_transport.h"
#include "src/core/lib/address_utils/parse_address.h"
#include "test/core/test_util/passthrough_endpoint.h"
#include "test/core/transport/call_spine_benchmarks.h"
namespace grpc_core {
namespace {
const Slice kTestPath = Slice::FromExternalString("/foo/bar");
class ChaoticGoodTraits {
public:
BenchmarkTransport MakeTransport() {
auto channel_args = CoreConfiguration::Get()
.channel_args_preconditioning()
.PreconditionChannelArgs(nullptr);
auto control = grpc_event_engine::experimental::PassthroughEndpoint::
MakePassthroughEndpoint(1, 2, true);
auto data = grpc_event_engine::experimental::PassthroughEndpoint::
MakePassthroughEndpoint(3, 4, true);
auto client = MakeOrphanable<chaotic_good::ChaoticGoodClientTransport>(
PromiseEndpoint(std::move(control.client), SliceBuffer()),
PromiseEndpoint(std::move(data.client), SliceBuffer()), channel_args,
grpc_event_engine::experimental::GetDefaultEventEngine(), HPackParser(),
HPackCompressor());
auto server = MakeOrphanable<chaotic_good::ChaoticGoodServerTransport>(
channel_args, PromiseEndpoint(std::move(control.server), SliceBuffer()),
PromiseEndpoint(std::move(data.server), SliceBuffer()),
grpc_event_engine::experimental::GetDefaultEventEngine(), HPackParser(),
HPackCompressor());
return {std::move(client), std::move(server)};
}
ClientMetadataHandle MakeClientInitialMetadata() {
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), kTestPath.Copy());
return md;
}
ServerMetadataHandle MakeServerInitialMetadata() {
return Arena::MakePooled<ServerMetadata>();
}
MessageHandle MakePayload() { return Arena::MakePooled<Message>(); }
ServerMetadataHandle MakeServerTrailingMetadata() {
auto md = Arena::MakePooled<ServerMetadata>();
return md;
}
};
GRPC_CALL_SPINE_BENCHMARK(TransportFixture<ChaoticGoodTraits>);
} // namespace
} // namespace grpc_core
// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
} // namespace benchmark
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
grpc_init();
{
auto ee = grpc_event_engine::experimental::GetDefaultEventEngine();
benchmark::RunTheBenchmarksNamespaced();
}
grpc_shutdown();
return 0;
}

@ -0,0 +1,83 @@
// Copyright 2024 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.
#include <memory>
#include <benchmark/benchmark.h>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include <grpc/grpc.h>
#include "src/core/ext/transport/inproc/inproc_transport.h"
#include "src/core/lib/address_utils/parse_address.h"
#include "test/core/transport/call_spine_benchmarks.h"
namespace grpc_core {
namespace {
const Slice kTestPath = Slice::FromExternalString("/foo/bar");
class InprocTraits {
public:
BenchmarkTransport MakeTransport() {
auto channel_args = CoreConfiguration::Get()
.channel_args_preconditioning()
.PreconditionChannelArgs(nullptr);
auto t = MakeInProcessTransportPair(channel_args);
return {OrphanablePtr<ClientTransport>(
DownCast<ClientTransport*>(t.first.release())),
OrphanablePtr<ServerTransport>(
DownCast<ServerTransport*>(t.second.release()))};
}
ClientMetadataHandle MakeClientInitialMetadata() {
auto md = Arena::MakePooled<ClientMetadata>();
md->Set(HttpPathMetadata(), kTestPath.Copy());
return md;
}
ServerMetadataHandle MakeServerInitialMetadata() {
return Arena::MakePooled<ServerMetadata>();
}
MessageHandle MakePayload() { return Arena::MakePooled<Message>(); }
ServerMetadataHandle MakeServerTrailingMetadata() {
auto md = Arena::MakePooled<ServerMetadata>();
return md;
}
};
GRPC_CALL_SPINE_BENCHMARK(TransportFixture<InprocTraits>);
} // namespace
} // namespace grpc_core
// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
} // namespace benchmark
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
grpc_init();
{
auto ee = grpc_event_engine::experimental::GetDefaultEventEngine();
benchmark::RunTheBenchmarksNamespaced();
}
grpc_shutdown();
return 0;
}

@ -27,6 +27,7 @@
#include "src/core/lib/promise/map.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/transport/call_spine.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
@ -361,6 +362,88 @@ class UnstartedCallDestinationFixture {
traits_->CreateCallDestination(bottom_destination_);
};
// Base class for transports
// Traits should have MakeClientInitialMetadata, MakeServerInitialMetadata,
// MakePayload, MakeServerTrailingMetadata.
// They should also have a MakeTransport returning a BenchmarkTransport.
struct BenchmarkTransport {
OrphanablePtr<ClientTransport> client;
OrphanablePtr<ServerTransport> server;
};
template <class Traits>
class TransportFixture {
public:
TransportFixture() { transport_.server->SetCallDestination(acceptor_); };
BenchmarkCall MakeCall() {
auto arena = arena_allocator_->MakeArena();
arena->SetContext<grpc_event_engine::experimental::EventEngine>(
event_engine_.get());
auto p =
MakeCallPair(traits_.MakeClientInitialMetadata(), std::move(arena));
transport_.client->StartCall(p.handler.StartCall());
auto handler = acceptor_->TakeHandler();
absl::optional<CallHandler> started_handler;
Notification started;
handler.SpawnInfallible("handler_setup", [&]() {
started_handler = handler.StartCall();
started.Notify();
return Empty{};
});
started.WaitForNotification();
CHECK(started_handler.has_value());
return {std::move(p.initiator), std::move(*started_handler)};
}
ServerMetadataHandle MakeServerInitialMetadata() {
return traits_.MakeServerInitialMetadata();
}
MessageHandle MakePayload() { return traits_.MakePayload(); }
ServerMetadataHandle MakeServerTrailingMetadata() {
return traits_.MakeServerTrailingMetadata();
}
private:
class Acceptor : public UnstartedCallDestination {
public:
void StartCall(UnstartedCallHandler handler) override {
MutexLock lock(&mu_);
handler_ = std::move(handler);
}
void Orphaned() override {}
UnstartedCallHandler TakeHandler() {
mu_.LockWhen(absl::Condition(
+[](Acceptor* dest) ABSL_EXCLUSIVE_LOCKS_REQUIRED(dest->mu_) {
return dest->handler_.has_value();
},
this));
auto h = std::move(*handler_);
handler_.reset();
mu_.Unlock();
return h;
}
absl::Mutex mu_;
absl::optional<UnstartedCallHandler> handler_ ABSL_GUARDED_BY(mu_);
};
Traits traits_;
std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine_ =
grpc_event_engine::experimental::GetDefaultEventEngine();
RefCountedPtr<CallArenaAllocator> arena_allocator_ =
MakeRefCounted<CallArenaAllocator>(
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
"test-allocator"),
1024);
RefCountedPtr<Acceptor> acceptor_ = MakeRefCounted<Acceptor>();
BenchmarkTransport transport_ = traits_.MakeTransport();
};
} // namespace grpc_core
// Declare all relevant benchmarks for a given fixture

@ -94,7 +94,6 @@ TEST(UsefulTest, RoundUpToPowerOf2) {
}
TEST(UsefulTest, CountTrailingZeros32) {
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(0)), 32);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(1)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(2)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(3)), 0);
@ -118,7 +117,6 @@ TEST(UsefulTest, CountTrailingZeros32) {
}
TEST(UsefulTest, CountTrailingZeros64) {
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(0)), 64);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(1)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(2)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(3)), 0);

File diff suppressed because it is too large Load Diff

@ -456,7 +456,7 @@ class ExperimentsCompiler(object):
)
print(
"inline bool Is%sEnabled() { return"
" Is%sExperimentEnabled(kExperimentId%s); }"
" Is%sExperimentEnabled<kExperimentId%s>(); }"
% (
SnakeToPascal(exp.name),
"Test" if mode == "test" else "",

@ -1,4 +1,5 @@
include _parallel_compile_patch.py
include _spawn_patch.py
include grpc_version.py
include protoc_deps.py
include protoc_lib_deps.py

@ -0,0 +1,64 @@
# Copyright 2016 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.
"""Patches the spawn() command for windows compilers.
Windows has an 8191 character command line limit, but some compilers
support an @command_file directive where command_file is a file
containing the full command line.
"""
from distutils import ccompiler
import os
import os.path
import shutil
import sys
import tempfile
MAX_COMMAND_LENGTH = 8191
_classic_spawn = ccompiler.CCompiler.spawn
def _commandfile_spawn(self, command, **kwargs):
command_length = sum([len(arg) for arg in command])
if os.name == "nt" and command_length > MAX_COMMAND_LENGTH:
# Even if this command doesn't support the @command_file, it will
# fail as is so we try blindly
print("Command line length exceeded, using command file")
print(" ".join(command))
temporary_directory = tempfile.mkdtemp()
command_filename = os.path.abspath(
os.path.join(temporary_directory, "command")
)
with open(command_filename, "w") as command_file:
escaped_args = [
'"' + arg.replace("\\", "\\\\") + '"' for arg in command[1:]
]
# add each arg on a separate line to avoid hitting the
# "line in command file contains 131071 or more characters" error
# (can happen for extra long link commands)
command_file.write(" \n".join(escaped_args))
modified_command = command[:1] + ["@{}".format(command_filename)]
try:
_classic_spawn(self, modified_command, **kwargs)
finally:
shutil.rmtree(temporary_directory)
else:
_classic_spawn(self, command, **kwargs)
def monkeypatch_spawn():
"""Monkeypatching is dumb, but it's either that or we become maintainers of
something much, much bigger."""
ccompiler.CCompiler.spawn = _commandfile_spawn

@ -37,6 +37,7 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.abspath("."))
import _parallel_compile_patch
import _spawn_patch
import protoc_lib_deps
import grpc_version
@ -48,6 +49,7 @@ else:
_EXT_INIT_SYMBOL = "PyInit__protoc_compiler"
_parallel_compile_patch.monkeypatch_compile_maybe()
_spawn_patch.monkeypatch_spawn()
CLASSIFIERS = [
"Development Status :: 5 - Production/Stable",

@ -23,6 +23,28 @@
],
"uses_polling": false
},
{
"args": [
"--benchmark_min_time=0.001s"
],
"benchmark": true,
"ci_platforms": [
"linux",
"posix"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "bm_chaotic_good",
"platforms": [
"linux",
"posix"
],
"uses_polling": false
},
{
"args": [
"--benchmark_min_time=0.001s"
@ -111,6 +133,28 @@
],
"uses_polling": false
},
{
"args": [
"--benchmark_min_time=0.001s"
],
"benchmark": true,
"ci_platforms": [
"linux",
"posix"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "bm_inproc",
"platforms": [
"linux",
"posix"
],
"uses_polling": false
},
{
"args": [
"--benchmark_min_time=0.001s"

@ -76,7 +76,6 @@ DEPRECATED_FUNCTION_TEMP_ALLOW_LIST = {
"./src/core/ext/transport/chaotic_good/server_transport.cc",
"./src/core/ext/transport/chttp2/client/chttp2_connector.cc",
"./src/core/ext/transport/chttp2/transport/bin_decoder.cc",
"./src/core/ext/transport/chttp2/transport/chttp2_transport.cc",
"./src/core/ext/transport/chttp2/transport/flow_control.cc",
"./src/core/ext/transport/chttp2/transport/frame_ping.cc",
"./src/core/ext/transport/chttp2/transport/frame_rst_stream.cc",
@ -123,8 +122,6 @@ DEPRECATED_FUNCTION_TEMP_ALLOW_LIST = {
"./src/core/lib/iomgr/socket_utils_common_posix.cc",
"./src/core/lib/iomgr/tcp_client_cfstream.cc",
"./src/core/lib/iomgr/tcp_client_posix.cc",
"./src/core/lib/iomgr/tcp_posix.cc",
"./src/core/lib/iomgr/tcp_server_posix.cc",
"./src/core/lib/iomgr/tcp_windows.cc",
"./src/core/lib/iomgr/timer_generic.cc",
"./src/core/lib/iomgr/timer_manager.cc",
@ -165,18 +162,6 @@ DEPRECATED_FUNCTION_TEMP_ALLOW_LIST = {
"./src/core/resolver/xds/xds_resolver.cc",
"./src/core/server/server.cc",
"./src/core/server/xds_server_config_fetcher.cc",
"./src/core/tsi/alts/frame_protector/frame_handler.cc",
"./src/core/tsi/alts/handshaker/alts_handshaker_client.cc",
"./src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc",
"./src/core/tsi/alts/handshaker/transport_security_common_api.cc",
"./src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc",
"./src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc",
"./src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc",
"./src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc",
"./src/core/tsi/fake_transport_security.cc",
"./src/core/tsi/ssl/key_logging/ssl_key_logging.cc",
"./src/core/tsi/ssl_transport_security.cc",
"./src/core/tsi/ssl_transport_security_utils.cc",
"./src/core/util/android/log.cc",
"./src/core/util/linux/log.cc",
"./src/core/util/posix/log.cc",

Loading…
Cancel
Save