From 80dbe90c18f0a7d3da65bcac3f0e2eba7b74dc9e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 13 Jun 2023 08:11:53 -0700 Subject: [PATCH] Revert "[resource quota] Fix bugs in iomgr and event engine endpoint interactions with resource quota" (#33417) Reverts grpc/grpc#33375 Breaks import --- CMakeLists.txt | 54 ------ build_autogenerated.yaml | 13 -- src/core/BUILD | 2 - .../posix_engine/posix_endpoint.cc | 33 +--- .../posix_engine/posix_endpoint.h | 2 - .../posix_engine/posix_engine_listener.cc | 58 +++---- src/core/lib/iomgr/exec_ctx.h | 11 -- src/core/lib/iomgr/tcp_posix.cc | 25 +-- test/cpp/end2end/BUILD | 18 -- .../resource_quota_end2end_stress_test.cc | 154 ------------------ tools/run_tests/generated/tests.json | 24 --- 11 files changed, 36 insertions(+), 358 deletions(-) delete mode 100644 test/cpp/end2end/resource_quota_end2end_stress_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 2701c882eee..9389676a9a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1186,7 +1186,6 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx resolve_address_using_native_resolver_posix_test) endif() add_dependencies(buildtests_cxx resolve_address_using_native_resolver_test) - add_dependencies(buildtests_cxx resource_quota_end2end_stress_test) add_dependencies(buildtests_cxx resource_quota_server_test) add_dependencies(buildtests_cxx resource_quota_test) add_dependencies(buildtests_cxx retry_cancel_after_first_attempt_starts_test) @@ -19834,59 +19833,6 @@ target_link_libraries(resolve_address_using_native_resolver_test ) -endif() -if(gRPC_BUILD_TESTS) - -add_executable(resource_quota_end2end_stress_test - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.h - test/cpp/end2end/resource_quota_end2end_stress_test.cc - third_party/googletest/googletest/src/gtest-all.cc - third_party/googletest/googlemock/src/gmock-all.cc -) -target_compile_features(resource_quota_end2end_stress_test PUBLIC cxx_std_14) -target_include_directories(resource_quota_end2end_stress_test - 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} - third_party/googletest/googletest/include - third_party/googletest/googletest - third_party/googletest/googlemock/include - third_party/googletest/googlemock - ${_gRPC_PROTO_GENS_DIR} -) - -target_link_libraries(resource_quota_end2end_stress_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_PROTOBUF_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util -) - - endif() if(gRPC_BUILD_TESTS) diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 67e5645ad78..95d5e06f1b6 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -12034,19 +12034,6 @@ targets: deps: - grpc_test_util - grpc++_test_config -- name: resource_quota_end2end_stress_test - gtest: true - build: test - language: c++ - headers: [] - src: - - src/proto/grpc/testing/echo.proto - - src/proto/grpc/testing/echo_messages.proto - - src/proto/grpc/testing/simple_messages.proto - - src/proto/grpc/testing/xds/v3/orca_load_report.proto - - test/cpp/end2end/resource_quota_end2end_stress_test.cc - deps: - - grpc++_test_util - name: resource_quota_server_test gtest: true build: test diff --git a/src/core/BUILD b/src/core/BUILD index 81753688430..85472b4dc38 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -1838,7 +1838,6 @@ grpc_cc_library( "time", "//:debug_location", "//:event_engine_base_hdrs", - "//:exec_ctx", "//:gpr", "//:grpc_public_hdrs", "//:ref_counted_ptr", @@ -1940,7 +1939,6 @@ grpc_cc_library( "socket_mutator", "status_helper", "//:event_engine_base_hdrs", - "//:exec_ctx", "//:gpr", ], ) diff --git a/src/core/lib/event_engine/posix_engine/posix_endpoint.cc b/src/core/lib/event_engine/posix_engine/posix_endpoint.cc index f42742229ef..b99dde4bc4b 100644 --- a/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +++ b/src/core/lib/event_engine/posix_engine/posix_endpoint.cc @@ -49,9 +49,7 @@ #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/status_helper.h" #include "src/core/lib/gprpp/strerror.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/time.h" -#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/resource_quota/resource_quota.h" #include "src/core/lib/slice/slice.h" @@ -551,43 +549,28 @@ void PosixEndpointImpl::MaybeMakeReadSlices() { } } -bool PosixEndpointImpl::HandleReadLocked(absl::Status& status) { +void PosixEndpointImpl::HandleRead(absl::Status status) { + read_mu_.Lock(); if (status.ok() && memory_owner_.is_valid()) { MaybeMakeReadSlices(); if (!TcpDoRead(status)) { UpdateRcvLowat(); // We've consumed the edge, request a new one. - return false; + read_mu_.Unlock(); + handle_->NotifyOnRead(on_read_); + return; } } else { - if (!memory_owner_.is_valid() && status.ok()) { - status = TcpAnnotateError(absl::UnknownError("Shutting down endpoint")); + if (!memory_owner_.is_valid()) { + status = absl::UnknownError("Shutting down endpoint"); } incoming_buffer_->Clear(); last_read_buffer_.Clear(); } - return true; -} - -void PosixEndpointImpl::HandleRead(absl::Status status) { - grpc_core::ReleasableMutexLock lock(&read_mu_); - bool ret = false; - if (grpc_core::ExecCtx::Get() == nullptr) { - grpc_core::ApplicationCallbackExecCtx app_ctx; - grpc_core::ExecCtx exec_ctx; - ret = HandleReadLocked(status); - } else { - ret = HandleReadLocked(status); - } - if (!ret) { - lock.Release(); - handle_->NotifyOnRead(on_read_); - return; - } absl::AnyInvocable cb = std::move(read_cb_); read_cb_ = nullptr; incoming_buffer_ = nullptr; - lock.Release(); + read_mu_.Unlock(); cb(status); Unref(); } diff --git a/src/core/lib/event_engine/posix_engine/posix_endpoint.h b/src/core/lib/event_engine/posix_engine/posix_endpoint.h index e10e1eec70a..8c2fae5ecf5 100644 --- a/src/core/lib/event_engine/posix_engine/posix_endpoint.h +++ b/src/core/lib/event_engine/posix_engine/posix_endpoint.h @@ -504,8 +504,6 @@ class PosixEndpointImpl : public grpc_core::RefCounted { void HandleWrite(absl::Status status); void HandleError(absl::Status status); void HandleRead(absl::Status status); - bool HandleReadLocked(absl::Status& status) - ABSL_EXCLUSIVE_LOCKS_REQUIRED(read_mu_); void MaybeMakeReadSlices() ABSL_EXCLUSIVE_LOCKS_REQUIRED(read_mu_); bool TcpDoRead(absl::Status& status) ABSL_EXCLUSIVE_LOCKS_REQUIRED(read_mu_); void FinishEstimate(); diff --git a/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc b/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc index 59facad83b5..98f7a6783e4 100644 --- a/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +++ b/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc @@ -15,7 +15,6 @@ #include #include "src/core/lib/event_engine/posix.h" -#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/port.h" #ifdef GRPC_POSIX_SOCKET_TCP @@ -25,7 +24,6 @@ #include // IWYU pragma: keep #include -#include #include #include "absl/functional/any_invocable.h" @@ -199,20 +197,15 @@ void PosixEngineListenerImpl::AsyncConnectionAcceptor::NotifyOnAccept( listener_->memory_allocator_factory_->CreateMemoryAllocator( absl::StrCat("endpoint-tcp-server-connection: ", *peer_name)), /*options=*/listener_->options_); - - grpc_core::EnsureRunInExecCtx([this, peer_name = std::move(*peer_name), - endpoint = std::move(endpoint)]() mutable { - // Call on_accept_ and then resume accepting new connections - // by continuing the parent for-loop. - listener_->on_accept_( - /*listener_fd=*/handle_->WrappedFd(), - /*endpoint=*/std::move(endpoint), - /*is_external=*/false, - /*memory_allocator=*/ - listener_->memory_allocator_factory_->CreateMemoryAllocator( - absl::StrCat("on-accept-tcp-server-connection: ", peer_name)), - /*pending_data=*/nullptr); - }); + // Call on_accept_ and then resume accepting new connections by continuing + // the parent for-loop. + listener_->on_accept_( + /*listener_fd=*/handle_->WrappedFd(), /*endpoint=*/std::move(endpoint), + /*is_external=*/false, + /*memory_allocator=*/ + listener_->memory_allocator_factory_->CreateMemoryAllocator( + absl::StrCat("on-accept-tcp-server-connection: ", *peer_name)), + /*pending_data=*/nullptr); } GPR_UNREACHABLE_CODE(return); } @@ -235,24 +228,21 @@ absl::Status PosixEngineListenerImpl::HandleExternalConnection( absl::StrCat("HandleExternalConnection: peer not connected: ", peer_name.status().ToString())); } - grpc_core::EnsureRunInExecCtx([this, peer_name = std::move(*peer_name), - pending_data, listener_fd, fd]() mutable { - auto endpoint = CreatePosixEndpoint( - /*handle=*/poller_->CreateHandle(fd, peer_name, - poller_->CanTrackErrors()), - /*on_shutdown=*/nullptr, /*engine=*/engine_, - /*allocator=*/ - memory_allocator_factory_->CreateMemoryAllocator(absl::StrCat( - "external:endpoint-tcp-server-connection: ", peer_name)), - /*options=*/options_); - on_accept_( - /*listener_fd=*/listener_fd, /*endpoint=*/std::move(endpoint), - /*is_external=*/true, - /*memory_allocator=*/ - memory_allocator_factory_->CreateMemoryAllocator(absl::StrCat( - "external:on-accept-tcp-server-connection: ", peer_name)), - /*pending_data=*/pending_data); - }); + auto endpoint = CreatePosixEndpoint( + /*handle=*/poller_->CreateHandle(fd, *peer_name, + poller_->CanTrackErrors()), + /*on_shutdown=*/nullptr, /*engine=*/engine_, + /*allocator=*/ + memory_allocator_factory_->CreateMemoryAllocator(absl::StrCat( + "external:endpoint-tcp-server-connection: ", *peer_name)), + /*options=*/options_); + on_accept_( + /*listener_fd=*/listener_fd, /*endpoint=*/std::move(endpoint), + /*is_external=*/true, + /*memory_allocator=*/ + memory_allocator_factory_->CreateMemoryAllocator(absl::StrCat( + "external:on-accept-tcp-server-connection: ", *peer_name)), + /*pending_data=*/pending_data); return absl::OkStatus(); } diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 20d9ebe04e1..230af79699d 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -329,17 +329,6 @@ class ApplicationCallbackExecCtx { static thread_local ApplicationCallbackExecCtx* callback_exec_ctx_; }; -template -void EnsureRunInExecCtx(F f) { - if (ExecCtx::Get() == nullptr) { - ApplicationCallbackExecCtx app_ctx; - ExecCtx exec_ctx; - f(); - } else { - f(); - } -} - } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_IOMGR_EXEC_CTX_H diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 4664d1a10d2..3b732122528 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -729,9 +729,6 @@ static void tcp_shutdown(grpc_endpoint* ep, grpc_error_handle why) { grpc_tcp* tcp = reinterpret_cast(ep); ZerocopyDisableAndWaitForRemaining(tcp); grpc_fd_shutdown(tcp->em_fd, why); - tcp->read_mu.Lock(); - tcp->memory_owner.Reset(); - tcp->read_mu.Unlock(); } static void tcp_free(grpc_tcp* tcp) { @@ -778,9 +775,6 @@ static void tcp_destroy(grpc_endpoint* ep) { gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } - tcp->read_mu.Lock(); - tcp->memory_owner.Reset(); - tcp->read_mu.Unlock(); TCP_UNREF(tcp, "destroy"); } @@ -801,14 +795,11 @@ static void maybe_post_reclaimer(grpc_tcp* tcp) ABSL_EXCLUSIVE_LOCKS_REQUIRED(tcp->read_mu) { if (!tcp->has_posted_reclaimer) { tcp->has_posted_reclaimer = true; - TCP_REF(tcp, "posted_reclaimer"); tcp->memory_owner.PostReclaimer( grpc_core::ReclamationPass::kBenign, [tcp](absl::optional sweep) { - if (sweep.has_value()) { - perform_reclamation(tcp); - } - TCP_UNREF(tcp, "posted_reclaimer"); + if (!sweep.has_value()) return; + perform_reclamation(tcp); }); } } @@ -1097,7 +1088,7 @@ static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error_handle error) { } tcp->read_mu.Lock(); grpc_error_handle tcp_read_error; - if (GPR_LIKELY(error.ok()) && tcp->memory_owner.is_valid()) { + if (GPR_LIKELY(error.ok())) { maybe_make_read_slices(tcp); if (!tcp_do_read(tcp, &tcp_read_error)) { // Maybe update rcv lowat value based on the number of bytes read in this @@ -1110,12 +1101,7 @@ static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error_handle error) { } tcp_trace_read(tcp, tcp_read_error); } else { - if (!tcp->memory_owner.is_valid() && error.ok()) { - tcp_read_error = - tcp_annotate_error(absl::InternalError("Socket closed"), tcp); - } else { - tcp_read_error = error; - } + tcp_read_error = error; grpc_slice_buffer_reset_and_unref(tcp->incoming_buffer); grpc_slice_buffer_reset_and_unref(&tcp->last_read_buffer); } @@ -2045,9 +2031,6 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } - tcp->read_mu.Lock(); - tcp->memory_owner.Reset(); - tcp->read_mu.Unlock(); TCP_UNREF(tcp, "destroy"); } diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 69b01b60d64..f29027c34ed 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -1008,21 +1008,3 @@ grpc_cc_test( "//test/cpp/util:test_util", ], ) - -grpc_cc_test( - name = "resource_quota_end2end_stress_test", - srcs = ["resource_quota_end2end_stress_test.cc"], - external_deps = [ - "gtest", - "absl/strings", - "absl/time", - ], - deps = [ - "//:grpc++", - "//src/core:experiments", - "//src/proto/grpc/testing:echo_messages_proto", - "//src/proto/grpc/testing:echo_proto", - "//test/core/util:grpc_test_util", - "//test/cpp/util:test_util", - ], -) diff --git a/test/cpp/end2end/resource_quota_end2end_stress_test.cc b/test/cpp/end2end/resource_quota_end2end_stress_test.cc deleted file mode 100644 index c475fa1ab68..00000000000 --- a/test/cpp/end2end/resource_quota_end2end_stress_test.cc +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2023 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 -#include -#include -#include -#include - -#include - -#include "absl/status/statusor.h" -#include "absl/strings/str_cat.h" -#include "absl/time/time.h" - -#include -#include -#include -#include - -#include "src/core/lib/experiments/config.h" -#include "src/core/lib/gprpp/notification.h" -#include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -// A stress test which spins up a server with a small configured resource quota -// value. It then creates many channels which exchange large payloads with the -// server. This would drive the server to reach resource quota limits and -// trigger reclamation. - -namespace grpc { -namespace testing { -namespace { -constexpr int kResourceQuotaSizeBytes = 1024 * 1024; -constexpr int kPayloadSizeBytes = 1024 * 1024; -constexpr int kNumParallelChannels = 1024; -} // namespace - -class EchoClientUnaryReactor : public grpc::ClientUnaryReactor { - public: - EchoClientUnaryReactor(ClientContext* ctx, EchoTestService::Stub* stub, - const std::string payload, Status* status) - : ctx_(ctx), payload_(payload), status_(status) { - ctx_->set_wait_for_ready(true); - request_.set_message(payload); - stub->async()->Echo(ctx_, &request_, &response_, this); - StartCall(); - } - - void Await() { notification_.WaitForNotification(); } - - protected: - void OnReadInitialMetadataDone(bool /*ok*/) override {} - - void OnDone(const Status& s) override { - *status_ = s; - notification_.Notify(); - } - - private: - ClientContext* const ctx_; - EchoRequest request_; - EchoResponse response_; - const std::string payload_; - grpc_core::Notification notification_; - Status* const status_; -}; - -class EchoServerUnaryReactor : public ServerUnaryReactor { - public: - EchoServerUnaryReactor(CallbackServerContext* /*ctx*/, - const EchoRequest* request, EchoResponse* response) { - response->set_message(request->message()); - Finish(grpc::Status::OK); - } - - private: - void OnDone() override { delete this; } -}; - -class GrpcCallbackServiceImpl : public EchoTestService::CallbackService { - public: - ServerUnaryReactor* Echo(CallbackServerContext* context, - const EchoRequest* request, - EchoResponse* response) override { - return new EchoServerUnaryReactor(context, request, response); - } -}; - -class End2EndResourceQuotaUnaryTest : public ::testing::Test { - protected: - End2EndResourceQuotaUnaryTest() { - int port = grpc_pick_unused_port_or_die(); - server_address_ = absl::StrCat("localhost:", port); - payload_ = std::string(kPayloadSizeBytes, 'a'); - ServerBuilder builder; - builder.AddListeningPort(server_address_, InsecureServerCredentials()); - builder.SetResourceQuota( - grpc::ResourceQuota("TestService").Resize(kResourceQuotaSizeBytes)); - builder.RegisterService(&grpc_service_); - server_ = builder.BuildAndStart(); - } - - ~End2EndResourceQuotaUnaryTest() override { server_->Shutdown(); } - - void MakeGrpcCall() { - ClientContext ctx; - Status status; - auto stub = EchoTestService::NewStub( - CreateChannel(server_address_, grpc::InsecureChannelCredentials())); - EchoClientUnaryReactor reactor(&ctx, stub.get(), payload_, &status); - reactor.Await(); - } - - void MakeGrpcCalls() { - std::vector workers; - workers.reserve(kNumParallelChannels); - // Run MakeGrpcCall() many times concurrently. - for (int i = 0; i < kNumParallelChannels; ++i) { - workers.emplace_back([this]() { MakeGrpcCall(); }); - } - for (int i = 0; i < kNumParallelChannels; ++i) { - workers[i].join(); - } - } - - int port_; - std::unique_ptr server_; - string server_address_; - GrpcCallbackServiceImpl grpc_service_; - std::string payload_; -}; - -TEST_F(End2EndResourceQuotaUnaryTest, MultipleUnaryRPCTest) { MakeGrpcCalls(); } - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 81a5653f6e1..563d0eba66e 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -7089,30 +7089,6 @@ ], "uses_polling": true }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": true, - "language": "c++", - "name": "resource_quota_end2end_stress_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, { "args": [], "benchmark": false,