[promise] Add an optimization for promises of size <= sizeof(void*) (#29835)

* vtable phrasing

* small promise optimization

* fix

* Automated change: Fix sanity tests

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/30573/head
Craig Tiller 2 years ago committed by GitHub
parent 0e38bb3b5c
commit 468fe2d835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      BUILD
  2. 1
      src/core/ext/filters/fault_injection/fault_injection_filter.cc
  3. 1
      src/core/ext/filters/http/client/http_client_filter.cc
  4. 1
      src/core/ext/filters/http/client_authority_filter.cc
  5. 1
      src/core/ext/filters/http/server/http_server_filter.cc
  6. 1
      src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
  7. 1
      src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
  8. 1
      src/core/lib/channel/channel_stack.cc
  9. 1
      src/core/lib/http/httpcli_security_connector.cc
  10. 164
      src/core/lib/promise/arena_promise.h
  11. 1
      src/core/lib/security/authorization/grpc_server_authz_filter.cc
  12. 1
      src/core/lib/security/credentials/composite/composite_credentials.cc
  13. 1
      src/core/lib/security/credentials/fake/fake_credentials.cc
  14. 1
      src/core/lib/security/credentials/iam/iam_credentials.cc
  15. 1
      src/core/lib/security/credentials/jwt/jwt_credentials.cc
  16. 1
      src/core/lib/security/security_connector/alts/alts_security_connector.cc
  17. 1
      src/core/lib/security/security_connector/fake/fake_security_connector.cc
  18. 1
      src/core/lib/security/security_connector/insecure/insecure_security_connector.cc
  19. 1
      src/core/lib/security/security_connector/local/local_security_connector.cc
  20. 1
      src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
  21. 1
      src/core/lib/security/security_connector/tls/tls_security_connector.cc
  22. 1
      src/core/lib/security/transport/client_auth_filter.cc
  23. 1
      src/core/lib/surface/lame_client.cc

15
BUILD

@ -3641,7 +3641,6 @@ grpc_cc_library(
"grpc_base",
"grpc_server_config_selector",
"grpc_service_config",
"poll",
"promise",
"ref_counted_ptr",
],
@ -3762,7 +3761,6 @@ grpc_cc_library(
"gpr_platform",
"grpc_base",
"grpc_codegen",
"poll",
"slice",
],
)
@ -3835,7 +3833,6 @@ grpc_cc_library(
"grpc_trace",
"json",
"json_util",
"poll",
"service_config_parser",
"sleep",
"time",
@ -3929,7 +3926,6 @@ grpc_cc_library(
"grpc_trace",
"latch",
"percent_encoding",
"poll",
"promise",
"seq",
"slice",
@ -4882,7 +4878,6 @@ grpc_cc_library(
"grpc_public_hdrs",
"grpc_security_base",
"grpc_sockaddr",
"poll",
"promise",
"resolved_address",
"seq",
@ -5401,7 +5396,6 @@ grpc_cc_library(
"grpc_credentials_util",
"grpc_security_base",
"grpc_trace",
"poll",
"promise",
"ref_counted",
"ref_counted_ptr",
@ -5459,7 +5453,6 @@ grpc_cc_library(
"grpc_security_base",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted_ptr",
"slice",
@ -5493,7 +5486,6 @@ grpc_cc_library(
"grpc_security_base",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted_ptr",
"tsi_base",
@ -5546,7 +5538,6 @@ grpc_cc_library(
"grpc_sockaddr",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted_ptr",
"resolved_address",
@ -5586,7 +5577,6 @@ grpc_cc_library(
"grpc_security_base",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted_ptr",
"slice_refcount",
@ -5624,7 +5614,6 @@ grpc_cc_library(
"grpc_trace",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted_ptr",
"tsi_base",
@ -5720,7 +5709,6 @@ grpc_cc_library(
"grpc_trace",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted",
"ref_counted_ptr",
@ -5754,7 +5742,6 @@ grpc_cc_library(
"grpc_base",
"grpc_security_base",
"grpc_trace",
"poll",
"promise",
"ref_counted_ptr",
"slice",
@ -5799,7 +5786,6 @@ grpc_cc_library(
"httpcli_ssl_credentials",
"json",
"orphanable",
"poll",
"promise",
"ref_counted_ptr",
"slice",
@ -5921,7 +5907,6 @@ grpc_cc_library(
"grpc_security_base",
"handshaker",
"iomgr_fwd",
"poll",
"promise",
"ref_counted_ptr",
"tsi_base",

@ -46,7 +46,6 @@
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/sleep.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/service_config/service_config_call_data.h"

@ -43,7 +43,6 @@
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/detail/basic_seq.h"
#include "src/core/lib/promise/latch.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/percent_encoding.h"

@ -33,7 +33,6 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/metadata_batch.h"

@ -36,7 +36,6 @@
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/detail/basic_seq.h"
#include "src/core/lib/promise/latch.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/promise/seq.h"
#include "src/core/lib/resource_quota/arena.h"

@ -57,7 +57,6 @@
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/promise/seq.h"
#include "src/core/lib/security/context/security_context.h"

@ -37,7 +37,6 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config_call_data.h"

@ -27,7 +27,6 @@
#include <grpc/support/log.h>
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/promise/poll.h"
grpc_core::TraceFlag grpc_trace_channel(false, "channel");
grpc_core::TraceFlag grpc_trace_channel_stack(false, "channel_stack");

@ -44,7 +44,6 @@
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/security_connector/security_connector.h"

@ -19,6 +19,7 @@
#include <stdlib.h>
#include <new>
#include <utility>
#include "absl/meta/type_traits.h"
@ -31,59 +32,58 @@ namespace grpc_core {
namespace arena_promise_detail {
// Type erased promise stored in the arena.
template <typename T>
class ImplInterface {
public:
struct Vtable {
// Poll the promise, once.
virtual Poll<T> PollOnce() = 0;
Poll<T> (*poll_once)(void** arg);
// Destroy the underlying callable object if there is one.
// Since we don't delete (the arena owns the memory) but we may need to call a
// destructor, we expose this for when the ArenaPromise object is destroyed.
virtual void Destroy() = 0;
void (*destroy)(void** arg);
};
protected:
~ImplInterface() = default;
template <typename T>
struct VtableAndArg {
const Vtable<T>* vtable;
void* arg;
};
// Implementation of ImplInterface for an empty object.
// Implementation of Vtable for an empty object.
// Used when an empty ArenaPromise is created, or when the ArenaPromise is moved
// from. Since in either case these objects should not be polled, we simply
// crash if it is.
template <typename T>
class NullImpl final : public ImplInterface<T> {
public:
Poll<T> PollOnce() override {
abort();
GPR_UNREACHABLE_CODE(return Pending{});
}
void Destroy() override {}
static ImplInterface<T>* Get() {
static NullImpl<T> instance;
return &instance;
}
private:
~NullImpl() = default;
};
inline const Vtable<T>* null_impl() {
static const Vtable<T> vtable = {[](void**) -> Poll<T> {
abort();
GPR_UNREACHABLE_CODE(return Pending{});
},
[](void**) {}};
return &vtable;
}
// Implementation of ImplInterface for a callable object.
template <typename T, typename Callable>
class CallableImpl final : public ImplInterface<T> {
public:
explicit CallableImpl(Callable&& callable) : callable_(std::move(callable)) {}
// Forward polls to the callable object.
Poll<T> PollOnce() override { return poll_cast<T>(callable_()); }
// Destroy destructs the callable object.
void Destroy() override { this->~CallableImpl(); }
private:
// Should only be called by Destroy().
~CallableImpl() = default;
inline const Vtable<T>* allocated_callable_impl() {
static const Vtable<T> vtable = {
[](void** arg) -> Poll<T> {
return poll_cast<T>((*static_cast<Callable*>(*arg))());
},
[](void** arg) { static_cast<Callable*>(*arg)->~Callable(); }};
return &vtable;
}
Callable callable_;
};
// Implementation of ImplInterface for a small callable object (one that fits
// within the void* arg)
template <typename T, typename Callable>
inline const Vtable<T>* inlined_callable_impl() {
static const Vtable<T> vtable = {
[](void** arg) -> Poll<T> {
return poll_cast<T>((*reinterpret_cast<Callable*>(arg))());
},
[](void** arg) { reinterpret_cast<Callable*>(arg)->~Callable(); }};
return &vtable;
}
// If a callable object is empty we can substitute any instance of that callable
// for the one we call (for how could we tell the difference)?
@ -93,27 +93,12 @@ class CallableImpl final : public ImplInterface<T> {
// (this comes up often when the promise only accesses context data from the
// containing activity).
template <typename T, typename Callable>
class SharedImpl final : public ImplInterface<T>, private Callable {
public:
// Call the callable, or at least an exact duplicate of it - if you have no
// members, all your instances look the same.
Poll<T> PollOnce() override { return Callable::operator()(); }
// Nothing to destroy.
void Destroy() override {}
// Return a pointer to the shared instance - these are singletons, and are
// needed just to get the vtable in place.
static SharedImpl* Get(Callable&& callable) {
static_assert(sizeof(SharedImpl) == sizeof(void*),
"SharedImpl should be pointer sized");
static SharedImpl impl(std::forward<Callable>(callable));
return &impl;
}
private:
explicit SharedImpl(Callable&& callable)
: Callable(std::forward<Callable>(callable)) {}
~SharedImpl() = default;
};
inline const Vtable<T>* shared_callable_impl(Callable&& callable) {
static Callable instance = std::forward<Callable>(callable);
static const Vtable<T> vtable = {[](void**) -> Poll<T> { return instance(); },
[](void**) {}};
return &vtable;
}
// Redirector type: given a callable type, expose a Make() function that creates
// the appropriate underlying implementation.
@ -122,26 +107,41 @@ struct ChooseImplForCallable;
template <typename T, typename Callable>
struct ChooseImplForCallable<
T, Callable, absl::enable_if_t<!std::is_empty<Callable>::value>> {
static ImplInterface<T>* Make(Callable&& callable) {
return GetContext<Arena>()->template New<CallableImpl<T, Callable>>(
std::forward<Callable>(callable));
T, Callable,
absl::enable_if_t<!std::is_empty<Callable>::value &&
(sizeof(Callable) > sizeof(void*))>> {
static void Make(Callable&& callable, VtableAndArg<T>* out) {
*out = {allocated_callable_impl<T, Callable>(),
GetContext<Arena>()->template New<Callable>(
std::forward<Callable>(callable))};
}
};
template <typename T, typename Callable>
struct ChooseImplForCallable<
T, Callable,
absl::enable_if_t<!std::is_empty<Callable>::value &&
(sizeof(Callable) <= sizeof(void*))>> {
static void Make(Callable&& callable, VtableAndArg<T>* out) {
out->vtable = inlined_callable_impl<T, Callable>();
new (&out->arg) Callable(std::forward<Callable>(callable));
}
};
template <typename T, typename Callable>
struct ChooseImplForCallable<
T, Callable, absl::enable_if_t<std::is_empty<Callable>::value>> {
static ImplInterface<T>* Make(Callable&& callable) {
return SharedImpl<T, Callable>::Get(std::forward<Callable>(callable));
static void Make(Callable&& callable, VtableAndArg<T>* out) {
out->vtable =
shared_callable_impl<T, Callable>(std::forward<Callable>(callable));
}
};
// Wrap ChooseImplForCallable with a friend approachable syntax.
template <typename T, typename Callable>
ImplInterface<T>* MakeImplForCallable(Callable&& callable) {
return ChooseImplForCallable<T, Callable>::Make(
std::forward<Callable>(callable));
void MakeImplForCallable(Callable&& callable, VtableAndArg<T>* out) {
ChooseImplForCallable<T, Callable>::Make(std::forward<Callable>(callable),
out);
}
} // namespace arena_promise_detail
@ -158,38 +158,42 @@ class ArenaPromise {
typename Ignored =
absl::enable_if_t<!std::is_same<Callable, ArenaPromise>::value>>
// NOLINTNEXTLINE(google-explicit-constructor)
ArenaPromise(Callable&& callable)
: impl_(arena_promise_detail::MakeImplForCallable<T>(
std::forward<Callable>(callable))) {}
ArenaPromise(Callable&& callable) {
arena_promise_detail::MakeImplForCallable<T>(
std::forward<Callable>(callable), &vtable_and_arg_);
}
// ArenaPromise is not copyable.
ArenaPromise(const ArenaPromise&) = delete;
ArenaPromise& operator=(const ArenaPromise&) = delete;
// ArenaPromise is movable.
ArenaPromise(ArenaPromise&& other) noexcept : impl_(other.impl_) {
other.impl_ = arena_promise_detail::NullImpl<T>::Get();
ArenaPromise(ArenaPromise&& other) noexcept
: vtable_and_arg_(other.vtable_and_arg_) {
other.vtable_and_arg_.vtable = arena_promise_detail::null_impl<T>();
}
ArenaPromise& operator=(ArenaPromise&& other) noexcept {
impl_->Destroy();
impl_ = other.impl_;
other.impl_ = arena_promise_detail::NullImpl<T>::Get();
vtable_and_arg_.vtable->destroy(&vtable_and_arg_.arg);
vtable_and_arg_ = other.vtable_and_arg_;
other.vtable_and_arg_.vtable = arena_promise_detail::null_impl<T>();
return *this;
}
// Destruction => call Destroy on the underlying impl object.
~ArenaPromise() { impl_->Destroy(); }
~ArenaPromise() { vtable_and_arg_.vtable->destroy(&vtable_and_arg_.arg); }
// Expose the promise interface: a call operator that returns Poll<T>.
Poll<T> operator()() { return impl_->PollOnce(); }
Poll<T> operator()() {
return vtable_and_arg_.vtable->poll_once(&vtable_and_arg_.arg);
}
bool has_value() const {
return impl_ != arena_promise_detail::NullImpl<T>::Get();
return vtable_and_arg_.vtable != arena_promise_detail::null_impl<T>();
}
private:
// Underlying impl object.
arena_promise_detail::ImplInterface<T>* impl_ =
arena_promise_detail::NullImpl<T>::Get();
arena_promise_detail::VtableAndArg<T> vtable_and_arg_ = {
arena_promise_detail::null_impl<T>(), nullptr};
};
} // namespace grpc_core

@ -29,7 +29,6 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/authorization/authorization_engine.h"
#include "src/core/lib/security/authorization/evaluate_args.h"

@ -31,7 +31,6 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/transport.h"

@ -28,7 +28,6 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/security_connector/fake/fake_security_connector.h"
#include "src/core/lib/security/security_connector/security_connector.h"

@ -32,7 +32,6 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/metadata_batch.h"

@ -39,7 +39,6 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/call_creds_util.h"
#include "src/core/lib/surface/api_trace.h"

@ -46,7 +46,6 @@
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/alts/alts_credentials.h"

@ -50,7 +50,6 @@
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"

@ -29,7 +29,6 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/transport/security_handshaker.h"

@ -53,7 +53,6 @@
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"

@ -45,7 +45,6 @@
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"

@ -42,7 +42,6 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"

@ -41,7 +41,6 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/arena.h"

@ -42,7 +42,6 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/channel.h"

Loading…
Cancel
Save