Reapply "[experiments] Explicit requirement check" (#34911) (#34915)

This reverts commit b0e0659bab.

Closes #34915

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/34915 from ctiller:requires2 8e4f033317
PiperOrigin-RevId: 583110606
pull/34974/head
Craig Tiller 1 year ago committed by Copybara-Service
parent b644164988
commit 399fded213
  1. 51
      bazel/experiments.bzl
  2. 7
      bazel/grpc_build_system.bzl
  3. 7
      bazel/test_experiments.bzl
  4. 13
      src/core/lib/experiments/config.cc
  5. 3
      src/core/lib/experiments/config.h
  6. 449
      src/core/lib/experiments/experiments.cc
  7. 66
      src/core/lib/experiments/experiments.h
  8. 8
      src/core/lib/experiments/experiments.yaml
  9. 4
      src/core/lib/experiments/rollouts.yaml
  10. 29
      test/core/experiments/fixtures/experiments.cc
  11. 72
      tools/codegen/core/experiments_compiler.py

@ -16,6 +16,57 @@
"""Dictionary of tags to experiments so we know when to test different experiments."""
EXPERIMENT_ENABLES = {
"block_excessive_requests_before_settings_ack": "block_excessive_requests_before_settings_ack",
"call_status_override_on_cancellation": "call_status_override_on_cancellation",
"canary_client_privacy": "canary_client_privacy",
"client_idleness": "client_idleness",
"client_privacy": "client_privacy",
"combiner_offload_to_event_engine": "combiner_offload_to_event_engine",
"chttp2_batch_requests": "chttp2_batch_requests,combiner_offload_to_event_engine",
"chttp2_offload_on_rst_stream": "chttp2_offload_on_rst_stream,combiner_offload_to_event_engine",
"event_engine_client": "event_engine_client",
"event_engine_dns": "event_engine_dns",
"event_engine_listener": "event_engine_listener",
"free_large_allocator": "free_large_allocator",
"http2_stats_fix": "http2_stats_fix",
"keepalive_fix": "keepalive_fix",
"keepalive_server_fix": "keepalive_server_fix",
"lazier_stream_updates": "lazier_stream_updates",
"memory_pressure_controller": "memory_pressure_controller",
"monitoring_experiment": "monitoring_experiment",
"multiping": "multiping",
"overload_protection": "overload_protection",
"peer_state_based_framing": "peer_state_based_framing",
"pending_queue_cap": "pending_queue_cap",
"pick_first_happy_eyeballs": "pick_first_happy_eyeballs",
"ping_on_rst_stream": "ping_on_rst_stream",
"promise_based_client_call": "promise_based_client_call",
"promise_based_inproc_transport": "promise_based_inproc_transport",
"promise_based_server_call": "lazier_stream_updates,promise_based_server_call",
"red_max_concurrent_streams": "red_max_concurrent_streams",
"registered_method_lookup_in_transport": "registered_method_lookup_in_transport",
"registered_methods_map": "registered_methods_map",
"rfc_max_concurrent_streams": "rfc_max_concurrent_streams",
"round_robin_delegate_to_pick_first": "round_robin_delegate_to_pick_first",
"rstpit": "rstpit",
"schedule_cancellation_over_write": "schedule_cancellation_over_write",
"separate_ping_from_keepalive": "separate_ping_from_keepalive",
"server_privacy": "server_privacy",
"settings_timeout": "settings_timeout",
"tarpit": "tarpit",
"tcp_frame_size_tuning": "tcp_frame_size_tuning",
"tcp_rcv_lowat": "tcp_rcv_lowat",
"trace_record_callops": "trace_record_callops",
"unconstrained_max_quota_buffer_size": "unconstrained_max_quota_buffer_size",
"uniquely_unowned": "uniquely_unowned",
"work_serializer_clears_time_cache": "work_serializer_clears_time_cache",
"work_serializer_dispatch": "work_serializer_dispatch",
"write_size_policy": "write_size_policy",
"write_size_cap": "write_size_cap,write_size_policy",
"wrr_delegate_to_pick_first": "wrr_delegate_to_pick_first",
}
EXPERIMENTS = {
"windows": {
"dbg": {

@ -29,8 +29,8 @@ Contains macros used throughout the repo.
load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS")
load("//bazel:experiments.bzl", "EXPERIMENTS")
load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS")
load("//bazel:experiments.bzl", "EXPERIMENTS", "EXPERIMENT_ENABLES")
load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS", "TEST_EXPERIMENT_ENABLES")
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load("@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl", "ios_test_runner")
load("@com_google_protobuf//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
@ -418,6 +418,7 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
return tags
experiment_config = list(poller_config)
experiment_enables = {k: v for k, v in EXPERIMENT_ENABLES.items() + TEST_EXPERIMENT_ENABLES.items()}
for mode, config in mode_config.items():
enabled_tags, disabled_tags = config
if enabled_tags != None:
@ -426,7 +427,7 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
config = dict(config)
config["name"] = config["name"] + "@experiment=" + experiment
env = dict(config["env"])
env["GRPC_EXPERIMENTS"] = experiment
env["GRPC_EXPERIMENTS"] = experiment_enables[experiment]
env["GRPC_CI_EXPERIMENTS"] = "1"
config["env"] = env
tags = config["tags"] + ["experiment_variation"]

@ -16,6 +16,13 @@
"""Dictionary of tags to experiments so we know when to test different experiments."""
TEST_EXPERIMENT_ENABLES = {
"test_experiment_1": "test_experiment_1",
"test_experiment_2": "test_experiment_2",
"test_experiment_3": "test_experiment_3",
"test_experiment_4": "test_experiment_4",
}
TEST_EXPERIMENTS = {
"windows": {
"dbg": {

@ -135,6 +135,19 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariable() {
std::string(experiment).c_str());
}
}
for (size_t i = 0; i < kNumExperiments; i++) {
// If required experiments are not enabled, disable this one too.
for (size_t j = 0; j < g_experiment_metadata[i].num_required_experiments;
j++) {
// Require that we can check dependent requirements with a linear sweep
// (implies the experiments generator must DAG sort the experiments)
GPR_ASSERT(g_experiment_metadata[i].required_experiments[j] < i);
if (!experiments
.enabled[g_experiment_metadata[i].required_experiments[j]]) {
experiments.enabled[i] = false;
}
}
}
return experiments;
}

@ -18,6 +18,7 @@
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include <stdint.h>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
@ -30,6 +31,8 @@ struct ExperimentMetadata {
const char* name;
const char* description;
const char* additional_constaints;
const uint8_t* required_experiments;
uint8_t num_required_experiments;
bool default_value;
bool allow_in_fuzzing_config;
};

@ -18,6 +18,8 @@
#include "src/core/lib/experiments/experiments.h"
#include <stdint.h>
#ifndef GRPC_EXPERIMENTS_ARE_FINAL
#if defined(GRPC_CFSTREAM)
@ -34,13 +36,6 @@ const char* const additional_constraints_call_status_override_on_cancellation =
const char* const description_canary_client_privacy =
"If set, canary client privacy";
const char* const additional_constraints_canary_client_privacy = "{}";
const char* const description_chttp2_batch_requests =
"Cap the number of requests received by one transport read prior to "
"offload.";
const char* const additional_constraints_chttp2_batch_requests = "{}";
const char* const description_chttp2_offload_on_rst_stream =
"Offload work on RST_STREAM.";
const char* const additional_constraints_chttp2_offload_on_rst_stream = "{}";
const char* const description_client_idleness =
"If enabled, client channel idleness is enabled by default.";
const char* const additional_constraints_client_idleness = "{}";
@ -50,6 +45,17 @@ const char* const description_combiner_offload_to_event_engine =
"Offload Combiner work onto the EventEngine instead of the Executor.";
const char* const additional_constraints_combiner_offload_to_event_engine =
"{}";
const char* const description_chttp2_batch_requests =
"Cap the number of requests received by one transport read prior to "
"offload.";
const char* const additional_constraints_chttp2_batch_requests = "{}";
const uint8_t required_experiments_chttp2_batch_requests[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdCombinerOffloadToEventEngine)};
const char* const description_chttp2_offload_on_rst_stream =
"Offload work on RST_STREAM.";
const char* const additional_constraints_chttp2_offload_on_rst_stream = "{}";
const uint8_t required_experiments_chttp2_offload_on_rst_stream[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdCombinerOffloadToEventEngine)};
const char* const description_event_engine_client =
"Use EventEngine clients instead of iomgr's grpc_tcp_client";
const char* const additional_constraints_event_engine_client = "{}";
@ -121,6 +127,8 @@ const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const uint8_t required_experiments_promise_based_server_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdLazierStreamUpdates)};
const char* const description_red_max_concurrent_streams =
"Perform random early rejection of requests that would exceed a newly "
"reduced MAX_CONCURRENT_STREAMS but are allowed by the current.";
@ -193,12 +201,14 @@ 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 char* const description_write_size_cap =
"Limit outgoing writes proportional to the target write size";
const char* const additional_constraints_write_size_cap = "{}";
const char* const description_write_size_policy =
"Try to size writes such that they don't create too large of a backlog";
const char* const additional_constraints_write_size_policy = "{}";
const char* const description_write_size_cap =
"Limit outgoing writes proportional to the target write size";
const char* const additional_constraints_write_size_cap = "{}";
const uint8_t required_experiments_write_size_cap[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdWriteSizePolicy)};
const char* const description_wrr_delegate_to_pick_first =
"Change WRR code to delegate to pick_first as per dualstack backend "
"design.";
@ -215,109 +225,126 @@ namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"block_excessive_requests_before_settings_ack",
description_block_excessive_requests_before_settings_ack,
additional_constraints_block_excessive_requests_before_settings_ack, true,
true},
additional_constraints_block_excessive_requests_before_settings_ack,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
kDefaultForDebugOnly, true},
{"canary_client_privacy", description_canary_client_privacy,
additional_constraints_canary_client_privacy, false, false},
{"chttp2_batch_requests", description_chttp2_batch_requests,
additional_constraints_chttp2_batch_requests, true, true},
{"chttp2_offload_on_rst_stream", description_chttp2_offload_on_rst_stream,
additional_constraints_chttp2_offload_on_rst_stream, true, true},
additional_constraints_canary_client_privacy, nullptr, 0, false, false},
{"client_idleness", description_client_idleness,
additional_constraints_client_idleness, true, true},
additional_constraints_client_idleness, nullptr, 0, true, true},
{"client_privacy", description_client_privacy,
additional_constraints_client_privacy, false, false},
additional_constraints_client_privacy, nullptr, 0, false, false},
{"combiner_offload_to_event_engine",
description_combiner_offload_to_event_engine,
additional_constraints_combiner_offload_to_event_engine, true, true},
additional_constraints_combiner_offload_to_event_engine, nullptr, 0, true,
true},
{"chttp2_batch_requests", description_chttp2_batch_requests,
additional_constraints_chttp2_batch_requests,
required_experiments_chttp2_batch_requests, 1, true, true},
{"chttp2_offload_on_rst_stream", description_chttp2_offload_on_rst_stream,
additional_constraints_chttp2_offload_on_rst_stream,
required_experiments_chttp2_offload_on_rst_stream, 1, true, true},
{"event_engine_client", description_event_engine_client,
additional_constraints_event_engine_client, false, true},
additional_constraints_event_engine_client, nullptr, 0, false, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, false, false},
additional_constraints_event_engine_dns, nullptr, 0, false, false},
{"event_engine_listener", description_event_engine_listener,
additional_constraints_event_engine_listener, false, true},
additional_constraints_event_engine_listener, nullptr, 0, false, true},
{"free_large_allocator", description_free_large_allocator,
additional_constraints_free_large_allocator, false, true},
additional_constraints_free_large_allocator, nullptr, 0, false, true},
{"http2_stats_fix", description_http2_stats_fix,
additional_constraints_http2_stats_fix, true, true},
additional_constraints_http2_stats_fix, nullptr, 0, true, true},
{"keepalive_fix", description_keepalive_fix,
additional_constraints_keepalive_fix, false, false},
additional_constraints_keepalive_fix, nullptr, 0, false, false},
{"keepalive_server_fix", description_keepalive_server_fix,
additional_constraints_keepalive_server_fix, false, false},
additional_constraints_keepalive_server_fix, nullptr, 0, false, false},
{"lazier_stream_updates", description_lazier_stream_updates,
additional_constraints_lazier_stream_updates, true, true},
additional_constraints_lazier_stream_updates, nullptr, 0, true, true},
{"memory_pressure_controller", description_memory_pressure_controller,
additional_constraints_memory_pressure_controller, false, true},
additional_constraints_memory_pressure_controller, nullptr, 0, false,
true},
{"monitoring_experiment", description_monitoring_experiment,
additional_constraints_monitoring_experiment, true, true},
additional_constraints_monitoring_experiment, nullptr, 0, true, true},
{"multiping", description_multiping, additional_constraints_multiping,
false, true},
nullptr, 0, false, true},
{"overload_protection", description_overload_protection,
additional_constraints_overload_protection, true, true},
additional_constraints_overload_protection, nullptr, 0, true, true},
{"peer_state_based_framing", description_peer_state_based_framing,
additional_constraints_peer_state_based_framing, false, true},
additional_constraints_peer_state_based_framing, nullptr, 0, false, true},
{"pending_queue_cap", description_pending_queue_cap,
additional_constraints_pending_queue_cap, true, true},
additional_constraints_pending_queue_cap, nullptr, 0, true, true},
{"pick_first_happy_eyeballs", description_pick_first_happy_eyeballs,
additional_constraints_pick_first_happy_eyeballs, true, true},
additional_constraints_pick_first_happy_eyeballs, nullptr, 0, true, true},
{"ping_on_rst_stream", description_ping_on_rst_stream,
additional_constraints_ping_on_rst_stream, true, true},
additional_constraints_ping_on_rst_stream, nullptr, 0, true, true},
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call, false, true},
additional_constraints_promise_based_client_call, nullptr, 0, false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport, false, false},
additional_constraints_promise_based_inproc_transport, nullptr, 0, false,
false},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, false, true},
additional_constraints_promise_based_server_call,
required_experiments_promise_based_server_call, 1, false, true},
{"red_max_concurrent_streams", description_red_max_concurrent_streams,
additional_constraints_red_max_concurrent_streams, false, true},
additional_constraints_red_max_concurrent_streams, nullptr, 0, false,
true},
{"registered_method_lookup_in_transport",
description_registered_method_lookup_in_transport,
additional_constraints_registered_method_lookup_in_transport, true, true},
additional_constraints_registered_method_lookup_in_transport, nullptr, 0,
true, true},
{"registered_methods_map", description_registered_methods_map,
additional_constraints_registered_methods_map, false, true},
additional_constraints_registered_methods_map, nullptr, 0, false, true},
{"rfc_max_concurrent_streams", description_rfc_max_concurrent_streams,
additional_constraints_rfc_max_concurrent_streams, false, true},
additional_constraints_rfc_max_concurrent_streams, nullptr, 0, false,
true},
{"round_robin_delegate_to_pick_first",
description_round_robin_delegate_to_pick_first,
additional_constraints_round_robin_delegate_to_pick_first, true, true},
{"rstpit", description_rstpit, additional_constraints_rstpit, false, true},
additional_constraints_round_robin_delegate_to_pick_first, nullptr, 0,
true, true},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
description_schedule_cancellation_over_write,
additional_constraints_schedule_cancellation_over_write, false, true},
additional_constraints_schedule_cancellation_over_write, nullptr, 0, false,
true},
{"separate_ping_from_keepalive", description_separate_ping_from_keepalive,
additional_constraints_separate_ping_from_keepalive, true, true},
additional_constraints_separate_ping_from_keepalive, nullptr, 0, true,
true},
{"server_privacy", description_server_privacy,
additional_constraints_server_privacy, false, false},
additional_constraints_server_privacy, nullptr, 0, false, false},
{"settings_timeout", description_settings_timeout,
additional_constraints_settings_timeout, true, true},
{"tarpit", description_tarpit, additional_constraints_tarpit, true, true},
additional_constraints_settings_timeout, nullptr, 0, true, true},
{"tarpit", description_tarpit, additional_constraints_tarpit, nullptr, 0,
true, true},
{"tcp_frame_size_tuning", description_tcp_frame_size_tuning,
additional_constraints_tcp_frame_size_tuning, false, true},
additional_constraints_tcp_frame_size_tuning, nullptr, 0, false, true},
{"tcp_rcv_lowat", description_tcp_rcv_lowat,
additional_constraints_tcp_rcv_lowat, false, true},
additional_constraints_tcp_rcv_lowat, nullptr, 0, false, true},
{"trace_record_callops", description_trace_record_callops,
additional_constraints_trace_record_callops, false, true},
additional_constraints_trace_record_callops, nullptr, 0, false, true},
{"unconstrained_max_quota_buffer_size",
description_unconstrained_max_quota_buffer_size,
additional_constraints_unconstrained_max_quota_buffer_size, false, true},
additional_constraints_unconstrained_max_quota_buffer_size, nullptr, 0,
false, true},
{"uniquely_unowned", description_uniquely_unowned,
additional_constraints_uniquely_unowned, true, true},
additional_constraints_uniquely_unowned, nullptr, 0, true, true},
{"work_serializer_clears_time_cache",
description_work_serializer_clears_time_cache,
additional_constraints_work_serializer_clears_time_cache, true, true},
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
true},
{"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch, false, true},
{"write_size_cap", description_write_size_cap,
additional_constraints_write_size_cap, true, true},
additional_constraints_work_serializer_dispatch, nullptr, 0, false, true},
{"write_size_policy", description_write_size_policy,
additional_constraints_write_size_policy, true, true},
additional_constraints_write_size_policy, nullptr, 0, true, true},
{"write_size_cap", description_write_size_cap,
additional_constraints_write_size_cap, required_experiments_write_size_cap,
1, true, true},
{"wrr_delegate_to_pick_first", description_wrr_delegate_to_pick_first,
additional_constraints_wrr_delegate_to_pick_first, true, true},
additional_constraints_wrr_delegate_to_pick_first, nullptr, 0, true, true},
};
} // namespace grpc_core
@ -336,13 +363,6 @@ const char* const additional_constraints_call_status_override_on_cancellation =
const char* const description_canary_client_privacy =
"If set, canary client privacy";
const char* const additional_constraints_canary_client_privacy = "{}";
const char* const description_chttp2_batch_requests =
"Cap the number of requests received by one transport read prior to "
"offload.";
const char* const additional_constraints_chttp2_batch_requests = "{}";
const char* const description_chttp2_offload_on_rst_stream =
"Offload work on RST_STREAM.";
const char* const additional_constraints_chttp2_offload_on_rst_stream = "{}";
const char* const description_client_idleness =
"If enabled, client channel idleness is enabled by default.";
const char* const additional_constraints_client_idleness = "{}";
@ -352,6 +372,17 @@ const char* const description_combiner_offload_to_event_engine =
"Offload Combiner work onto the EventEngine instead of the Executor.";
const char* const additional_constraints_combiner_offload_to_event_engine =
"{}";
const char* const description_chttp2_batch_requests =
"Cap the number of requests received by one transport read prior to "
"offload.";
const char* const additional_constraints_chttp2_batch_requests = "{}";
const uint8_t required_experiments_chttp2_batch_requests[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdCombinerOffloadToEventEngine)};
const char* const description_chttp2_offload_on_rst_stream =
"Offload work on RST_STREAM.";
const char* const additional_constraints_chttp2_offload_on_rst_stream = "{}";
const uint8_t required_experiments_chttp2_offload_on_rst_stream[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdCombinerOffloadToEventEngine)};
const char* const description_event_engine_client =
"Use EventEngine clients instead of iomgr's grpc_tcp_client";
const char* const additional_constraints_event_engine_client = "{}";
@ -423,6 +454,8 @@ const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const uint8_t required_experiments_promise_based_server_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdLazierStreamUpdates)};
const char* const description_red_max_concurrent_streams =
"Perform random early rejection of requests that would exceed a newly "
"reduced MAX_CONCURRENT_STREAMS but are allowed by the current.";
@ -495,12 +528,14 @@ 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 char* const description_write_size_cap =
"Limit outgoing writes proportional to the target write size";
const char* const additional_constraints_write_size_cap = "{}";
const char* const description_write_size_policy =
"Try to size writes such that they don't create too large of a backlog";
const char* const additional_constraints_write_size_policy = "{}";
const char* const description_write_size_cap =
"Limit outgoing writes proportional to the target write size";
const char* const additional_constraints_write_size_cap = "{}";
const uint8_t required_experiments_write_size_cap[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdWriteSizePolicy)};
const char* const description_wrr_delegate_to_pick_first =
"Change WRR code to delegate to pick_first as per dualstack backend "
"design.";
@ -517,109 +552,126 @@ namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"block_excessive_requests_before_settings_ack",
description_block_excessive_requests_before_settings_ack,
additional_constraints_block_excessive_requests_before_settings_ack, true,
true},
additional_constraints_block_excessive_requests_before_settings_ack,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
kDefaultForDebugOnly, true},
{"canary_client_privacy", description_canary_client_privacy,
additional_constraints_canary_client_privacy, false, false},
{"chttp2_batch_requests", description_chttp2_batch_requests,
additional_constraints_chttp2_batch_requests, true, true},
{"chttp2_offload_on_rst_stream", description_chttp2_offload_on_rst_stream,
additional_constraints_chttp2_offload_on_rst_stream, true, true},
additional_constraints_canary_client_privacy, nullptr, 0, false, false},
{"client_idleness", description_client_idleness,
additional_constraints_client_idleness, true, true},
additional_constraints_client_idleness, nullptr, 0, true, true},
{"client_privacy", description_client_privacy,
additional_constraints_client_privacy, false, false},
additional_constraints_client_privacy, nullptr, 0, false, false},
{"combiner_offload_to_event_engine",
description_combiner_offload_to_event_engine,
additional_constraints_combiner_offload_to_event_engine, true, true},
additional_constraints_combiner_offload_to_event_engine, nullptr, 0, true,
true},
{"chttp2_batch_requests", description_chttp2_batch_requests,
additional_constraints_chttp2_batch_requests,
required_experiments_chttp2_batch_requests, 1, true, true},
{"chttp2_offload_on_rst_stream", description_chttp2_offload_on_rst_stream,
additional_constraints_chttp2_offload_on_rst_stream,
required_experiments_chttp2_offload_on_rst_stream, 1, true, true},
{"event_engine_client", description_event_engine_client,
additional_constraints_event_engine_client, false, true},
additional_constraints_event_engine_client, nullptr, 0, false, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, false, false},
additional_constraints_event_engine_dns, nullptr, 0, false, false},
{"event_engine_listener", description_event_engine_listener,
additional_constraints_event_engine_listener, true, true},
additional_constraints_event_engine_listener, nullptr, 0, true, true},
{"free_large_allocator", description_free_large_allocator,
additional_constraints_free_large_allocator, false, true},
additional_constraints_free_large_allocator, nullptr, 0, false, true},
{"http2_stats_fix", description_http2_stats_fix,
additional_constraints_http2_stats_fix, true, true},
additional_constraints_http2_stats_fix, nullptr, 0, true, true},
{"keepalive_fix", description_keepalive_fix,
additional_constraints_keepalive_fix, false, false},
additional_constraints_keepalive_fix, nullptr, 0, false, false},
{"keepalive_server_fix", description_keepalive_server_fix,
additional_constraints_keepalive_server_fix, false, false},
additional_constraints_keepalive_server_fix, nullptr, 0, false, false},
{"lazier_stream_updates", description_lazier_stream_updates,
additional_constraints_lazier_stream_updates, true, true},
additional_constraints_lazier_stream_updates, nullptr, 0, true, true},
{"memory_pressure_controller", description_memory_pressure_controller,
additional_constraints_memory_pressure_controller, false, true},
additional_constraints_memory_pressure_controller, nullptr, 0, false,
true},
{"monitoring_experiment", description_monitoring_experiment,
additional_constraints_monitoring_experiment, true, true},
additional_constraints_monitoring_experiment, nullptr, 0, true, true},
{"multiping", description_multiping, additional_constraints_multiping,
false, true},
nullptr, 0, false, true},
{"overload_protection", description_overload_protection,
additional_constraints_overload_protection, true, true},
additional_constraints_overload_protection, nullptr, 0, true, true},
{"peer_state_based_framing", description_peer_state_based_framing,
additional_constraints_peer_state_based_framing, false, true},
additional_constraints_peer_state_based_framing, nullptr, 0, false, true},
{"pending_queue_cap", description_pending_queue_cap,
additional_constraints_pending_queue_cap, true, true},
additional_constraints_pending_queue_cap, nullptr, 0, true, true},
{"pick_first_happy_eyeballs", description_pick_first_happy_eyeballs,
additional_constraints_pick_first_happy_eyeballs, true, true},
additional_constraints_pick_first_happy_eyeballs, nullptr, 0, true, true},
{"ping_on_rst_stream", description_ping_on_rst_stream,
additional_constraints_ping_on_rst_stream, true, true},
additional_constraints_ping_on_rst_stream, nullptr, 0, true, true},
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call, false, true},
additional_constraints_promise_based_client_call, nullptr, 0, false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport, false, false},
additional_constraints_promise_based_inproc_transport, nullptr, 0, false,
false},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, false, true},
additional_constraints_promise_based_server_call,
required_experiments_promise_based_server_call, 1, false, true},
{"red_max_concurrent_streams", description_red_max_concurrent_streams,
additional_constraints_red_max_concurrent_streams, false, true},
additional_constraints_red_max_concurrent_streams, nullptr, 0, false,
true},
{"registered_method_lookup_in_transport",
description_registered_method_lookup_in_transport,
additional_constraints_registered_method_lookup_in_transport, true, true},
additional_constraints_registered_method_lookup_in_transport, nullptr, 0,
true, true},
{"registered_methods_map", description_registered_methods_map,
additional_constraints_registered_methods_map, false, true},
additional_constraints_registered_methods_map, nullptr, 0, false, true},
{"rfc_max_concurrent_streams", description_rfc_max_concurrent_streams,
additional_constraints_rfc_max_concurrent_streams, false, true},
additional_constraints_rfc_max_concurrent_streams, nullptr, 0, false,
true},
{"round_robin_delegate_to_pick_first",
description_round_robin_delegate_to_pick_first,
additional_constraints_round_robin_delegate_to_pick_first, true, true},
{"rstpit", description_rstpit, additional_constraints_rstpit, false, true},
additional_constraints_round_robin_delegate_to_pick_first, nullptr, 0,
true, true},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
description_schedule_cancellation_over_write,
additional_constraints_schedule_cancellation_over_write, false, true},
additional_constraints_schedule_cancellation_over_write, nullptr, 0, false,
true},
{"separate_ping_from_keepalive", description_separate_ping_from_keepalive,
additional_constraints_separate_ping_from_keepalive, true, true},
additional_constraints_separate_ping_from_keepalive, nullptr, 0, true,
true},
{"server_privacy", description_server_privacy,
additional_constraints_server_privacy, false, false},
additional_constraints_server_privacy, nullptr, 0, false, false},
{"settings_timeout", description_settings_timeout,
additional_constraints_settings_timeout, true, true},
{"tarpit", description_tarpit, additional_constraints_tarpit, true, true},
additional_constraints_settings_timeout, nullptr, 0, true, true},
{"tarpit", description_tarpit, additional_constraints_tarpit, nullptr, 0,
true, true},
{"tcp_frame_size_tuning", description_tcp_frame_size_tuning,
additional_constraints_tcp_frame_size_tuning, false, true},
additional_constraints_tcp_frame_size_tuning, nullptr, 0, false, true},
{"tcp_rcv_lowat", description_tcp_rcv_lowat,
additional_constraints_tcp_rcv_lowat, false, true},
additional_constraints_tcp_rcv_lowat, nullptr, 0, false, true},
{"trace_record_callops", description_trace_record_callops,
additional_constraints_trace_record_callops, false, true},
additional_constraints_trace_record_callops, nullptr, 0, false, true},
{"unconstrained_max_quota_buffer_size",
description_unconstrained_max_quota_buffer_size,
additional_constraints_unconstrained_max_quota_buffer_size, false, true},
additional_constraints_unconstrained_max_quota_buffer_size, nullptr, 0,
false, true},
{"uniquely_unowned", description_uniquely_unowned,
additional_constraints_uniquely_unowned, true, true},
additional_constraints_uniquely_unowned, nullptr, 0, true, true},
{"work_serializer_clears_time_cache",
description_work_serializer_clears_time_cache,
additional_constraints_work_serializer_clears_time_cache, true, true},
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
true},
{"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch, false, true},
{"write_size_cap", description_write_size_cap,
additional_constraints_write_size_cap, true, true},
additional_constraints_work_serializer_dispatch, nullptr, 0, false, true},
{"write_size_policy", description_write_size_policy,
additional_constraints_write_size_policy, true, true},
additional_constraints_write_size_policy, nullptr, 0, true, true},
{"write_size_cap", description_write_size_cap,
additional_constraints_write_size_cap, required_experiments_write_size_cap,
1, true, true},
{"wrr_delegate_to_pick_first", description_wrr_delegate_to_pick_first,
additional_constraints_wrr_delegate_to_pick_first, true, true},
additional_constraints_wrr_delegate_to_pick_first, nullptr, 0, true, true},
};
} // namespace grpc_core
@ -638,13 +690,6 @@ const char* const additional_constraints_call_status_override_on_cancellation =
const char* const description_canary_client_privacy =
"If set, canary client privacy";
const char* const additional_constraints_canary_client_privacy = "{}";
const char* const description_chttp2_batch_requests =
"Cap the number of requests received by one transport read prior to "
"offload.";
const char* const additional_constraints_chttp2_batch_requests = "{}";
const char* const description_chttp2_offload_on_rst_stream =
"Offload work on RST_STREAM.";
const char* const additional_constraints_chttp2_offload_on_rst_stream = "{}";
const char* const description_client_idleness =
"If enabled, client channel idleness is enabled by default.";
const char* const additional_constraints_client_idleness = "{}";
@ -654,6 +699,17 @@ const char* const description_combiner_offload_to_event_engine =
"Offload Combiner work onto the EventEngine instead of the Executor.";
const char* const additional_constraints_combiner_offload_to_event_engine =
"{}";
const char* const description_chttp2_batch_requests =
"Cap the number of requests received by one transport read prior to "
"offload.";
const char* const additional_constraints_chttp2_batch_requests = "{}";
const uint8_t required_experiments_chttp2_batch_requests[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdCombinerOffloadToEventEngine)};
const char* const description_chttp2_offload_on_rst_stream =
"Offload work on RST_STREAM.";
const char* const additional_constraints_chttp2_offload_on_rst_stream = "{}";
const uint8_t required_experiments_chttp2_offload_on_rst_stream[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdCombinerOffloadToEventEngine)};
const char* const description_event_engine_client =
"Use EventEngine clients instead of iomgr's grpc_tcp_client";
const char* const additional_constraints_event_engine_client = "{}";
@ -725,6 +781,8 @@ const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const uint8_t required_experiments_promise_based_server_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdLazierStreamUpdates)};
const char* const description_red_max_concurrent_streams =
"Perform random early rejection of requests that would exceed a newly "
"reduced MAX_CONCURRENT_STREAMS but are allowed by the current.";
@ -797,12 +855,14 @@ 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 char* const description_write_size_cap =
"Limit outgoing writes proportional to the target write size";
const char* const additional_constraints_write_size_cap = "{}";
const char* const description_write_size_policy =
"Try to size writes such that they don't create too large of a backlog";
const char* const additional_constraints_write_size_policy = "{}";
const char* const description_write_size_cap =
"Limit outgoing writes proportional to the target write size";
const char* const additional_constraints_write_size_cap = "{}";
const uint8_t required_experiments_write_size_cap[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdWriteSizePolicy)};
const char* const description_wrr_delegate_to_pick_first =
"Change WRR code to delegate to pick_first as per dualstack backend "
"design.";
@ -819,109 +879,126 @@ namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"block_excessive_requests_before_settings_ack",
description_block_excessive_requests_before_settings_ack,
additional_constraints_block_excessive_requests_before_settings_ack, true,
true},
additional_constraints_block_excessive_requests_before_settings_ack,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
kDefaultForDebugOnly, true},
{"canary_client_privacy", description_canary_client_privacy,
additional_constraints_canary_client_privacy, false, false},
{"chttp2_batch_requests", description_chttp2_batch_requests,
additional_constraints_chttp2_batch_requests, true, true},
{"chttp2_offload_on_rst_stream", description_chttp2_offload_on_rst_stream,
additional_constraints_chttp2_offload_on_rst_stream, true, true},
additional_constraints_canary_client_privacy, nullptr, 0, false, false},
{"client_idleness", description_client_idleness,
additional_constraints_client_idleness, true, true},
additional_constraints_client_idleness, nullptr, 0, true, true},
{"client_privacy", description_client_privacy,
additional_constraints_client_privacy, false, false},
additional_constraints_client_privacy, nullptr, 0, false, false},
{"combiner_offload_to_event_engine",
description_combiner_offload_to_event_engine,
additional_constraints_combiner_offload_to_event_engine, true, true},
additional_constraints_combiner_offload_to_event_engine, nullptr, 0, true,
true},
{"chttp2_batch_requests", description_chttp2_batch_requests,
additional_constraints_chttp2_batch_requests,
required_experiments_chttp2_batch_requests, 1, true, true},
{"chttp2_offload_on_rst_stream", description_chttp2_offload_on_rst_stream,
additional_constraints_chttp2_offload_on_rst_stream,
required_experiments_chttp2_offload_on_rst_stream, 1, true, true},
{"event_engine_client", description_event_engine_client,
additional_constraints_event_engine_client, false, true},
additional_constraints_event_engine_client, nullptr, 0, false, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, false, false},
additional_constraints_event_engine_dns, nullptr, 0, false, false},
{"event_engine_listener", description_event_engine_listener,
additional_constraints_event_engine_listener, true, true},
additional_constraints_event_engine_listener, nullptr, 0, true, true},
{"free_large_allocator", description_free_large_allocator,
additional_constraints_free_large_allocator, false, true},
additional_constraints_free_large_allocator, nullptr, 0, false, true},
{"http2_stats_fix", description_http2_stats_fix,
additional_constraints_http2_stats_fix, true, true},
additional_constraints_http2_stats_fix, nullptr, 0, true, true},
{"keepalive_fix", description_keepalive_fix,
additional_constraints_keepalive_fix, false, false},
additional_constraints_keepalive_fix, nullptr, 0, false, false},
{"keepalive_server_fix", description_keepalive_server_fix,
additional_constraints_keepalive_server_fix, false, false},
additional_constraints_keepalive_server_fix, nullptr, 0, false, false},
{"lazier_stream_updates", description_lazier_stream_updates,
additional_constraints_lazier_stream_updates, true, true},
additional_constraints_lazier_stream_updates, nullptr, 0, true, true},
{"memory_pressure_controller", description_memory_pressure_controller,
additional_constraints_memory_pressure_controller, false, true},
additional_constraints_memory_pressure_controller, nullptr, 0, false,
true},
{"monitoring_experiment", description_monitoring_experiment,
additional_constraints_monitoring_experiment, true, true},
additional_constraints_monitoring_experiment, nullptr, 0, true, true},
{"multiping", description_multiping, additional_constraints_multiping,
false, true},
nullptr, 0, false, true},
{"overload_protection", description_overload_protection,
additional_constraints_overload_protection, true, true},
additional_constraints_overload_protection, nullptr, 0, true, true},
{"peer_state_based_framing", description_peer_state_based_framing,
additional_constraints_peer_state_based_framing, false, true},
additional_constraints_peer_state_based_framing, nullptr, 0, false, true},
{"pending_queue_cap", description_pending_queue_cap,
additional_constraints_pending_queue_cap, true, true},
additional_constraints_pending_queue_cap, nullptr, 0, true, true},
{"pick_first_happy_eyeballs", description_pick_first_happy_eyeballs,
additional_constraints_pick_first_happy_eyeballs, true, true},
additional_constraints_pick_first_happy_eyeballs, nullptr, 0, true, true},
{"ping_on_rst_stream", description_ping_on_rst_stream,
additional_constraints_ping_on_rst_stream, true, true},
additional_constraints_ping_on_rst_stream, nullptr, 0, true, true},
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call, false, true},
additional_constraints_promise_based_client_call, nullptr, 0, false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport, false, false},
additional_constraints_promise_based_inproc_transport, nullptr, 0, false,
false},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, false, true},
additional_constraints_promise_based_server_call,
required_experiments_promise_based_server_call, 1, false, true},
{"red_max_concurrent_streams", description_red_max_concurrent_streams,
additional_constraints_red_max_concurrent_streams, false, true},
additional_constraints_red_max_concurrent_streams, nullptr, 0, false,
true},
{"registered_method_lookup_in_transport",
description_registered_method_lookup_in_transport,
additional_constraints_registered_method_lookup_in_transport, true, true},
additional_constraints_registered_method_lookup_in_transport, nullptr, 0,
true, true},
{"registered_methods_map", description_registered_methods_map,
additional_constraints_registered_methods_map, false, true},
additional_constraints_registered_methods_map, nullptr, 0, false, true},
{"rfc_max_concurrent_streams", description_rfc_max_concurrent_streams,
additional_constraints_rfc_max_concurrent_streams, false, true},
additional_constraints_rfc_max_concurrent_streams, nullptr, 0, false,
true},
{"round_robin_delegate_to_pick_first",
description_round_robin_delegate_to_pick_first,
additional_constraints_round_robin_delegate_to_pick_first, true, true},
{"rstpit", description_rstpit, additional_constraints_rstpit, false, true},
additional_constraints_round_robin_delegate_to_pick_first, nullptr, 0,
true, true},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
description_schedule_cancellation_over_write,
additional_constraints_schedule_cancellation_over_write, false, true},
additional_constraints_schedule_cancellation_over_write, nullptr, 0, false,
true},
{"separate_ping_from_keepalive", description_separate_ping_from_keepalive,
additional_constraints_separate_ping_from_keepalive, true, true},
additional_constraints_separate_ping_from_keepalive, nullptr, 0, true,
true},
{"server_privacy", description_server_privacy,
additional_constraints_server_privacy, false, false},
additional_constraints_server_privacy, nullptr, 0, false, false},
{"settings_timeout", description_settings_timeout,
additional_constraints_settings_timeout, true, true},
{"tarpit", description_tarpit, additional_constraints_tarpit, true, true},
additional_constraints_settings_timeout, nullptr, 0, true, true},
{"tarpit", description_tarpit, additional_constraints_tarpit, nullptr, 0,
true, true},
{"tcp_frame_size_tuning", description_tcp_frame_size_tuning,
additional_constraints_tcp_frame_size_tuning, false, true},
additional_constraints_tcp_frame_size_tuning, nullptr, 0, false, true},
{"tcp_rcv_lowat", description_tcp_rcv_lowat,
additional_constraints_tcp_rcv_lowat, false, true},
additional_constraints_tcp_rcv_lowat, nullptr, 0, false, true},
{"trace_record_callops", description_trace_record_callops,
additional_constraints_trace_record_callops, false, true},
additional_constraints_trace_record_callops, nullptr, 0, false, true},
{"unconstrained_max_quota_buffer_size",
description_unconstrained_max_quota_buffer_size,
additional_constraints_unconstrained_max_quota_buffer_size, false, true},
additional_constraints_unconstrained_max_quota_buffer_size, nullptr, 0,
false, true},
{"uniquely_unowned", description_uniquely_unowned,
additional_constraints_uniquely_unowned, true, true},
additional_constraints_uniquely_unowned, nullptr, 0, true, true},
{"work_serializer_clears_time_cache",
description_work_serializer_clears_time_cache,
additional_constraints_work_serializer_clears_time_cache, true, true},
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
true},
{"work_serializer_dispatch", description_work_serializer_dispatch,
additional_constraints_work_serializer_dispatch, false, true},
{"write_size_cap", description_write_size_cap,
additional_constraints_write_size_cap, true, true},
additional_constraints_work_serializer_dispatch, nullptr, 0, false, true},
{"write_size_policy", description_write_size_policy,
additional_constraints_write_size_policy, true, true},
additional_constraints_write_size_policy, nullptr, 0, true, true},
{"write_size_cap", description_write_size_cap,
additional_constraints_write_size_cap, required_experiments_write_size_cap,
1, true, true},
{"wrr_delegate_to_pick_first", description_wrr_delegate_to_pick_first,
additional_constraints_wrr_delegate_to_pick_first, true, true},
additional_constraints_wrr_delegate_to_pick_first, nullptr, 0, true, true},
};
} // namespace grpc_core

@ -70,15 +70,15 @@ inline bool IsCallStatusOverrideOnCancellationEnabled() {
#endif
}
inline bool IsCanaryClientPrivacyEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CLIENT_IDLENESS
inline bool IsClientIdlenessEnabled() { return true; }
inline bool IsClientPrivacyEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_COMBINER_OFFLOAD_TO_EVENT_ENGINE
inline bool IsCombinerOffloadToEventEngineEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() { return true; }
inline bool IsEventEngineClientEnabled() { return false; }
inline bool IsEventEngineDnsEnabled() { return false; }
inline bool IsEventEngineListenerEnabled() { return false; }
@ -130,10 +130,10 @@ inline bool IsUniquelyUnownedEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
inline bool IsWorkSerializerDispatchEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_POLICY
inline bool IsWriteSizePolicyEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRR_DELEGATE_TO_PICK_FIRST
inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
@ -151,15 +151,15 @@ inline bool IsCallStatusOverrideOnCancellationEnabled() {
#endif
}
inline bool IsCanaryClientPrivacyEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CLIENT_IDLENESS
inline bool IsClientIdlenessEnabled() { return true; }
inline bool IsClientPrivacyEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_COMBINER_OFFLOAD_TO_EVENT_ENGINE
inline bool IsCombinerOffloadToEventEngineEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() { return true; }
inline bool IsEventEngineClientEnabled() { return false; }
inline bool IsEventEngineDnsEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
@ -212,10 +212,10 @@ inline bool IsUniquelyUnownedEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
inline bool IsWorkSerializerDispatchEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_POLICY
inline bool IsWriteSizePolicyEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRR_DELEGATE_TO_PICK_FIRST
inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
@ -233,15 +233,15 @@ inline bool IsCallStatusOverrideOnCancellationEnabled() {
#endif
}
inline bool IsCanaryClientPrivacyEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CLIENT_IDLENESS
inline bool IsClientIdlenessEnabled() { return true; }
inline bool IsClientPrivacyEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_COMBINER_OFFLOAD_TO_EVENT_ENGINE
inline bool IsCombinerOffloadToEventEngineEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() { return true; }
inline bool IsEventEngineClientEnabled() { return false; }
inline bool IsEventEngineDnsEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
@ -294,10 +294,10 @@ inline bool IsUniquelyUnownedEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
inline bool IsWorkSerializerDispatchEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_POLICY
inline bool IsWriteSizePolicyEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WRR_DELEGATE_TO_PICK_FIRST
inline bool IsWrrDelegateToPickFirstEnabled() { return true; }
#endif
@ -307,11 +307,11 @@ enum ExperimentIds {
kExperimentIdBlockExcessiveRequestsBeforeSettingsAck,
kExperimentIdCallStatusOverrideOnCancellation,
kExperimentIdCanaryClientPrivacy,
kExperimentIdChttp2BatchRequests,
kExperimentIdChttp2OffloadOnRstStream,
kExperimentIdClientIdleness,
kExperimentIdClientPrivacy,
kExperimentIdCombinerOffloadToEventEngine,
kExperimentIdChttp2BatchRequests,
kExperimentIdChttp2OffloadOnRstStream,
kExperimentIdEventEngineClient,
kExperimentIdEventEngineDns,
kExperimentIdEventEngineListener,
@ -349,8 +349,8 @@ enum ExperimentIds {
kExperimentIdUniquelyUnowned,
kExperimentIdWorkSerializerClearsTimeCache,
kExperimentIdWorkSerializerDispatch,
kExperimentIdWriteSizeCap,
kExperimentIdWriteSizePolicy,
kExperimentIdWriteSizeCap,
kExperimentIdWrrDelegateToPickFirst,
kNumExperiments
};
@ -367,14 +367,6 @@ inline bool IsCallStatusOverrideOnCancellationEnabled() {
inline bool IsCanaryClientPrivacyEnabled() {
return IsExperimentEnabled(kExperimentIdCanaryClientPrivacy);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() {
return IsExperimentEnabled(kExperimentIdChttp2BatchRequests);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() {
return IsExperimentEnabled(kExperimentIdChttp2OffloadOnRstStream);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CLIENT_IDLENESS
inline bool IsClientIdlenessEnabled() {
return IsExperimentEnabled(kExperimentIdClientIdleness);
@ -387,6 +379,14 @@ inline bool IsClientPrivacyEnabled() {
inline bool IsCombinerOffloadToEventEngineEnabled() {
return IsExperimentEnabled(kExperimentIdCombinerOffloadToEventEngine);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_BATCH_REQUESTS
inline bool IsChttp2BatchRequestsEnabled() {
return IsExperimentEnabled(kExperimentIdChttp2BatchRequests);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CHTTP2_OFFLOAD_ON_RST_STREAM
inline bool IsChttp2OffloadOnRstStreamEnabled() {
return IsExperimentEnabled(kExperimentIdChttp2OffloadOnRstStream);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_CLIENT
inline bool IsEventEngineClientEnabled() {
return IsExperimentEnabled(kExperimentIdEventEngineClient);
@ -535,14 +535,14 @@ inline bool IsWorkSerializerClearsTimeCacheEnabled() {
inline bool IsWorkSerializerDispatchEnabled() {
return IsExperimentEnabled(kExperimentIdWorkSerializerDispatch);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() {
return IsExperimentEnabled(kExperimentIdWriteSizeCap);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_POLICY
inline bool IsWriteSizePolicyEnabled() {
return IsExperimentEnabled(kExperimentIdWriteSizePolicy);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WRITE_SIZE_CAP
inline bool IsWriteSizeCapEnabled() {
return IsExperimentEnabled(kExperimentIdWriteSizeCap);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WRR_DELEGATE_TO_PICK_FIRST
inline bool IsWrrDelegateToPickFirstEnabled() {
return IsExperimentEnabled(kExperimentIdWrrDelegateToPickFirst);

@ -22,6 +22,10 @@
# allow_in_fuzzing_config: optional boolean (true if not specified)
# if false, this experiment will not be included in fuzzers that
# explore the config space
# requires: A list of names of experiments that this experiment depends on.
# Defaults to the empty list.
# If any of the experiments in the required list is determined to
# be disabled at runtime, this experiment is disabled at runtime.
#
# Well known test tags:
# core_end2end_test: all tests, fixtures in the core end2end suite
@ -59,12 +63,14 @@
expiry: 2024/03/03
owner: ctiller@google.com
test_tags: ["cpp_end2end_test", "flow_control_test"]
requires: [combiner_offload_to_event_engine]
- name: chttp2_offload_on_rst_stream
description:
Offload work on RST_STREAM.
expiry: 2024/03/03
owner: ctiller@google.com
test_tags: ["cpp_end2end_test", "flow_control_test"]
requires: [combiner_offload_to_event_engine]
- name: client_idleness
description: If enabled, client channel idleness is enabled by default.
expiry: 2023/12/15
@ -210,6 +216,7 @@
expiry: 2024/06/14
owner: ctiller@google.com
test_tags: ["core_end2end_test", "cpp_end2end_test", "xds_end2end_test", "logging_test"]
requires: [lazier_stream_updates]
- name: red_max_concurrent_streams
description:
Perform random early rejection of requests that would exceed a newly reduced
@ -331,6 +338,7 @@
expiry: 2024/03/03
owner: ctiller@google.com
test_tags: [flow_control_test]
requires: [write_size_policy]
- name: write_size_policy
description:
Try to size writes such that they don't create too large of a backlog

@ -22,6 +22,10 @@
# - debug - the experiment defaults to on in debug builds,
# off in release builds in all platforms.
# - true - the experiment defaults to on in all platforms.
# requires: A list of names of experiments that this experiment depends on.
# Defaults to the empty list.
# If any of the experiments in the required list is determined to
# be disabled at runtime, this experiment is disabled at runtime.
#
# [OR] the default can be platform specific:
# -----------------------------------------

@ -41,13 +41,14 @@ namespace grpc_core {
const ExperimentMetadata g_test_experiment_metadata[] = {
{"test_experiment_1", description_test_experiment_1,
additional_constraints_test_experiment_1, false, true},
additional_constraints_test_experiment_1, nullptr, 0, false, true},
{"test_experiment_2", description_test_experiment_2,
additional_constraints_test_experiment_2, true, true},
additional_constraints_test_experiment_2, nullptr, 0, true, true},
{"test_experiment_3", description_test_experiment_3,
additional_constraints_test_experiment_3, kDefaultForDebugOnly, true},
additional_constraints_test_experiment_3, nullptr, 0, kDefaultForDebugOnly,
true},
{"test_experiment_4", description_test_experiment_4,
additional_constraints_test_experiment_4, true, true},
additional_constraints_test_experiment_4, nullptr, 0, true, true},
};
} // namespace grpc_core
@ -73,13 +74,14 @@ namespace grpc_core {
const ExperimentMetadata g_test_experiment_metadata[] = {
{"test_experiment_1", description_test_experiment_1,
additional_constraints_test_experiment_1, false, true},
additional_constraints_test_experiment_1, nullptr, 0, false, true},
{"test_experiment_2", description_test_experiment_2,
additional_constraints_test_experiment_2, false, true},
additional_constraints_test_experiment_2, nullptr, 0, false, true},
{"test_experiment_3", description_test_experiment_3,
additional_constraints_test_experiment_3, kDefaultForDebugOnly, true},
additional_constraints_test_experiment_3, nullptr, 0, kDefaultForDebugOnly,
true},
{"test_experiment_4", description_test_experiment_4,
additional_constraints_test_experiment_4, true, true},
additional_constraints_test_experiment_4, nullptr, 0, true, true},
};
} // namespace grpc_core
@ -105,13 +107,16 @@ namespace grpc_core {
const ExperimentMetadata g_test_experiment_metadata[] = {
{"test_experiment_1", description_test_experiment_1,
additional_constraints_test_experiment_1, kDefaultForDebugOnly, true},
additional_constraints_test_experiment_1, nullptr, 0, kDefaultForDebugOnly,
true},
{"test_experiment_2", description_test_experiment_2,
additional_constraints_test_experiment_2, kDefaultForDebugOnly, true},
additional_constraints_test_experiment_2, nullptr, 0, kDefaultForDebugOnly,
true},
{"test_experiment_3", description_test_experiment_3,
additional_constraints_test_experiment_3, kDefaultForDebugOnly, true},
additional_constraints_test_experiment_3, nullptr, 0, kDefaultForDebugOnly,
true},
{"test_experiment_4", description_test_experiment_4,
additional_constraints_test_experiment_4, false, true},
additional_constraints_test_experiment_4, nullptr, 0, false, true},
};
} // namespace grpc_core

@ -198,6 +198,7 @@ class ExperimentDefinition(object):
self._default = {}
self._additional_constraints = {}
self._test_tags = []
self._requires = set()
if "allow_in_fuzzing_config" in attributes:
self._allow_in_fuzzing_config = attributes[
@ -207,6 +208,9 @@ class ExperimentDefinition(object):
if "test_tags" in attributes:
self._test_tags = attributes["test_tags"]
for requirement in attributes.get("requires", []):
self._requires.add(requirement)
def IsValid(self, check_expiry=False):
if self._error:
return False
@ -244,6 +248,8 @@ class ExperimentDefinition(object):
" experiment: %s" % self._name
)
return False
for requirement in rollout_attributes.get("requires", []):
self._requires.add(requirement)
if "default" not in rollout_attributes:
print(
"ERROR: no default for experiment %s"
@ -310,7 +316,7 @@ class ExperimentsCompiler(object):
self._final_define = final_define
self._platforms_define = platforms_define
self._bzl_list_for_defaults = bzl_list_for_defaults
self._experiment_definitions = {}
self._experiment_definitions = collections.OrderedDict()
self._experiment_rollouts = {}
def AddExperimentDefinition(self, experiment_definition):
@ -344,6 +350,27 @@ class ExperimentsCompiler(object):
self._defaults, self._platforms_define, rollout_attributes
)
def _FinalizeExperiments(self):
queue = collections.OrderedDict()
for name, exp in self._experiment_definitions.items():
queue[name] = exp._requires
done = set()
final = collections.OrderedDict()
while queue:
take = None
for name, requires in queue.items():
if requires.issubset(done):
take = name
break
if take is None:
print("ERROR: circular dependency in experiments")
return False
done.add(take)
final[take] = self._experiment_definitions[take]
del queue[take]
self._experiment_definitions = final
return True
def _GenerateExperimentsHdrForPlatform(self, platform, file_desc):
for _, exp in self._experiment_definitions.items():
define_fmt = self._final_define[exp.default(platform)]
@ -363,6 +390,7 @@ class ExperimentsCompiler(object):
)
def GenerateExperimentsHdr(self, output_file, mode):
assert self._FinalizeExperiments()
with open(output_file, "w") as H:
PutCopyright(H, "//")
PutBanner(
@ -463,6 +491,18 @@ class ExperimentsCompiler(object):
file=file_desc,
)
have_defaults.add(self._defaults[exp.default(platform)])
if exp._requires:
print(
"const uint8_t required_experiments_%s[] = {%s};"
% (
exp.name,
",".join(
f"static_cast<uint8_t>(grpc_core::kExperimentId{SnakeToPascal(name)})"
for name in sorted(exp._requires)
),
),
file=file_desc,
)
if "kDefaultForDebugOnly" in have_defaults:
print("#ifdef NDEBUG", file=file_desc)
if "kDefaultForDebugOnly" in have_defaults:
@ -487,11 +527,15 @@ class ExperimentsCompiler(object):
)
for _, exp in self._experiment_definitions.items():
print(
" {%s, description_%s, additional_constraints_%s, %s, %s},"
" {%s, description_%s, additional_constraints_%s, %s, %d, %s, %s},"
% (
ToCStr(exp.name),
exp.name,
exp.name,
f"required_experiments_{exp.name}"
if exp._requires
else "nullptr",
len(exp._requires),
self._defaults[exp.default(platform)],
"true" if exp.allow_in_fuzzing_config else "false",
),
@ -502,6 +546,7 @@ class ExperimentsCompiler(object):
print("} // namespace grpc_core", file=file_desc)
def GenerateExperimentsSrc(self, output_file, header_file_path, mode):
assert self._FinalizeExperiments()
with open(output_file, "w") as C:
PutCopyright(C, "//")
PutBanner(
@ -510,7 +555,15 @@ class ExperimentsCompiler(object):
"//",
)
any_requires = False
for _, exp in self._experiment_definitions.items():
if exp._requires:
any_requires = True
break
print("#include <grpc/support/port_platform.h>", file=C)
if any_requires:
print("#include <stdint.h>", file=C)
print(f'#include "{header_file_path}"', file=C)
print(file=C)
print("#ifndef GRPC_EXPERIMENTS_ARE_FINAL", file=C)
@ -540,6 +593,7 @@ class ExperimentsCompiler(object):
return defs
def GenTest(self, output_file):
assert self._FinalizeExperiments()
with open(output_file, "w") as C:
PutCopyright(C, "//")
PutBanner(
@ -567,6 +621,7 @@ class ExperimentsCompiler(object):
print(_EXPERIMENTS_TEST_SKELETON(defs, test_body), file=C)
def GenExperimentsBzl(self, mode, output_file):
assert self._FinalizeExperiments()
if self._bzl_list_for_defaults is None:
return
@ -610,6 +665,19 @@ class ExperimentsCompiler(object):
file=B,
)
print(file=B)
if mode == "test":
print("TEST_EXPERIMENT_ENABLES = {", file=B)
else:
print("EXPERIMENT_ENABLES = {", file=B)
for name, exp in self._experiment_definitions.items():
enables = exp._requires.copy()
enables.add(name)
print(
f" \"{name}\": \"{','.join(sorted(enables))}\",", file=B
)
print("}", file=B)
print(file=B)
if mode == "test":
print("TEST_EXPERIMENTS = {", file=B)

Loading…
Cancel
Save