[arena] Make arena refcounted (#36758)
Make `Arena` be a refcounted object.
Solves a bunch of issues: our stack right now needs a very complicated dance between transport and surface to destroy a call, but with this scheme we can just hold a ref to what we need in each place and everything works out.
Removes some `ifdef`'d out code that had been sitting dormant for a year or two also -- I'd left it in as a hedge against it being maybe a bad idea, but it looks like it's not needed.
Closes #36758
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36758 from ctiller:arena-counting d1b672fe30
PiperOrigin-RevId: 638767768
This commit is contained in:
parent
4423bfd0c6
commit
53c42e9dae
|
|
@ -8535,8 +8535,11 @@ add_executable(call_filters_test
|
|||
src/core/lib/promise/activity.cc
|
||||
src/core/lib/promise/trace.cc
|
||||
src/core/lib/resource_quota/arena.cc
|
||||
src/core/lib/resource_quota/connection_quota.cc
|
||||
src/core/lib/resource_quota/memory_quota.cc
|
||||
src/core/lib/resource_quota/periodic_update.cc
|
||||
src/core/lib/resource_quota/resource_quota.cc
|
||||
src/core/lib/resource_quota/thread_quota.cc
|
||||
src/core/lib/resource_quota/trace.cc
|
||||
src/core/lib/slice/percent_encoding.cc
|
||||
src/core/lib/slice/slice.cc
|
||||
|
|
|
|||
|
|
@ -6393,6 +6393,7 @@ targets:
|
|||
- src/core/lib/gprpp/atomic_utils.h
|
||||
- src/core/lib/gprpp/bitset.h
|
||||
- src/core/lib/gprpp/chunked_vector.h
|
||||
- src/core/lib/gprpp/cpp_impl_of.h
|
||||
- src/core/lib/gprpp/down_cast.h
|
||||
- src/core/lib/gprpp/dual_ref_counted.h
|
||||
- src/core/lib/gprpp/dump_args.h
|
||||
|
|
@ -6432,8 +6433,11 @@ targets:
|
|||
- src/core/lib/promise/status_flag.h
|
||||
- src/core/lib/promise/trace.h
|
||||
- src/core/lib/resource_quota/arena.h
|
||||
- src/core/lib/resource_quota/connection_quota.h
|
||||
- src/core/lib/resource_quota/memory_quota.h
|
||||
- src/core/lib/resource_quota/periodic_update.h
|
||||
- src/core/lib/resource_quota/resource_quota.h
|
||||
- src/core/lib/resource_quota/thread_quota.h
|
||||
- src/core/lib/resource_quota/trace.h
|
||||
- src/core/lib/slice/percent_encoding.h
|
||||
- src/core/lib/slice/slice.h
|
||||
|
|
@ -6499,8 +6503,11 @@ targets:
|
|||
- src/core/lib/promise/activity.cc
|
||||
- src/core/lib/promise/trace.cc
|
||||
- src/core/lib/resource_quota/arena.cc
|
||||
- src/core/lib/resource_quota/connection_quota.cc
|
||||
- src/core/lib/resource_quota/memory_quota.cc
|
||||
- src/core/lib/resource_quota/periodic_update.cc
|
||||
- src/core/lib/resource_quota/resource_quota.cc
|
||||
- src/core/lib/resource_quota/thread_quota.cc
|
||||
- src/core/lib/resource_quota/trace.cc
|
||||
- src/core/lib/slice/percent_encoding.cc
|
||||
- src/core/lib/slice/slice.cc
|
||||
|
|
|
|||
|
|
@ -1489,6 +1489,7 @@ grpc_cc_library(
|
|||
"context",
|
||||
"event_engine_memory_allocator",
|
||||
"memory_quota",
|
||||
"resource_quota",
|
||||
"//:gpr",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -653,11 +653,6 @@ ClientChannel::ClientChannel(
|
|||
default_authority_(
|
||||
GetDefaultAuthorityFromChannelArgs(channel_args_, this->target())),
|
||||
channelz_node_(channel_args_.GetObject<channelz::ChannelNode>()),
|
||||
call_arena_allocator_(MakeRefCounted<CallArenaAllocator>(
|
||||
channel_args_.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("client_channel"),
|
||||
1024)),
|
||||
idle_timeout_(GetClientIdleTimeout(channel_args_)),
|
||||
resolver_data_for_calls_(ResolverDataForCalls{}),
|
||||
picker_(nullptr),
|
||||
|
|
@ -825,9 +820,9 @@ CallInitiator ClientChannel::CreateCall(
|
|||
// Exit IDLE if needed.
|
||||
CheckConnectivityState(/*try_to_connect=*/true);
|
||||
// Create an initiator/unstarted-handler pair.
|
||||
auto call = MakeCallPair(
|
||||
std::move(client_initial_metadata), event_engine_.get(),
|
||||
call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr);
|
||||
auto call =
|
||||
MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
|
||||
call_arena_allocator()->MakeArena(), nullptr);
|
||||
// Spawn a promise to wait for the resolver result.
|
||||
// This will eventually start the call.
|
||||
call.initiator.SpawnGuardedUntilCallCompletes(
|
||||
|
|
|
|||
|
|
@ -179,8 +179,6 @@ class ClientChannel : public Channel {
|
|||
ClientChannelFactory* const client_channel_factory_;
|
||||
const std::string default_authority_;
|
||||
channelz::ChannelNode* const channelz_node_;
|
||||
// TODO(ctiller): unify with Channel
|
||||
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
|
||||
GlobalStatsPluginRegistry::StatsPluginGroup stats_plugin_group_;
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -59,12 +59,13 @@ SubchannelStreamClient::SubchannelStreamClient(
|
|||
connected_subchannel_(std::move(connected_subchannel)),
|
||||
interested_parties_(interested_parties),
|
||||
tracer_(tracer),
|
||||
call_allocator_(
|
||||
call_allocator_(MakeRefCounted<CallArenaAllocator>(
|
||||
connected_subchannel_->args()
|
||||
.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator(
|
||||
(tracer != nullptr) ? tracer : "SubchannelStreamClient")),
|
||||
(tracer != nullptr) ? tracer : "SubchannelStreamClient"),
|
||||
1024)),
|
||||
event_handler_(std::move(event_handler)),
|
||||
retry_backoff_(
|
||||
BackOff::Options()
|
||||
|
|
@ -171,9 +172,7 @@ SubchannelStreamClient::CallState::CallState(
|
|||
grpc_pollset_set* interested_parties)
|
||||
: subchannel_stream_client_(std::move(health_check_client)),
|
||||
pollent_(grpc_polling_entity_create_from_pollset_set(interested_parties)),
|
||||
arena_(Arena::Create(subchannel_stream_client_->connected_subchannel_
|
||||
->GetInitialCallSizeEstimate(),
|
||||
&subchannel_stream_client_->call_allocator_)),
|
||||
arena_(subchannel_stream_client_->call_allocator_->MakeArena()),
|
||||
payload_(context_) {}
|
||||
|
||||
SubchannelStreamClient::CallState::~CallState() {
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ class SubchannelStreamClient final
|
|||
RefCountedPtr<SubchannelStreamClient> subchannel_stream_client_;
|
||||
grpc_polling_entity pollent_;
|
||||
|
||||
ScopedArenaPtr arena_;
|
||||
RefCountedPtr<Arena> arena_;
|
||||
CallCombiner call_combiner_;
|
||||
grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {};
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ class SubchannelStreamClient final
|
|||
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
|
||||
grpc_pollset_set* interested_parties_; // Do not own.
|
||||
const char* tracer_;
|
||||
MemoryAllocator call_allocator_;
|
||||
RefCountedPtr<CallArenaAllocator> call_allocator_;
|
||||
|
||||
Mutex mu_;
|
||||
std::unique_ptr<CallEventHandler> event_handler_ ABSL_GUARDED_BY(mu_);
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ void ChaoticGoodConnector::OnHandshakeDone(void* arg, grpc_error_handle error) {
|
|||
status);
|
||||
}
|
||||
},
|
||||
self->arena_.get(), self->event_engine_.get());
|
||||
self->arena_, self->event_engine_.get());
|
||||
MutexLock lock(&self->mu_);
|
||||
if (!self->is_shutdown_) {
|
||||
self->connect_activity_ = std::move(activity);
|
||||
|
|
|
|||
|
|
@ -79,10 +79,7 @@ class ChaoticGoodConnector : public SubchannelConnector {
|
|||
RefCountedPtr<ChaoticGoodConnector> self);
|
||||
static void OnHandshakeDone(void* arg, grpc_error_handle error);
|
||||
|
||||
grpc_event_engine::experimental::MemoryAllocator memory_allocator_ =
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"connect_activity");
|
||||
ScopedArenaPtr arena_ = MakeScopedArena(1024, &memory_allocator_);
|
||||
RefCountedPtr<Arena> arena_ = SimpleArenaAllocator()->MakeArena();
|
||||
Mutex mu_;
|
||||
Args args_;
|
||||
Result* result_ ABSL_GUARDED_BY(mu_);
|
||||
|
|
|
|||
|
|
@ -146,10 +146,9 @@ auto ChaoticGoodClientTransport::TransportReadLoop(
|
|||
frame_limits);
|
||||
} else {
|
||||
// Stream not found, skip the frame.
|
||||
auto arena = MakeScopedArena(1024, &allocator_);
|
||||
deserialize_status =
|
||||
transport->DeserializeFrame(frame_header, std::move(buffers),
|
||||
arena.get(), frame, frame_limits);
|
||||
deserialize_status = transport->DeserializeFrame(
|
||||
frame_header, std::move(buffers),
|
||||
SimpleArenaAllocator()->MakeArena().get(), frame, frame_limits);
|
||||
}
|
||||
return If(
|
||||
deserialize_status.ok() && call_handler.has_value(),
|
||||
|
|
|
|||
|
|
@ -149,8 +149,7 @@ absl::Status ChaoticGoodServerListener::StartListening() {
|
|||
ChaoticGoodServerListener::ActiveConnection::ActiveConnection(
|
||||
RefCountedPtr<ChaoticGoodServerListener> listener,
|
||||
std::unique_ptr<EventEngine::Endpoint> endpoint)
|
||||
: memory_allocator_(listener->memory_allocator_),
|
||||
listener_(std::move(listener)) {
|
||||
: listener_(std::move(listener)) {
|
||||
handshaking_state_ = MakeRefCounted<HandshakingState>(Ref());
|
||||
handshaking_state_->Start(std::move(endpoint));
|
||||
}
|
||||
|
|
@ -208,8 +207,7 @@ void ChaoticGoodServerListener::ActiveConnection::Done(
|
|||
|
||||
ChaoticGoodServerListener::ActiveConnection::HandshakingState::HandshakingState(
|
||||
RefCountedPtr<ActiveConnection> connection)
|
||||
: memory_allocator_(connection->memory_allocator_),
|
||||
connection_(std::move(connection)),
|
||||
: connection_(std::move(connection)),
|
||||
handshake_mgr_(MakeRefCounted<HandshakeManager>()) {}
|
||||
|
||||
void ChaoticGoodServerListener::ActiveConnection::HandshakingState::Start(
|
||||
|
|
|
|||
|
|
@ -106,8 +106,6 @@ class ChaoticGoodServerListener final : public Server::ListenerInterface {
|
|||
|
||||
static void OnHandshakeDone(void* arg, grpc_error_handle error);
|
||||
Timestamp GetConnectionDeadline();
|
||||
const std::shared_ptr<grpc_event_engine::experimental::MemoryAllocator>
|
||||
memory_allocator_;
|
||||
const RefCountedPtr<ActiveConnection> connection_;
|
||||
const RefCountedPtr<HandshakeManager> handshake_mgr_;
|
||||
};
|
||||
|
|
@ -115,9 +113,7 @@ class ChaoticGoodServerListener final : public Server::ListenerInterface {
|
|||
private:
|
||||
void Done(absl::optional<absl::string_view> error = absl::nullopt);
|
||||
void NewConnectionID();
|
||||
const std::shared_ptr<grpc_event_engine::experimental::MemoryAllocator>
|
||||
memory_allocator_;
|
||||
ScopedArenaPtr arena_ = MakeScopedArena(1024, memory_allocator_.get());
|
||||
RefCountedPtr<Arena> arena_ = SimpleArenaAllocator()->MakeArena();
|
||||
const RefCountedPtr<ChaoticGoodServerListener> listener_;
|
||||
RefCountedPtr<HandshakingState> handshaking_state_;
|
||||
Mutex mu_;
|
||||
|
|
@ -161,11 +157,6 @@ class ChaoticGoodServerListener final : public Server::ListenerInterface {
|
|||
absl::AnyInvocable<std::string()> connection_id_generator_
|
||||
ABSL_GUARDED_BY(mu_);
|
||||
grpc_closure* on_destroy_done_ ABSL_GUARDED_BY(mu_) = nullptr;
|
||||
std::shared_ptr<grpc_event_engine::experimental::MemoryAllocator>
|
||||
memory_allocator_ =
|
||||
std::make_shared<grpc_event_engine::experimental::MemoryAllocator>(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"server_connection"));
|
||||
};
|
||||
|
||||
} // namespace chaotic_good
|
||||
|
|
|
|||
|
|
@ -235,15 +235,14 @@ auto ChaoticGoodServerTransport::DeserializeAndPushFragmentToNewCall(
|
|||
FrameHeader frame_header, BufferPair buffers,
|
||||
ChaoticGoodTransport& transport) {
|
||||
ClientFragmentFrame fragment_frame;
|
||||
ScopedArenaPtr arena(call_arena_allocator_->MakeArena());
|
||||
RefCountedPtr<Arena> arena(call_arena_allocator_->MakeArena());
|
||||
absl::Status status = transport.DeserializeFrame(
|
||||
frame_header, std::move(buffers), arena.get(), fragment_frame,
|
||||
FrameLimits{1024 * 1024 * 1024, aligned_bytes_ - 1});
|
||||
absl::optional<CallInitiator> call_initiator;
|
||||
if (status.ok()) {
|
||||
auto call =
|
||||
MakeCallPair(std::move(fragment_frame.headers), event_engine_.get(),
|
||||
arena.release(), call_arena_allocator_, nullptr);
|
||||
auto call = MakeCallPair(std::move(fragment_frame.headers),
|
||||
event_engine_.get(), std::move(arena), nullptr);
|
||||
call_initiator.emplace(std::move(call.initiator));
|
||||
auto add_result = NewStream(frame_header.stream_id, *call_initiator);
|
||||
if (add_result.ok()) {
|
||||
|
|
|
|||
|
|
@ -105,9 +105,9 @@ class InprocServerTransport final : public ServerTransport {
|
|||
case ConnectionState::kReady:
|
||||
break;
|
||||
}
|
||||
auto* arena = call_arena_allocator_->MakeArena();
|
||||
auto server_call = MakeCallPair(std::move(md), event_engine_.get(), arena,
|
||||
call_arena_allocator_, nullptr);
|
||||
auto server_call =
|
||||
MakeCallPair(std::move(md), event_engine_.get(),
|
||||
call_arena_allocator_->MakeArena(), nullptr);
|
||||
unstarted_call_handler_->StartCall(std::move(server_call.handler));
|
||||
return std::move(server_call.initiator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,6 +289,19 @@ class ContextHolder<std::unique_ptr<Context, Deleter>> {
|
|||
std::unique_ptr<Context, Deleter> value_;
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
class ContextHolder<RefCountedPtr<Context>> {
|
||||
public:
|
||||
using ContextType = Context;
|
||||
|
||||
explicit ContextHolder(RefCountedPtr<Context> value)
|
||||
: value_(std::move(value)) {}
|
||||
Context* GetContext() { return value_.get(); }
|
||||
|
||||
private:
|
||||
RefCountedPtr<Context> value_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class Context<Activity> {
|
||||
public:
|
||||
|
|
@ -296,19 +309,23 @@ class Context<Activity> {
|
|||
};
|
||||
|
||||
template <typename HeldContext>
|
||||
using ContextTypeFromHeld = typename ContextHolder<HeldContext>::ContextType;
|
||||
using ContextTypeFromHeld = typename ContextHolder<
|
||||
typename std::remove_reference<HeldContext>::type>::ContextType;
|
||||
|
||||
template <typename... Contexts>
|
||||
class ActivityContexts : public ContextHolder<Contexts>... {
|
||||
class ActivityContexts
|
||||
: public ContextHolder<typename std::remove_reference<Contexts>::type>... {
|
||||
public:
|
||||
explicit ActivityContexts(Contexts&&... contexts)
|
||||
: ContextHolder<Contexts>(std::forward<Contexts>(contexts))... {}
|
||||
: ContextHolder<typename std::remove_reference<Contexts>::type>(
|
||||
std::forward<Contexts>(contexts))... {}
|
||||
|
||||
class ScopedContext : public Context<ContextTypeFromHeld<Contexts>>... {
|
||||
public:
|
||||
explicit ScopedContext(ActivityContexts* contexts)
|
||||
: Context<ContextTypeFromHeld<Contexts>>(
|
||||
static_cast<ContextHolder<Contexts>*>(contexts)
|
||||
static_cast<ContextHolder<
|
||||
typename std::remove_reference<Contexts>::type>*>(contexts)
|
||||
->GetContext())... {
|
||||
// Silence `unused-but-set-parameter` in case of Contexts = {}
|
||||
(void)contexts;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "src/core/lib/resource_quota/resource_quota.h"
|
||||
#include "src/core/util/alloc.h"
|
||||
|
||||
namespace {
|
||||
|
|
@ -46,6 +47,10 @@ void* ArenaStorage(size_t initial_size) {
|
|||
namespace grpc_core {
|
||||
|
||||
Arena::~Arena() {
|
||||
DestroyManagedNewObjects();
|
||||
arena_factory_->FinalizeArena(this);
|
||||
arena_factory_->allocator().Release(
|
||||
total_allocated_.load(std::memory_order_relaxed));
|
||||
Zone* z = last_zone_;
|
||||
while (z) {
|
||||
Zone* prev_z = z->prev;
|
||||
|
|
@ -58,19 +63,19 @@ Arena::~Arena() {
|
|||
#endif
|
||||
}
|
||||
|
||||
Arena* Arena::Create(size_t initial_size, MemoryAllocator* memory_allocator) {
|
||||
return new (ArenaStorage(initial_size))
|
||||
Arena(initial_size, 0, memory_allocator);
|
||||
RefCountedPtr<Arena> Arena::Create(size_t initial_size,
|
||||
RefCountedPtr<ArenaFactory> arena_factory) {
|
||||
return RefCountedPtr<Arena>(new (ArenaStorage(initial_size)) Arena(
|
||||
initial_size, 0, std::move(arena_factory)));
|
||||
}
|
||||
|
||||
std::pair<Arena*, void*> Arena::CreateWithAlloc(
|
||||
size_t initial_size, size_t alloc_size, MemoryAllocator* memory_allocator) {
|
||||
static constexpr size_t base_size =
|
||||
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Arena));
|
||||
auto* new_arena = new (ArenaStorage(initial_size))
|
||||
Arena(initial_size, alloc_size, memory_allocator);
|
||||
void* first_alloc = reinterpret_cast<char*>(new_arena) + base_size;
|
||||
return std::make_pair(new_arena, first_alloc);
|
||||
Arena::Arena(size_t initial_size, size_t initial_alloc,
|
||||
RefCountedPtr<ArenaFactory> arena_factory)
|
||||
: total_used_(GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_alloc)),
|
||||
initial_zone_size_(initial_size),
|
||||
arena_factory_(std::move(arena_factory)) {
|
||||
arena_factory_->allocator().Reserve(
|
||||
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_alloc));
|
||||
}
|
||||
|
||||
void Arena::DestroyManagedNewObjects() {
|
||||
|
|
@ -86,11 +91,9 @@ void Arena::DestroyManagedNewObjects() {
|
|||
}
|
||||
}
|
||||
|
||||
void Arena::Destroy() {
|
||||
DestroyManagedNewObjects();
|
||||
memory_allocator_->Release(total_allocated_.load(std::memory_order_relaxed));
|
||||
void Arena::Destroy() const {
|
||||
this->~Arena();
|
||||
gpr_free_aligned(this);
|
||||
gpr_free_aligned(const_cast<Arena*>(this));
|
||||
}
|
||||
|
||||
void* Arena::AllocZone(size_t size) {
|
||||
|
|
@ -102,7 +105,7 @@ void* Arena::AllocZone(size_t size) {
|
|||
static constexpr size_t zone_base_size =
|
||||
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Zone));
|
||||
size_t alloc_size = zone_base_size + size;
|
||||
memory_allocator_->Reserve(alloc_size);
|
||||
arena_factory_->allocator().Reserve(alloc_size);
|
||||
total_allocated_.fetch_add(alloc_size, std::memory_order_relaxed);
|
||||
Zone* z = new (gpr_malloc_aligned(alloc_size, GPR_MAX_ALIGNMENT)) Zone();
|
||||
auto* prev = last_zone_.load(std::memory_order_relaxed);
|
||||
|
|
@ -120,63 +123,27 @@ void Arena::ManagedNewObject::Link(std::atomic<ManagedNewObject*>* head) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
void* Arena::AllocPooled(size_t obj_size, size_t alloc_size,
|
||||
std::atomic<FreePoolNode*>* head) {
|
||||
// ABA mitigation:
|
||||
// AllocPooled may be called by multiple threads, and to remove a node from
|
||||
// the free list we need to manipulate the next pointer, which may be done
|
||||
// differently by each thread in a naive implementation.
|
||||
// The literature contains various ways of dealing with this. Here we expect
|
||||
// to be mostly single threaded - Arena's are owned by calls and calls don't
|
||||
// do a lot of concurrent work with the pooled allocator. The place that they
|
||||
// do is allocating metadata batches for decoding HPACK headers in chttp2.
|
||||
// So we adopt an approach that is simple and fast for the single threaded
|
||||
// case, and that is also correct in the multi threaded case.
|
||||
RefCountedPtr<ArenaFactory> SimpleArenaAllocator(size_t initial_size) {
|
||||
class Allocator : public ArenaFactory {
|
||||
public:
|
||||
explicit Allocator(size_t initial_size)
|
||||
: ArenaFactory(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"simple-arena-allocator")),
|
||||
initial_size_(initial_size) {}
|
||||
|
||||
// First, take ownership of the entire free list. At this point we know that
|
||||
// no other thread can see free nodes and will be forced to allocate.
|
||||
// We think we're mostly single threaded and so that's ok.
|
||||
FreePoolNode* p = head->exchange(nullptr, std::memory_order_acquire);
|
||||
// If there are no nodes in the free list, then go ahead and allocate from the
|
||||
// arena.
|
||||
if (p == nullptr) {
|
||||
void* r = Alloc(alloc_size);
|
||||
TracePoolAlloc(obj_size, r);
|
||||
return r;
|
||||
}
|
||||
// We had a non-empty free list... but we own the *entire* free list.
|
||||
// We only want one node, so if there are extras we'd better give them back.
|
||||
if (p->next != nullptr) {
|
||||
// We perform an exchange to do so, but if there were concurrent frees with
|
||||
// this allocation then there'll be a free list that needs to be merged with
|
||||
// ours.
|
||||
FreePoolNode* extra = head->exchange(p->next, std::memory_order_acq_rel);
|
||||
// If there was a free list concurrently created, we merge it into the
|
||||
// overall free list here by simply freeing each node in turn. This is O(n),
|
||||
// but only O(n) in the number of nodes that were freed concurrently, and
|
||||
// again: we think real world use cases are going to see this as mostly
|
||||
// single threaded.
|
||||
while (extra != nullptr) {
|
||||
FreePoolNode* next = extra->next;
|
||||
FreePooled(extra, head);
|
||||
extra = next;
|
||||
RefCountedPtr<Arena> MakeArena() override {
|
||||
return Arena::Create(initial_size_, Ref());
|
||||
}
|
||||
}
|
||||
TracePoolAlloc(obj_size, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void Arena::FreePooled(void* p, std::atomic<FreePoolNode*>* head) {
|
||||
// May spuriously trace a free of an already freed object - see AllocPooled
|
||||
// ABA mitigation.
|
||||
TracePoolFree(p);
|
||||
FreePoolNode* node = static_cast<FreePoolNode*>(p);
|
||||
node->next = head->load(std::memory_order_acquire);
|
||||
while (!head->compare_exchange_weak(
|
||||
node->next, node, std::memory_order_acq_rel, std::memory_order_relaxed)) {
|
||||
}
|
||||
void FinalizeArena(Arena*) override {
|
||||
// No-op.
|
||||
}
|
||||
|
||||
private:
|
||||
size_t initial_size_;
|
||||
};
|
||||
return MakeRefCounted<Allocator>(initial_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -40,76 +40,12 @@
|
|||
#include "src/core/lib/resource_quota/memory_quota.h"
|
||||
#include "src/core/util/alloc.h"
|
||||
|
||||
#define GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
// #define GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
class Arena;
|
||||
|
||||
namespace arena_detail {
|
||||
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
struct PoolAndSize {
|
||||
size_t alloc_size;
|
||||
size_t pool_index;
|
||||
};
|
||||
|
||||
template <typename Void, size_t kIndex, size_t kObjectSize,
|
||||
size_t... kBucketSize>
|
||||
struct PoolIndexForSize;
|
||||
|
||||
template <size_t kObjectSize, size_t kIndex, size_t kSmallestRemainingBucket,
|
||||
size_t... kBucketSizes>
|
||||
struct PoolIndexForSize<
|
||||
absl::enable_if_t<kObjectSize <= kSmallestRemainingBucket>, kIndex,
|
||||
kObjectSize, kSmallestRemainingBucket, kBucketSizes...> {
|
||||
static constexpr size_t kPool = kIndex;
|
||||
static constexpr size_t kSize = kSmallestRemainingBucket;
|
||||
};
|
||||
|
||||
template <size_t kObjectSize, size_t kIndex, size_t kSmallestRemainingBucket,
|
||||
size_t... kBucketSizes>
|
||||
struct PoolIndexForSize<
|
||||
absl::enable_if_t<(kObjectSize > kSmallestRemainingBucket)>, kIndex,
|
||||
kObjectSize, kSmallestRemainingBucket, kBucketSizes...>
|
||||
: public PoolIndexForSize<void, kIndex + 1, kObjectSize, kBucketSizes...> {
|
||||
};
|
||||
|
||||
template <size_t kObjectSize, size_t... kBucketSizes>
|
||||
constexpr size_t PoolFromObjectSize(
|
||||
absl::integer_sequence<size_t, kBucketSizes...>) {
|
||||
return PoolIndexForSize<void, 0, kObjectSize, kBucketSizes...>::kPool;
|
||||
}
|
||||
|
||||
template <size_t kObjectSize, size_t... kBucketSizes>
|
||||
constexpr size_t AllocationSizeFromObjectSize(
|
||||
absl::integer_sequence<size_t, kBucketSizes...>) {
|
||||
return PoolIndexForSize<void, 0, kObjectSize, kBucketSizes...>::kSize;
|
||||
}
|
||||
|
||||
template <size_t kIndex, size_t... kBucketSizes>
|
||||
struct ChoosePoolForAllocationSizeImpl;
|
||||
|
||||
template <size_t kIndex, size_t kBucketSize, size_t... kBucketSizes>
|
||||
struct ChoosePoolForAllocationSizeImpl<kIndex, kBucketSize, kBucketSizes...> {
|
||||
static PoolAndSize Fn(size_t n) {
|
||||
if (n <= kBucketSize) return {kBucketSize, kIndex};
|
||||
return ChoosePoolForAllocationSizeImpl<kIndex + 1, kBucketSizes...>::Fn(n);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t kIndex>
|
||||
struct ChoosePoolForAllocationSizeImpl<kIndex> {
|
||||
static PoolAndSize Fn(size_t n) {
|
||||
return PoolAndSize{n, std::numeric_limits<size_t>::max()};
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t... kBucketSizes>
|
||||
PoolAndSize ChoosePoolForAllocationSize(
|
||||
size_t n, absl::integer_sequence<size_t, kBucketSizes...>) {
|
||||
return ChoosePoolForAllocationSizeImpl<0, kBucketSizes...>::Fn(n);
|
||||
}
|
||||
#else
|
||||
template <typename T, typename A, typename B>
|
||||
struct IfArray {
|
||||
using Result = A;
|
||||
|
|
@ -119,30 +55,36 @@ template <typename T, typename A, typename B>
|
|||
struct IfArray<T[], A, B> {
|
||||
using Result = B;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct UnrefDestroy {
|
||||
void operator()(const Arena* arena) const;
|
||||
};
|
||||
|
||||
} // namespace arena_detail
|
||||
|
||||
class Arena {
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
// Selected pool sizes.
|
||||
// How to tune: see tools/codegen/core/optimize_arena_pool_sizes.py
|
||||
using PoolSizes = absl::integer_sequence<size_t, 80, 304, 528, 1024>;
|
||||
struct FreePoolNode {
|
||||
FreePoolNode* next;
|
||||
};
|
||||
#endif
|
||||
class ArenaFactory : public RefCounted<ArenaFactory> {
|
||||
public:
|
||||
virtual RefCountedPtr<Arena> MakeArena() = 0;
|
||||
virtual void FinalizeArena(Arena* arena) = 0;
|
||||
|
||||
MemoryAllocator& allocator() { return allocator_; }
|
||||
|
||||
protected:
|
||||
explicit ArenaFactory(MemoryAllocator allocator)
|
||||
: allocator_(std::move(allocator)) {}
|
||||
|
||||
private:
|
||||
MemoryAllocator allocator_;
|
||||
};
|
||||
|
||||
RefCountedPtr<ArenaFactory> SimpleArenaAllocator(size_t initial_size = 1024);
|
||||
|
||||
class Arena final : public RefCounted<Arena, NonPolymorphicRefCount,
|
||||
arena_detail::UnrefDestroy> {
|
||||
public:
|
||||
// Create an arena, with \a initial_size bytes in the first allocated buffer.
|
||||
static Arena* Create(size_t initial_size, MemoryAllocator* memory_allocator);
|
||||
|
||||
// Create an arena, with \a initial_size bytes in the first allocated buffer,
|
||||
// and return both a void pointer to the returned arena and a void* with the
|
||||
// first allocation.
|
||||
static std::pair<Arena*, void*> CreateWithAlloc(
|
||||
size_t initial_size, size_t alloc_size,
|
||||
MemoryAllocator* memory_allocator);
|
||||
static RefCountedPtr<Arena> Create(size_t initial_size,
|
||||
RefCountedPtr<ArenaFactory> arena_factory);
|
||||
|
||||
// Destroy all `ManagedNew` allocated objects.
|
||||
// Allows safe destruction of these objects even if they need context held by
|
||||
|
|
@ -151,9 +93,6 @@ class Arena {
|
|||
// TODO(ctiller): eliminate ManagedNew.
|
||||
void DestroyManagedNewObjects();
|
||||
|
||||
// Destroy an arena.
|
||||
void Destroy();
|
||||
|
||||
// Return the total amount of memory allocated by this arena.
|
||||
size_t TotalUsedBytes() const {
|
||||
return total_used_.load(std::memory_order_relaxed);
|
||||
|
|
@ -194,95 +133,6 @@ class Arena {
|
|||
return &p->t;
|
||||
}
|
||||
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
class PooledDeleter {
|
||||
public:
|
||||
explicit PooledDeleter(std::atomic<FreePoolNode*>* free_list)
|
||||
: free_list_(free_list) {}
|
||||
PooledDeleter() = default;
|
||||
template <typename T>
|
||||
void operator()(T* p) {
|
||||
// TODO(ctiller): promise based filter hijacks ownership of some pointers
|
||||
// to make them appear as PoolPtr without really transferring ownership,
|
||||
// by setting the arena to nullptr.
|
||||
// This is a transitional hack and should be removed once promise based
|
||||
// filter is removed.
|
||||
if (free_list_ != nullptr) {
|
||||
p->~T();
|
||||
FreePooled(p, free_list_);
|
||||
}
|
||||
}
|
||||
|
||||
bool has_freelist() const { return free_list_ != nullptr; }
|
||||
|
||||
private:
|
||||
std::atomic<FreePoolNode*>* free_list_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using PoolPtr = std::unique_ptr<T, PooledDeleter>;
|
||||
|
||||
// Make a unique_ptr to T that is allocated from the arena.
|
||||
// When the pointer is released, the memory may be reused for other
|
||||
// MakePooled(.*) calls.
|
||||
// CAUTION: The amount of memory allocated is rounded up to the nearest
|
||||
// value in Arena::PoolSizes, and so this may pessimize total
|
||||
// arena size.
|
||||
template <typename T, typename... Args>
|
||||
PoolPtr<T> MakePooled(Args&&... args) {
|
||||
auto* free_list =
|
||||
&pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())];
|
||||
return PoolPtr<T>(
|
||||
new (AllocPooled(
|
||||
sizeof(T),
|
||||
arena_detail::AllocationSizeFromObjectSize<sizeof(T)>(PoolSizes()),
|
||||
free_list)) T(std::forward<Args>(args)...),
|
||||
PooledDeleter(free_list));
|
||||
}
|
||||
|
||||
// Make a unique_ptr to an array of T that is allocated from the arena.
|
||||
// When the pointer is released, the memory may be reused for other
|
||||
// MakePooled(.*) calls.
|
||||
// One can use MakePooledArray<char> to allocate a buffer of bytes.
|
||||
// CAUTION: The amount of memory allocated is rounded up to the nearest
|
||||
// value in Arena::PoolSizes, and so this may pessimize total
|
||||
// arena size.
|
||||
template <typename T>
|
||||
PoolPtr<T[]> MakePooledArray(size_t n) {
|
||||
auto where =
|
||||
arena_detail::ChoosePoolForAllocationSize(n * sizeof(T), PoolSizes());
|
||||
if (where.pool_index == std::numeric_limits<size_t>::max()) {
|
||||
return PoolPtr<T[]>(new (Alloc(where.alloc_size)) T[n],
|
||||
PooledDeleter(nullptr));
|
||||
} else {
|
||||
return PoolPtr<T[]>(new (AllocPooled(where.alloc_size, where.alloc_size,
|
||||
&pools_[where.pool_index])) T[n],
|
||||
PooledDeleter(&pools_[where.pool_index]));
|
||||
}
|
||||
}
|
||||
|
||||
// Like MakePooled, but with manual memory management.
|
||||
// The caller is responsible for calling DeletePooled() on the returned
|
||||
// pointer, and expected to call it with the same type T as was passed to this
|
||||
// function (else the free list returned to the arena will be corrupted).
|
||||
template <typename T, typename... Args>
|
||||
T* NewPooled(Args&&... args) {
|
||||
auto* free_list =
|
||||
&pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())];
|
||||
return new (AllocPooled(
|
||||
sizeof(T),
|
||||
arena_detail::AllocationSizeFromObjectSize<sizeof(T)>(PoolSizes()),
|
||||
free_list)) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DeletePooled(T* p) {
|
||||
auto* free_list =
|
||||
&pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())];
|
||||
p->~T();
|
||||
FreePooled(p, free_list);
|
||||
}
|
||||
#else
|
||||
class PooledDeleter {
|
||||
public:
|
||||
PooledDeleter() = default;
|
||||
|
|
@ -364,9 +214,10 @@ class Arena {
|
|||
void DeletePooled(T* p) {
|
||||
delete p;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend struct arena_detail::UnrefDestroy;
|
||||
|
||||
struct Zone {
|
||||
Zone* prev;
|
||||
};
|
||||
|
|
@ -397,34 +248,12 @@ class Arena {
|
|||
// where we wish to create an arena and then perform an immediate
|
||||
// allocation.
|
||||
explicit Arena(size_t initial_size, size_t initial_alloc,
|
||||
MemoryAllocator* memory_allocator)
|
||||
: total_used_(GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_alloc)),
|
||||
initial_zone_size_(initial_size),
|
||||
memory_allocator_(memory_allocator) {}
|
||||
RefCountedPtr<ArenaFactory> arena_factory);
|
||||
|
||||
~Arena();
|
||||
|
||||
void* AllocZone(size_t size);
|
||||
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
void* AllocPooled(size_t obj_size, size_t alloc_size,
|
||||
std::atomic<FreePoolNode*>* head);
|
||||
static void FreePooled(void* p, std::atomic<FreePoolNode*>* head);
|
||||
#endif
|
||||
|
||||
void TracePoolAlloc(size_t size, void* ptr) {
|
||||
(void)size;
|
||||
(void)ptr;
|
||||
#ifdef GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
|
||||
gpr_log(GPR_ERROR, "ARENA %p ALLOC %" PRIdPTR " @ %p", this, size, ptr);
|
||||
#endif
|
||||
}
|
||||
static void TracePoolFree(void* ptr) {
|
||||
(void)ptr;
|
||||
#ifdef GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
|
||||
gpr_log(GPR_ERROR, "FREE %p", ptr);
|
||||
#endif
|
||||
}
|
||||
void Destroy() const;
|
||||
|
||||
// Keep track of the total used size. We use this in our call sizing
|
||||
// hysteresis.
|
||||
|
|
@ -438,27 +267,19 @@ class Arena {
|
|||
// last zone; the zone list is reverse-walked during arena destruction only.
|
||||
std::atomic<Zone*> last_zone_{nullptr};
|
||||
std::atomic<ManagedNewObject*> managed_new_head_{nullptr};
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
std::atomic<FreePoolNode*> pools_[PoolSizes::size()]{};
|
||||
#endif
|
||||
// The backing memory quota
|
||||
MemoryAllocator* const memory_allocator_;
|
||||
RefCountedPtr<ArenaFactory> arena_factory_;
|
||||
};
|
||||
|
||||
// Smart pointer for arenas when the final size is not required.
|
||||
struct ScopedArenaDeleter {
|
||||
void operator()(Arena* arena) { arena->Destroy(); }
|
||||
};
|
||||
using ScopedArenaPtr = std::unique_ptr<Arena, ScopedArenaDeleter>;
|
||||
inline ScopedArenaPtr MakeScopedArena(size_t initial_size,
|
||||
MemoryAllocator* memory_allocator) {
|
||||
return ScopedArenaPtr(Arena::Create(initial_size, memory_allocator));
|
||||
}
|
||||
|
||||
// Arenas form a context for activities
|
||||
template <>
|
||||
struct ContextType<Arena> {};
|
||||
|
||||
namespace arena_detail {
|
||||
inline void UnrefDestroy::operator()(const Arena* arena) const {
|
||||
arena->Destroy();
|
||||
}
|
||||
} // namespace arena_detail
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_LIB_RESOURCE_QUOTA_ARENA_H
|
||||
|
|
|
|||
|
|
@ -380,15 +380,15 @@ void Call::Run() {
|
|||
|
||||
class ChannelBasedCall : public Call {
|
||||
protected:
|
||||
ChannelBasedCall(Arena* arena, bool is_client, Timestamp send_deadline,
|
||||
RefCountedPtr<Channel> channel)
|
||||
ChannelBasedCall(RefCountedPtr<Arena> arena, bool is_client,
|
||||
Timestamp send_deadline, RefCountedPtr<Channel> channel)
|
||||
: Call(is_client, send_deadline, channel->event_engine()),
|
||||
arena_(arena),
|
||||
arena_(std::move(arena)),
|
||||
channel_(std::move(channel)) {
|
||||
DCHECK_NE(arena_, nullptr);
|
||||
DCHECK_NE(arena_.get(), nullptr);
|
||||
}
|
||||
|
||||
Arena* arena() final { return arena_; }
|
||||
Arena* arena() final { return arena_.get(); }
|
||||
|
||||
char* GetPeer() final {
|
||||
Slice peer_slice = GetPeerString();
|
||||
|
|
@ -415,18 +415,17 @@ class ChannelBasedCall : public Call {
|
|||
|
||||
void DeleteThis() {
|
||||
RefCountedPtr<Channel> channel = std::move(channel_);
|
||||
Arena* arena = arena_;
|
||||
RefCountedPtr<Arena> arena = arena_;
|
||||
this->~ChannelBasedCall();
|
||||
channel->DestroyArena(arena);
|
||||
}
|
||||
|
||||
Channel* channel() const { return channel_.get(); }
|
||||
|
||||
// Non-virtual arena accessor -- needed by PipeBasedCall
|
||||
Arena* GetArena() { return arena_; }
|
||||
Arena* GetArena() { return arena_.get(); }
|
||||
|
||||
private:
|
||||
Arena* const arena_;
|
||||
const RefCountedPtr<Arena> arena_;
|
||||
RefCountedPtr<Channel> channel_;
|
||||
};
|
||||
|
||||
|
|
@ -597,8 +596,9 @@ class FilterStackCall final : public ChannelBasedCall {
|
|||
void FinishBatch(grpc_error_handle error);
|
||||
};
|
||||
|
||||
FilterStackCall(Arena* arena, const grpc_call_create_args& args)
|
||||
: ChannelBasedCall(arena, args.server_transport_data == nullptr,
|
||||
FilterStackCall(RefCountedPtr<Arena> arena, const grpc_call_create_args& args)
|
||||
: ChannelBasedCall(std::move(arena),
|
||||
args.server_transport_data == nullptr,
|
||||
args.send_deadline, args.channel->Ref()),
|
||||
cq_(args.cq),
|
||||
stream_op_payload_(context_) {
|
||||
|
|
@ -732,7 +732,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
|
|||
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(FilterStackCall)) +
|
||||
channel_stack->call_stack_size;
|
||||
|
||||
Arena* arena = channel->CreateArena();
|
||||
RefCountedPtr<Arena> arena = channel->call_arena_allocator()->MakeArena();
|
||||
call = new (arena->Alloc(call_alloc_size)) FilterStackCall(arena, *args);
|
||||
DCHECK(FromC(call->c_ptr()) == call);
|
||||
DCHECK(FromCallStack(call->call_stack()) == call);
|
||||
|
|
@ -771,7 +771,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
|
|||
args->server->server_call_tracer_factory() != nullptr) {
|
||||
auto* server_call_tracer =
|
||||
args->server->server_call_tracer_factory()->CreateNewServerCallTracer(
|
||||
arena, args->server->channel_args());
|
||||
arena.get(), args->server->channel_args());
|
||||
if (server_call_tracer != nullptr) {
|
||||
// Note that we are setting both
|
||||
// GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE and
|
||||
|
|
@ -1906,10 +1906,12 @@ class BasicPromiseBasedCall : public ChannelBasedCall, public Party {
|
|||
public:
|
||||
using Call::arena;
|
||||
|
||||
BasicPromiseBasedCall(Arena* arena, uint32_t initial_external_refs,
|
||||
BasicPromiseBasedCall(RefCountedPtr<Arena> arena,
|
||||
uint32_t initial_external_refs,
|
||||
uint32_t initial_internal_refs,
|
||||
const grpc_call_create_args& args)
|
||||
: ChannelBasedCall(arena, args.server_transport_data == nullptr,
|
||||
: ChannelBasedCall(std::move(arena),
|
||||
args.server_transport_data == nullptr,
|
||||
args.send_deadline, args.channel->Ref()),
|
||||
Party(initial_internal_refs),
|
||||
external_refs_(initial_external_refs),
|
||||
|
|
@ -2067,7 +2069,7 @@ class BasicPromiseBasedCall : public ChannelBasedCall, public Party {
|
|||
|
||||
class PromiseBasedCall : public BasicPromiseBasedCall {
|
||||
public:
|
||||
PromiseBasedCall(Arena* arena, uint32_t initial_external_refs,
|
||||
PromiseBasedCall(RefCountedPtr<Arena> arena, uint32_t initial_external_refs,
|
||||
const grpc_call_create_args& args);
|
||||
|
||||
bool Completed() final { return finished_.IsSet(); }
|
||||
|
|
@ -2348,17 +2350,17 @@ template <typename T>
|
|||
grpc_error_handle MakePromiseBasedCall(grpc_call_create_args* args,
|
||||
grpc_call** out_call) {
|
||||
Channel* channel = args->channel.get();
|
||||
|
||||
auto* arena = channel->CreateArena();
|
||||
auto arena = channel->call_arena_allocator()->MakeArena();
|
||||
PromiseBasedCall* call = arena->New<T>(arena, args);
|
||||
*out_call = call->c_ptr();
|
||||
DCHECK(Call::FromC(*out_call) == call);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
PromiseBasedCall::PromiseBasedCall(Arena* arena, uint32_t initial_external_refs,
|
||||
PromiseBasedCall::PromiseBasedCall(RefCountedPtr<Arena> arena,
|
||||
uint32_t initial_external_refs,
|
||||
const grpc_call_create_args& args)
|
||||
: BasicPromiseBasedCall(arena, initial_external_refs,
|
||||
: BasicPromiseBasedCall(std::move(arena), initial_external_refs,
|
||||
initial_external_refs != 0 ? 1 : 0, args) {}
|
||||
|
||||
static void CToMetadata(grpc_metadata* metadata, size_t count,
|
||||
|
|
@ -2591,8 +2593,9 @@ void PublishMetadataArray(grpc_metadata_batch* md, grpc_metadata_array* array,
|
|||
#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_CLIENT_CALL
|
||||
class ClientPromiseBasedCall final : public PromiseBasedCall {
|
||||
public:
|
||||
ClientPromiseBasedCall(Arena* arena, grpc_call_create_args* args)
|
||||
: PromiseBasedCall(arena, 1, *args),
|
||||
ClientPromiseBasedCall(RefCountedPtr<Arena> arena,
|
||||
grpc_call_create_args* args)
|
||||
: PromiseBasedCall(std::move(arena), 1, *args),
|
||||
polling_entity_(
|
||||
args->cq != nullptr
|
||||
? grpc_polling_entity_create_from_pollset(
|
||||
|
|
|
|||
|
|
@ -66,21 +66,11 @@ Channel::Channel(std::string target, const ChannelArgs& channel_args)
|
|||
: target_(std::move(target)),
|
||||
channelz_node_(channel_args.GetObjectRef<channelz::ChannelNode>()),
|
||||
compression_options_(CompressionOptionsFromChannelArgs(channel_args)),
|
||||
call_size_estimator_(1024),
|
||||
allocator_(channel_args.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryOwner()) {}
|
||||
|
||||
Arena* Channel::CreateArena() {
|
||||
const size_t initial_size = call_size_estimator_.CallSizeEstimate();
|
||||
global_stats().IncrementCallInitialSize(initial_size);
|
||||
return Arena::Create(initial_size, &allocator_);
|
||||
}
|
||||
|
||||
void Channel::DestroyArena(Arena* arena) {
|
||||
call_size_estimator_.UpdateCallSizeEstimate(arena->TotalUsedBytes());
|
||||
arena->Destroy();
|
||||
}
|
||||
call_arena_allocator_(MakeRefCounted<CallArenaAllocator>(
|
||||
channel_args.GetObject<ResourceQuota>()
|
||||
->memory_quota()
|
||||
->CreateMemoryOwner(),
|
||||
1024)) {}
|
||||
|
||||
Channel::RegisteredCall* Channel::RegisterCall(const char* method,
|
||||
const char* host) {
|
||||
|
|
|
|||
|
|
@ -134,12 +134,14 @@ class Channel : public InternallyRefCounted<Channel>,
|
|||
virtual void Ping(grpc_completion_queue* cq, void* tag) = 0;
|
||||
|
||||
// TODO(roth): Remove these methods when LegacyChannel goes away.
|
||||
Arena* CreateArena();
|
||||
void DestroyArena(Arena* arena);
|
||||
virtual grpc_channel_stack* channel_stack() const { return nullptr; }
|
||||
virtual bool is_client() const { return true; }
|
||||
virtual bool is_promising() const { return true; }
|
||||
|
||||
CallArenaAllocator* call_arena_allocator() const {
|
||||
return call_arena_allocator_.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
Channel(std::string target, const ChannelArgs& channel_args);
|
||||
|
||||
|
|
@ -148,16 +150,13 @@ class Channel : public InternallyRefCounted<Channel>,
|
|||
const RefCountedPtr<channelz::ChannelNode> channelz_node_;
|
||||
const grpc_compression_options compression_options_;
|
||||
|
||||
// TODO(ctiller): move to use CallArenaAllocator
|
||||
CallSizeEstimator call_size_estimator_;
|
||||
MemoryAllocator allocator_;
|
||||
|
||||
Mutex mu_;
|
||||
// The map key needs to be owned strings rather than unowned char*'s to
|
||||
// guarantee that it outlives calls on the core channel (which may outlast
|
||||
// the C++ or other wrapped language Channel that registered these calls).
|
||||
std::map<std::pair<std::string, std::string>, RegisteredCall>
|
||||
registration_table_ ABSL_GUARDED_BY(mu_);
|
||||
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
class CallSizeEstimator {
|
||||
class CallSizeEstimator final {
|
||||
public:
|
||||
explicit CallSizeEstimator(size_t initial_estimate)
|
||||
: call_size_estimate_(initial_estimate) {}
|
||||
|
|
@ -52,19 +52,21 @@ class CallSizeEstimator {
|
|||
std::atomic<size_t> call_size_estimate_;
|
||||
};
|
||||
|
||||
class CallArenaAllocator : public RefCounted<CallArenaAllocator> {
|
||||
class CallArenaAllocator final : public ArenaFactory {
|
||||
public:
|
||||
CallArenaAllocator(MemoryAllocator allocator, size_t initial_size)
|
||||
: allocator_(std::move(allocator)), call_size_estimator_(initial_size) {}
|
||||
: ArenaFactory(std::move(allocator)),
|
||||
call_size_estimator_(initial_size) {}
|
||||
|
||||
Arena* MakeArena() {
|
||||
return Arena::Create(call_size_estimator_.CallSizeEstimate(), &allocator_);
|
||||
RefCountedPtr<Arena> MakeArena() override {
|
||||
return Arena::Create(call_size_estimator_.CallSizeEstimate(), Ref());
|
||||
}
|
||||
|
||||
void Destroy(Arena* arena) { arena->Destroy(); }
|
||||
void FinalizeArena(Arena* arena) override {
|
||||
call_size_estimator_.UpdateCallSizeEstimate(arena->TotalUsedBytes());
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryAllocator allocator_;
|
||||
CallSizeEstimator call_size_estimator_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -94,12 +94,12 @@ void ForwardCall(CallHandler call_handler, CallInitiator call_initiator) {
|
|||
|
||||
CallInitiatorAndHandler MakeCallPair(
|
||||
ClientMetadataHandle client_initial_metadata,
|
||||
grpc_event_engine::experimental::EventEngine* event_engine, Arena* arena,
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_if_arena_is_owned,
|
||||
grpc_call_context_element* legacy_context) {
|
||||
auto spine = CallSpine::Create(
|
||||
std::move(client_initial_metadata), event_engine, arena,
|
||||
std::move(call_arena_allocator_if_arena_is_owned), legacy_context);
|
||||
grpc_event_engine::experimental::EventEngine* event_engine,
|
||||
RefCountedPtr<Arena> arena, grpc_call_context_element* legacy_context) {
|
||||
CHECK_NE(arena.get(), nullptr);
|
||||
auto spine =
|
||||
CallSpine::Create(std::move(client_initial_metadata), event_engine,
|
||||
std::move(arena), legacy_context);
|
||||
return {CallInitiator(spine), UnstartedCallHandler(spine)};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -280,12 +280,12 @@ class CallSpine final : public CallSpineInterface, public Party {
|
|||
public:
|
||||
static RefCountedPtr<CallSpine> Create(
|
||||
ClientMetadataHandle client_initial_metadata,
|
||||
grpc_event_engine::experimental::EventEngine* event_engine, Arena* arena,
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_if_arena_is_owned,
|
||||
grpc_call_context_element* legacy_context) {
|
||||
return RefCountedPtr<CallSpine>(arena->New<CallSpine>(
|
||||
std::move(client_initial_metadata), event_engine, arena,
|
||||
std::move(call_arena_allocator_if_arena_is_owned), legacy_context));
|
||||
grpc_event_engine::experimental::EventEngine* event_engine,
|
||||
RefCountedPtr<Arena> arena, grpc_call_context_element* legacy_context) {
|
||||
auto* arena_ptr = arena.get();
|
||||
return RefCountedPtr<CallSpine>(arena_ptr->New<CallSpine>(
|
||||
std::move(client_initial_metadata), event_engine, std::move(arena),
|
||||
legacy_context));
|
||||
}
|
||||
|
||||
~CallSpine() override {
|
||||
|
|
@ -301,7 +301,7 @@ class CallSpine final : public CallSpineInterface, public Party {
|
|||
|
||||
Party& party() override { return *this; }
|
||||
|
||||
Arena* arena() override { return arena_; }
|
||||
Arena* arena() override { return arena_.get(); }
|
||||
|
||||
void IncrementRefCount() override { Party::IncrementRefCount(); }
|
||||
|
||||
|
|
@ -385,18 +385,15 @@ class CallSpine final : public CallSpineInterface, public Party {
|
|||
friend class Arena;
|
||||
CallSpine(ClientMetadataHandle client_initial_metadata,
|
||||
grpc_event_engine::experimental::EventEngine* event_engine,
|
||||
Arena* arena,
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator,
|
||||
RefCountedPtr<Arena> arena,
|
||||
grpc_call_context_element* legacy_context)
|
||||
: Party(1),
|
||||
arena_(std::move(arena)),
|
||||
call_filters_(std::move(client_initial_metadata)),
|
||||
arena_(arena),
|
||||
event_engine_(event_engine),
|
||||
call_arena_allocator_if_arena_is_owned_(
|
||||
std::move(call_arena_allocator)) {
|
||||
event_engine_(event_engine) {
|
||||
if (legacy_context == nullptr) {
|
||||
legacy_context_ = static_cast<grpc_call_context_element*>(
|
||||
arena->Alloc(sizeof(grpc_call_context_element) * GRPC_CONTEXT_COUNT));
|
||||
legacy_context_ = static_cast<grpc_call_context_element*>(arena_->Alloc(
|
||||
sizeof(grpc_call_context_element) * GRPC_CONTEXT_COUNT));
|
||||
memset(legacy_context_, 0,
|
||||
sizeof(grpc_call_context_element) * GRPC_CONTEXT_COUNT);
|
||||
legacy_context_is_owned_ = true;
|
||||
|
|
@ -415,7 +412,7 @@ class CallSpine final : public CallSpineInterface, public Party {
|
|||
public:
|
||||
explicit ScopedContext(CallSpine* spine)
|
||||
: ScopedActivity(spine),
|
||||
Context<Arena>(spine->arena_),
|
||||
Context<Arena>(spine->arena_.get()),
|
||||
Context<grpc_event_engine::experimental::EventEngine>(
|
||||
spine->event_engine()),
|
||||
Context<grpc_call_context_element>(spine->legacy_context_) {}
|
||||
|
|
@ -427,29 +424,23 @@ class CallSpine final : public CallSpineInterface, public Party {
|
|||
}
|
||||
|
||||
void PartyOver() override {
|
||||
Arena* a = arena_;
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_if_arena_is_owned =
|
||||
std::move(call_arena_allocator_if_arena_is_owned_);
|
||||
auto arena = arena_;
|
||||
{
|
||||
ScopedContext context(this);
|
||||
CancelRemainingParticipants();
|
||||
a->DestroyManagedNewObjects();
|
||||
arena->DestroyManagedNewObjects();
|
||||
}
|
||||
this->~CallSpine();
|
||||
if (call_arena_allocator_if_arena_is_owned != nullptr) {
|
||||
call_arena_allocator_if_arena_is_owned->Destroy(a);
|
||||
}
|
||||
}
|
||||
|
||||
const RefCountedPtr<Arena> arena_;
|
||||
// Call filters/pipes part of the spine
|
||||
CallFilters call_filters_;
|
||||
Arena* const arena_;
|
||||
// Event engine associated with this call
|
||||
grpc_event_engine::experimental::EventEngine* const event_engine_;
|
||||
// Legacy context
|
||||
// TODO(ctiller): remove
|
||||
grpc_call_context_element* legacy_context_;
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_if_arena_is_owned_;
|
||||
bool legacy_context_is_owned_;
|
||||
};
|
||||
|
||||
|
|
@ -654,9 +645,8 @@ struct CallInitiatorAndHandler {
|
|||
|
||||
CallInitiatorAndHandler MakeCallPair(
|
||||
ClientMetadataHandle client_initial_metadata,
|
||||
grpc_event_engine::experimental::EventEngine* event_engine, Arena* arena,
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_if_arena_is_owned,
|
||||
grpc_call_context_element* legacy_context);
|
||||
grpc_event_engine::experimental::EventEngine* event_engine,
|
||||
RefCountedPtr<Arena> arena, grpc_call_context_element* legacy_context);
|
||||
|
||||
template <typename CallHalf>
|
||||
auto OutgoingMessages(CallHalf h) {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ CallInitiator HijackedCall::MakeCall() {
|
|||
CallInitiator HijackedCall::MakeCallWithMetadata(
|
||||
ClientMetadataHandle metadata) {
|
||||
auto call = MakeCallPair(std::move(metadata), call_handler_.event_engine(),
|
||||
call_handler_.arena(), nullptr,
|
||||
call_handler_.arena()->Ref(),
|
||||
call_handler_.legacy_context());
|
||||
destination_->StartCall(std::move(call.handler));
|
||||
return std::move(call.initiator);
|
||||
|
|
|
|||
|
|
@ -361,10 +361,9 @@ class YodelTest : public ::testing::Test {
|
|||
}
|
||||
|
||||
auto MakeCall(ClientMetadataHandle client_initial_metadata) {
|
||||
auto* arena = state_->call_arena_allocator->MakeArena();
|
||||
return MakeCallPair(std::move(client_initial_metadata),
|
||||
state_->event_engine.get(), arena,
|
||||
state_->call_arena_allocator, nullptr);
|
||||
state_->event_engine.get(),
|
||||
state_->call_arena_allocator->MakeArena(), nullptr);
|
||||
}
|
||||
|
||||
void WaitForAllPendingWork();
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@
|
|||
namespace grpc_core {
|
||||
|
||||
TEST(CallFinalizationTest, Works) {
|
||||
auto memory_allocator = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
std::string evidence;
|
||||
TestContext<Arena> context(arena.get());
|
||||
CallFinalization finalization;
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@ class ConnectedSubchannelTest : public YodelTest {
|
|||
|
||||
CallInitiatorAndHandler MakeCall(
|
||||
ClientMetadataHandle client_initial_metadata) {
|
||||
return MakeCallPair(
|
||||
std::move(client_initial_metadata), event_engine().get(),
|
||||
call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr);
|
||||
return MakeCallPair(std::move(client_initial_metadata),
|
||||
event_engine().get(),
|
||||
SimpleArenaAllocator()->MakeArena(), nullptr);
|
||||
}
|
||||
|
||||
CallHandler TickUntilCallStarted() {
|
||||
|
|
@ -151,11 +151,6 @@ class ConnectedSubchannelTest : public YodelTest {
|
|||
}
|
||||
|
||||
std::queue<CallHandler> handlers_;
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator_ =
|
||||
MakeRefCounted<CallArenaAllocator>(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test"),
|
||||
1024);
|
||||
};
|
||||
|
||||
#define CONNECTED_SUBCHANNEL_CHANNEL_TEST(name) \
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ class LoadBalancedCallDestinationTest : public YodelTest {
|
|||
|
||||
CallInitiatorAndHandler MakeCall(
|
||||
ClientMetadataHandle client_initial_metadata) {
|
||||
return MakeCallPair(
|
||||
std::move(client_initial_metadata), event_engine().get(),
|
||||
call_arena_allocator_->MakeArena(), call_arena_allocator_, nullptr);
|
||||
return MakeCallPair(std::move(client_initial_metadata),
|
||||
event_engine().get(),
|
||||
call_arena_allocator_->MakeArena(), nullptr);
|
||||
}
|
||||
|
||||
CallHandler TickUntilCallStarted() {
|
||||
|
|
|
|||
|
|
@ -83,8 +83,7 @@ class FilterTestBase::Call::Impl
|
|||
|
||||
Call* const call_;
|
||||
std::shared_ptr<Channel::Impl> const channel_;
|
||||
ScopedArenaPtr arena_{MakeScopedArena(channel_->initial_arena_size,
|
||||
&channel_->memory_allocator)};
|
||||
RefCountedPtr<Arena> arena_ = channel_->arena_factory->MakeArena();
|
||||
bool run_call_finalization_ = false;
|
||||
CallFinalization call_finalization_;
|
||||
absl::optional<ArenaPromise<ServerMetadataHandle>> promise_;
|
||||
|
|
|
|||
|
|
@ -101,19 +101,12 @@ class FilterTestBase : public ::testing::Test {
|
|||
struct Impl {
|
||||
Impl(std::unique_ptr<ChannelFilter> filter, FilterTestBase* test)
|
||||
: filter(std::move(filter)), test(test) {}
|
||||
size_t initial_arena_size = 1024;
|
||||
MemoryAllocator memory_allocator =
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test");
|
||||
RefCountedPtr<ArenaFactory> arena_factory = SimpleArenaAllocator();
|
||||
std::unique_ptr<ChannelFilter> filter;
|
||||
FilterTestBase* const test;
|
||||
};
|
||||
|
||||
public:
|
||||
void set_initial_arena_size(size_t size) {
|
||||
impl_->initial_arena_size = size;
|
||||
}
|
||||
|
||||
Call MakeCall();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ class Fuzzer {
|
|||
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
ScopedArenaPtr arena_ = MakeScopedArena(128, &memory_allocator_);
|
||||
RefCountedPtr<Arena> arena_ = SimpleArenaAllocator(128)->MakeArena();
|
||||
std::map<int, Comparison> vectors_;
|
||||
};
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -31,20 +31,14 @@ namespace testing {
|
|||
static constexpr size_t kInitialArenaSize = 1024;
|
||||
static constexpr size_t kChunkSize = 3;
|
||||
|
||||
class ChunkedVectorTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
|
||||
TEST_F(ChunkedVectorTest, Noop) {
|
||||
auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
|
||||
TEST(ChunkedVectorTest, Noop) {
|
||||
auto arena = SimpleArenaAllocator(kInitialArenaSize)->MakeArena();
|
||||
ChunkedVector<int, kChunkSize> v(arena.get());
|
||||
EXPECT_EQ(0, v.size());
|
||||
}
|
||||
|
||||
TEST_F(ChunkedVectorTest, Stack) {
|
||||
auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
|
||||
TEST(ChunkedVectorTest, Stack) {
|
||||
auto arena = SimpleArenaAllocator(kInitialArenaSize)->MakeArena();
|
||||
ChunkedVector<int, kChunkSize> v(arena.get());
|
||||
|
||||
// Populate 2 chunks of memory, and 2/3 of a final chunk.
|
||||
|
|
@ -85,8 +79,8 @@ TEST_F(ChunkedVectorTest, Stack) {
|
|||
EXPECT_EQ(0, v.size());
|
||||
}
|
||||
|
||||
TEST_F(ChunkedVectorTest, Iterate) {
|
||||
auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
|
||||
TEST(ChunkedVectorTest, Iterate) {
|
||||
auto arena = SimpleArenaAllocator(kInitialArenaSize)->MakeArena();
|
||||
ChunkedVector<int, kChunkSize> v(arena.get());
|
||||
v.EmplaceBack(1);
|
||||
v.EmplaceBack(2);
|
||||
|
|
@ -117,8 +111,8 @@ TEST_F(ChunkedVectorTest, Iterate) {
|
|||
EXPECT_EQ(v.end(), it);
|
||||
}
|
||||
|
||||
TEST_F(ChunkedVectorTest, ConstIterate) {
|
||||
auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
|
||||
TEST(ChunkedVectorTest, ConstIterate) {
|
||||
auto arena = SimpleArenaAllocator(kInitialArenaSize)->MakeArena();
|
||||
ChunkedVector<int, kChunkSize> v(arena.get());
|
||||
v.EmplaceBack(1);
|
||||
v.EmplaceBack(2);
|
||||
|
|
@ -149,8 +143,8 @@ TEST_F(ChunkedVectorTest, ConstIterate) {
|
|||
EXPECT_EQ(v.cend(), it);
|
||||
}
|
||||
|
||||
TEST_F(ChunkedVectorTest, Clear) {
|
||||
auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
|
||||
TEST(ChunkedVectorTest, Clear) {
|
||||
auto arena = SimpleArenaAllocator(kInitialArenaSize)->MakeArena();
|
||||
ChunkedVector<int, kChunkSize> v(arena.get());
|
||||
v.EmplaceBack(1);
|
||||
EXPECT_EQ(v.size(), 1);
|
||||
|
|
@ -159,8 +153,8 @@ TEST_F(ChunkedVectorTest, Clear) {
|
|||
EXPECT_EQ(v.begin(), v.end());
|
||||
}
|
||||
|
||||
TEST_F(ChunkedVectorTest, RemoveIf) {
|
||||
auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
|
||||
TEST(ChunkedVectorTest, RemoveIf) {
|
||||
auto arena = SimpleArenaAllocator(kInitialArenaSize)->MakeArena();
|
||||
ChunkedVector<int, kChunkSize> v(arena.get());
|
||||
v.EmplaceBack(1);
|
||||
v.SetEnd(std::remove_if(v.begin(), v.end(), [](int i) { return i == 1; }));
|
||||
|
|
|
|||
|
|
@ -30,22 +30,16 @@
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
class ArenaPromiseTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
|
||||
TEST_F(ArenaPromiseTest, DefaultInitializationYieldsNoValue) {
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
TEST(ArenaPromiseTest, DefaultInitializationYieldsNoValue) {
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> context(arena.get());
|
||||
ArenaPromise<int> p;
|
||||
EXPECT_FALSE(p.has_value());
|
||||
}
|
||||
|
||||
TEST_F(ArenaPromiseTest, AllocatedWorks) {
|
||||
TEST(ArenaPromiseTest, AllocatedWorks) {
|
||||
ExecCtx exec_ctx;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> context(arena.get());
|
||||
int x = 42;
|
||||
ArenaPromise<int> p([x] { return Poll<int>(x); });
|
||||
|
|
@ -55,9 +49,9 @@ TEST_F(ArenaPromiseTest, AllocatedWorks) {
|
|||
EXPECT_EQ(p(), Poll<int>(43));
|
||||
}
|
||||
|
||||
TEST_F(ArenaPromiseTest, DestructionWorks) {
|
||||
TEST(ArenaPromiseTest, DestructionWorks) {
|
||||
ExecCtx exec_ctx;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> context(arena.get());
|
||||
auto x = std::make_shared<int>(42);
|
||||
auto p = ArenaPromise<int>([x] { return Poll<int>(*x); });
|
||||
|
|
@ -65,18 +59,18 @@ TEST_F(ArenaPromiseTest, DestructionWorks) {
|
|||
EXPECT_EQ(q(), Poll<int>(42));
|
||||
}
|
||||
|
||||
TEST_F(ArenaPromiseTest, MoveAssignmentWorks) {
|
||||
TEST(ArenaPromiseTest, MoveAssignmentWorks) {
|
||||
ExecCtx exec_ctx;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> context(arena.get());
|
||||
auto x = std::make_shared<int>(42);
|
||||
auto p = ArenaPromise<int>([x] { return Poll<int>(*x); });
|
||||
p = ArenaPromise<int>();
|
||||
}
|
||||
|
||||
TEST_F(ArenaPromiseTest, AllocatedUniquePtrWorks) {
|
||||
TEST(ArenaPromiseTest, AllocatedUniquePtrWorks) {
|
||||
ExecCtx exec_ctx;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> context(arena.get());
|
||||
std::array<int, 5> garbage = {0, 1, 2, 3, 4};
|
||||
auto freer = [garbage](int* p) { free(p + garbage[0]); };
|
||||
|
|
|
|||
|
|
@ -40,13 +40,7 @@ using testing::StrictMock;
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
class ForEachTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
|
||||
TEST_F(ForEachTest, SendThriceWithPipe) {
|
||||
TEST(ForEachTest, SendThriceWithPipe) {
|
||||
int num_received = 0;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
|
|
@ -76,12 +70,12 @@ TEST_F(ForEachTest, SendThriceWithPipe) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
Mock::VerifyAndClearExpectations(&on_done);
|
||||
EXPECT_EQ(num_received, 3);
|
||||
}
|
||||
|
||||
TEST_F(ForEachTest, SendThriceWithInterActivityPipe) {
|
||||
TEST(ForEachTest, SendThriceWithInterActivityPipe) {
|
||||
int num_received = 0;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done_sender;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done_receiver;
|
||||
|
|
@ -148,7 +142,7 @@ class MoveableUntilPolled {
|
|||
int polls_ = 0;
|
||||
};
|
||||
|
||||
TEST_F(ForEachTest, NoMoveAfterPoll) {
|
||||
TEST(ForEachTest, NoMoveAfterPoll) {
|
||||
int num_received = 0;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
|
|
@ -179,12 +173,12 @@ TEST_F(ForEachTest, NoMoveAfterPoll) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
Mock::VerifyAndClearExpectations(&on_done);
|
||||
EXPECT_EQ(num_received, 1);
|
||||
}
|
||||
|
||||
TEST_F(ForEachTest, NextResultHeldThroughCallback) {
|
||||
TEST(ForEachTest, NextResultHeldThroughCallback) {
|
||||
int num_received = 0;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
|
|
@ -230,7 +224,7 @@ TEST_F(ForEachTest, NextResultHeldThroughCallback) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
Mock::VerifyAndClearExpectations(&on_done);
|
||||
EXPECT_EQ(num_received, 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,7 @@ namespace {
|
|||
|
||||
class InterceptorListTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
ScopedArenaPtr arena_ = MakeScopedArena(1024, &memory_allocator_);
|
||||
RefCountedPtr<Arena> arena_ = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> arena_ctx_{arena_.get()};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -58,13 +58,7 @@ class Delayed {
|
|||
T x_;
|
||||
};
|
||||
|
||||
class MapPipeTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
|
||||
TEST_F(MapPipeTest, SendThriceWithPipeInterceptingReceive) {
|
||||
TEST(MapPipeTest, SendThriceWithPipeInterceptingReceive) {
|
||||
int num_received = 0;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
|
|
@ -99,12 +93,12 @@ TEST_F(MapPipeTest, SendThriceWithPipeInterceptingReceive) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
Mock::VerifyAndClearExpectations(&on_done);
|
||||
EXPECT_EQ(num_received, 3);
|
||||
}
|
||||
|
||||
TEST_F(MapPipeTest, SendThriceWithPipeInterceptingSend) {
|
||||
TEST(MapPipeTest, SendThriceWithPipeInterceptingSend) {
|
||||
int num_received = 0;
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
|
|
@ -139,7 +133,7 @@ TEST_F(MapPipeTest, SendThriceWithPipeInterceptingSend) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
Mock::VerifyAndClearExpectations(&on_done);
|
||||
EXPECT_EQ(num_received, 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,7 @@ using testing::StrictMock;
|
|||
|
||||
namespace grpc_core {
|
||||
|
||||
class PipeTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
|
||||
TEST_F(PipeTest, CanSendAndReceive) {
|
||||
TEST(PipeTest, CanSendAndReceive) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -68,10 +62,10 @@ TEST_F(PipeTest, CanSendAndReceive) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanInterceptAndMapAtSender) {
|
||||
TEST(PipeTest, CanInterceptAndMapAtSender) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -93,10 +87,10 @@ TEST_F(PipeTest, CanInterceptAndMapAtSender) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanInterceptAndMapAtReceiver) {
|
||||
TEST(PipeTest, CanInterceptAndMapAtReceiver) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -118,10 +112,10 @@ TEST_F(PipeTest, CanInterceptAndMapAtReceiver) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, InterceptionOrderingIsCorrect) {
|
||||
TEST(PipeTest, InterceptionOrderingIsCorrect) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -154,10 +148,10 @@ TEST_F(PipeTest, InterceptionOrderingIsCorrect) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanReceiveAndSend) {
|
||||
TEST(PipeTest, CanReceiveAndSend) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -178,10 +172,10 @@ TEST_F(PipeTest, CanReceiveAndSend) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanSeeClosedOnSend) {
|
||||
TEST(PipeTest, CanSeeClosedOnSend) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -208,10 +202,10 @@ TEST_F(PipeTest, CanSeeClosedOnSend) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanSeeClosedOnReceive) {
|
||||
TEST(PipeTest, CanSeeClosedOnReceive) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -240,10 +234,10 @@ TEST_F(PipeTest, CanSeeClosedOnReceive) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanCloseSend) {
|
||||
TEST(PipeTest, CanCloseSend) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -270,10 +264,10 @@ TEST_F(PipeTest, CanCloseSend) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanCloseWithErrorSend) {
|
||||
TEST(PipeTest, CanCloseWithErrorSend) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -300,10 +294,10 @@ TEST_F(PipeTest, CanCloseWithErrorSend) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanCloseWithErrorRecv) {
|
||||
TEST(PipeTest, CanCloseWithErrorRecv) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -330,10 +324,10 @@ TEST_F(PipeTest, CanCloseWithErrorRecv) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanCloseSendWithInterceptor) {
|
||||
TEST(PipeTest, CanCloseSendWithInterceptor) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -361,10 +355,10 @@ TEST_F(PipeTest, CanCloseSendWithInterceptor) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanCancelSendWithInterceptor) {
|
||||
TEST(PipeTest, CanCancelSendWithInterceptor) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -389,10 +383,10 @@ TEST_F(PipeTest, CanCancelSendWithInterceptor) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, CanFlowControlThroughManyStages) {
|
||||
TEST(PipeTest, CanFlowControlThroughManyStages) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
auto done = std::make_shared<bool>(false);
|
||||
|
|
@ -437,11 +431,11 @@ TEST_F(PipeTest, CanFlowControlThroughManyStages) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
ASSERT_TRUE(*done);
|
||||
}
|
||||
|
||||
TEST_F(PipeTest, AwaitClosedWorks) {
|
||||
TEST(PipeTest, AwaitClosedWorks) {
|
||||
StrictMock<MockFunction<void(absl::Status)>> on_done;
|
||||
EXPECT_CALL(on_done, Call(absl::OkStatus()));
|
||||
MakeActivity(
|
||||
|
|
@ -468,7 +462,7 @@ TEST_F(PipeTest, AwaitClosedWorks) {
|
|||
},
|
||||
NoWakeupScheduler(),
|
||||
[&on_done](absl::Status status) { on_done.Call(std::move(status)); },
|
||||
MakeScopedArena(1024, &memory_allocator_));
|
||||
SimpleArenaAllocator()->MakeArena());
|
||||
}
|
||||
|
||||
class FakeActivity final : public Activity {
|
||||
|
|
@ -483,7 +477,7 @@ class FakeActivity final : public Activity {
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F(PipeTest, PollAckWaitsForReadyClosed) {
|
||||
TEST(PipeTest, PollAckWaitsForReadyClosed) {
|
||||
FakeActivity().Run([]() {
|
||||
pipe_detail::Center<int> c;
|
||||
int i = 1;
|
||||
|
|
|
|||
|
|
@ -57,9 +57,8 @@ class AllocTest : public ::testing::TestWithParam<AllocShape> {};
|
|||
|
||||
TEST_P(AllocTest, Works) {
|
||||
ExecCtx exec_ctx;
|
||||
MemoryAllocator memory_allocator = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
Arena* a = Arena::Create(GetParam().initial_size, &memory_allocator);
|
||||
RefCountedPtr<Arena> a =
|
||||
SimpleArenaAllocator(GetParam().initial_size)->MakeArena();
|
||||
std::vector<void*> allocated;
|
||||
for (auto alloc : GetParam().allocs) {
|
||||
void* p = a->Alloc(alloc);
|
||||
|
|
@ -73,7 +72,6 @@ TEST_P(AllocTest, Works) {
|
|||
memset(p, 1, alloc);
|
||||
allocated.push_back(p);
|
||||
}
|
||||
a->Destroy();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
|
@ -92,33 +90,23 @@ size_t concurrent_test_iterations() {
|
|||
|
||||
typedef struct {
|
||||
gpr_event ev_start;
|
||||
Arena* arena;
|
||||
RefCountedPtr<Arena> arena;
|
||||
} concurrent_test_args;
|
||||
|
||||
class ArenaTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
TEST(ArenaTest, NoOp) { SimpleArenaAllocator()->MakeArena(); }
|
||||
|
||||
TEST_F(ArenaTest, NoOp) {
|
||||
TEST(ArenaTest, ManagedNew) {
|
||||
ExecCtx exec_ctx;
|
||||
Arena::Create(1, &memory_allocator_)->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ArenaTest, ManagedNew) {
|
||||
ExecCtx exec_ctx;
|
||||
Arena* arena = Arena::Create(1, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator(1)->MakeArena();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
arena->ManagedNew<std::unique_ptr<int>>(std::make_unique<int>(i));
|
||||
}
|
||||
arena->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ArenaTest, ConcurrentAlloc) {
|
||||
TEST(ArenaTest, ConcurrentAlloc) {
|
||||
concurrent_test_args args;
|
||||
gpr_event_init(&args.ev_start);
|
||||
args.arena = Arena::Create(1024, &memory_allocator_);
|
||||
args.arena = SimpleArenaAllocator()->MakeArena();
|
||||
|
||||
Thread thds[CONCURRENT_TEST_THREADS];
|
||||
|
||||
|
|
@ -141,14 +129,12 @@ TEST_F(ArenaTest, ConcurrentAlloc) {
|
|||
for (auto& th : thds) {
|
||||
th.Join();
|
||||
}
|
||||
|
||||
args.arena->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ArenaTest, ConcurrentManagedNew) {
|
||||
TEST(ArenaTest, ConcurrentManagedNew) {
|
||||
concurrent_test_args args;
|
||||
gpr_event_init(&args.ev_start);
|
||||
args.arena = Arena::Create(1024, &memory_allocator_);
|
||||
args.arena = SimpleArenaAllocator()->MakeArena();
|
||||
|
||||
Thread thds[CONCURRENT_TEST_THREADS];
|
||||
|
||||
|
|
@ -172,8 +158,6 @@ TEST_F(ArenaTest, ConcurrentManagedNew) {
|
|||
for (auto& th : thds) {
|
||||
th.Join();
|
||||
}
|
||||
|
||||
args.arena->Destroy();
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
|
|
@ -191,31 +175,11 @@ bool IsScribbled(Int* ints, int n, int offset) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
TEST_F(ArenaTest, PooledObjectsArePooled) {
|
||||
TEST(ArenaTest, CreateManyObjects) {
|
||||
struct TestObj {
|
||||
char a[100];
|
||||
};
|
||||
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto obj = arena->MakePooled<TestObj>();
|
||||
Scribble(obj->a, 100, 1);
|
||||
EXPECT_TRUE(IsScribbled(obj->a, 100, 1));
|
||||
void* p = obj.get();
|
||||
obj.reset();
|
||||
obj = arena->MakePooled<TestObj>();
|
||||
EXPECT_FALSE(IsScribbled(obj->a, 100, 1));
|
||||
EXPECT_EQ(p, obj.get());
|
||||
Scribble(obj->a, 100, 2);
|
||||
EXPECT_TRUE(IsScribbled(obj->a, 100, 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(ArenaTest, CreateManyObjects) {
|
||||
struct TestObj {
|
||||
char a[100];
|
||||
};
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
std::vector<Arena::PoolPtr<TestObj>> objs;
|
||||
objs.reserve(1000);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
|
|
@ -227,9 +191,9 @@ TEST_F(ArenaTest, CreateManyObjects) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(ArenaTest, CreateManyObjectsWithDestructors) {
|
||||
TEST(ArenaTest, CreateManyObjectsWithDestructors) {
|
||||
using TestObj = std::unique_ptr<int>;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
std::vector<Arena::PoolPtr<TestObj>> objs;
|
||||
objs.reserve(1000);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
|
|
@ -237,24 +201,20 @@ TEST_F(ArenaTest, CreateManyObjectsWithDestructors) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(ArenaTest, CreatePoolArray) {
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
TEST(ArenaTest, CreatePoolArray) {
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto p = arena->MakePooledArray<int>(1024);
|
||||
#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
|
||||
EXPECT_FALSE(p.get_deleter().has_freelist());
|
||||
#else
|
||||
EXPECT_TRUE(p.get_deleter().has_freelist());
|
||||
#endif
|
||||
p = arena->MakePooledArray<int>(5);
|
||||
EXPECT_TRUE(p.get_deleter().has_freelist());
|
||||
Scribble(p.get(), 5, 1);
|
||||
EXPECT_TRUE(IsScribbled(p.get(), 5, 1));
|
||||
}
|
||||
|
||||
TEST_F(ArenaTest, ConcurrentMakePooled) {
|
||||
TEST(ArenaTest, ConcurrentMakePooled) {
|
||||
concurrent_test_args args;
|
||||
gpr_event_init(&args.ev_start);
|
||||
args.arena = Arena::Create(1024, &memory_allocator_);
|
||||
args.arena = SimpleArenaAllocator()->MakeArena();
|
||||
|
||||
class BaseClass {
|
||||
public:
|
||||
|
|
@ -309,8 +269,6 @@ TEST_F(ArenaTest, ConcurrentMakePooled) {
|
|||
for (auto& th : thds2) {
|
||||
th.Join();
|
||||
}
|
||||
|
||||
args.arena->Destroy();
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -515,9 +515,7 @@ class RequestMetadataState : public RefCounted<RequestMetadataState> {
|
|||
|
||||
grpc_error_handle expected_error_;
|
||||
std::string expected_;
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
ScopedArenaPtr arena_ = MakeScopedArena(1024, &memory_allocator_);
|
||||
RefCountedPtr<Arena> arena_ = SimpleArenaAllocator()->MakeArena();
|
||||
grpc_metadata_batch md_;
|
||||
grpc_call_credentials::GetRequestMetadataArgs get_request_metadata_args_;
|
||||
grpc_polling_entity pollent_;
|
||||
|
|
|
|||
|
|
@ -51,11 +51,7 @@ char* grpc_test_fetch_oauth2_token_with_credentials(
|
|||
auto pops = grpc_polling_entity_create_from_pollset(pollset);
|
||||
bool is_done = false;
|
||||
grpc_core::Notification done;
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = grpc_core::SimpleArenaAllocator()->MakeArena();
|
||||
grpc_metadata_batch initial_metadata;
|
||||
char* token = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ TEST(ChannelInitTest, CanCreateFilterWithCall) {
|
|||
"test"),
|
||||
1024);
|
||||
auto call = MakeCallPair(Arena::MakePooled<ClientMetadata>(), nullptr,
|
||||
allocator->MakeArena(), allocator, nullptr);
|
||||
allocator->MakeArena(), nullptr);
|
||||
(*stack)->StartCall(std::move(call.handler));
|
||||
EXPECT_EQ(p, 1);
|
||||
EXPECT_EQ(handled, 1);
|
||||
|
|
|
|||
|
|
@ -37,20 +37,7 @@ namespace {
|
|||
|
||||
class CallTracerTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
memory_allocator_ = new MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test"));
|
||||
arena_ = Arena::Create(1024, memory_allocator_);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
arena_->Destroy();
|
||||
delete memory_allocator_;
|
||||
}
|
||||
|
||||
MemoryAllocator* memory_allocator_ = nullptr;
|
||||
Arena* arena_ = nullptr;
|
||||
RefCountedPtr<Arena> arena_ = SimpleArenaAllocator()->MakeArena();
|
||||
grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {};
|
||||
std::vector<std::string> annotation_logger_;
|
||||
};
|
||||
|
|
@ -65,7 +52,7 @@ TEST_F(CallTracerTest, BasicClientCallTracer) {
|
|||
}
|
||||
|
||||
TEST_F(CallTracerTest, MultipleClientCallTracers) {
|
||||
promise_detail::Context<Arena> arena_ctx(arena_);
|
||||
promise_detail::Context<Arena> arena_ctx(arena_.get());
|
||||
FakeClientCallTracer client_call_tracer1(&annotation_logger_);
|
||||
FakeClientCallTracer client_call_tracer2(&annotation_logger_);
|
||||
FakeClientCallTracer client_call_tracer3(&annotation_logger_);
|
||||
|
|
@ -80,7 +67,7 @@ TEST_F(CallTracerTest, MultipleClientCallTracers) {
|
|||
}
|
||||
|
||||
TEST_F(CallTracerTest, MultipleClientCallAttemptTracers) {
|
||||
promise_detail::Context<Arena> arena_ctx(arena_);
|
||||
promise_detail::Context<Arena> arena_ctx(arena_.get());
|
||||
FakeClientCallTracer client_call_tracer1(&annotation_logger_);
|
||||
FakeClientCallTracer client_call_tracer2(&annotation_logger_);
|
||||
FakeClientCallTracer client_call_tracer3(&annotation_logger_);
|
||||
|
|
@ -110,7 +97,7 @@ TEST_F(CallTracerTest, BasicServerCallTracerTest) {
|
|||
}
|
||||
|
||||
TEST_F(CallTracerTest, MultipleServerCallTracers) {
|
||||
promise_detail::Context<Arena> arena_ctx(arena_);
|
||||
promise_detail::Context<Arena> arena_ctx(arena_.get());
|
||||
FakeServerCallTracer server_call_tracer1(&annotation_logger_);
|
||||
FakeServerCallTracer server_call_tracer2(&annotation_logger_);
|
||||
FakeServerCallTracer server_call_tracer3(&annotation_logger_);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ class BinderTransportTest : public ::testing::Test {
|
|||
gbs->~grpc_binder_stream();
|
||||
gpr_free(gbs);
|
||||
}
|
||||
arena_->Destroy();
|
||||
}
|
||||
|
||||
void PerformStreamOp(grpc_binder_stream* gbs,
|
||||
|
|
@ -81,7 +80,7 @@ class BinderTransportTest : public ::testing::Test {
|
|||
grpc_binder_stream* gbs = static_cast<grpc_binder_stream*>(
|
||||
gpr_malloc(transport_->filter_stack_transport()->SizeOfStream()));
|
||||
transport_->filter_stack_transport()->InitStream(
|
||||
reinterpret_cast<grpc_stream*>(gbs), &ref_, nullptr, arena_);
|
||||
reinterpret_cast<grpc_stream*>(gbs), &ref_, nullptr, arena_.get());
|
||||
stream_buffer_.push_back(gbs);
|
||||
return gbs;
|
||||
}
|
||||
|
|
@ -95,12 +94,8 @@ class BinderTransportTest : public ::testing::Test {
|
|||
static void TearDownTestSuite() { grpc_shutdown(); }
|
||||
|
||||
protected:
|
||||
grpc_core::MemoryAllocator memory_allocator_ =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
grpc_core::Arena* arena_ =
|
||||
grpc_core::Arena::Create(/* initial_size = */ 1, &memory_allocator_);
|
||||
grpc_core::RefCountedPtr<grpc_core::Arena> arena_ =
|
||||
grpc_core::SimpleArenaAllocator()->MakeArena();
|
||||
grpc_core::Transport* transport_;
|
||||
grpc_stream_refcount ref_;
|
||||
std::vector<grpc_binder_stream*> stream_buffer_;
|
||||
|
|
@ -234,12 +229,6 @@ struct MakeSendInitialMetadata {
|
|||
}
|
||||
~MakeSendInitialMetadata() {}
|
||||
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
grpc_core::ScopedArenaPtr arena =
|
||||
grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch grpc_initial_metadata;
|
||||
};
|
||||
|
||||
|
|
@ -269,8 +258,6 @@ struct MakeSendTrailingMetadata {
|
|||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
grpc_core::ScopedArenaPtr arena =
|
||||
grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch grpc_trailing_metadata;
|
||||
};
|
||||
|
||||
|
|
@ -297,8 +284,6 @@ struct MakeRecvInitialMetadata {
|
|||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
grpc_core::ScopedArenaPtr arena =
|
||||
grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch grpc_initial_metadata;
|
||||
grpc_core::Notification notification;
|
||||
};
|
||||
|
|
@ -345,8 +330,6 @@ struct MakeRecvTrailingMetadata {
|
|||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
grpc_core::ScopedArenaPtr arena =
|
||||
grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch grpc_trailing_metadata;
|
||||
grpc_core::Notification notification;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -407,9 +407,7 @@ TEST(StackDataTest, InstantClientInitialMetadataReturningAbslStatus) {
|
|||
// Check promise init
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
d.filter_constructor[0].call_init(call_data, &f1);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ClientMetadata>();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// A succeeding call
|
||||
|
|
@ -467,9 +465,7 @@ TEST(StackDataTest,
|
|||
// Check promise init
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
d.filter_constructor[0].call_init(call_data, &f1);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ClientMetadata>();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// A succeeding call
|
||||
|
|
@ -526,9 +522,7 @@ TEST(StackDataTest, InstantClientInitialMetadataReturningServerMetadata) {
|
|||
// Check promise init
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
d.filter_constructor[0].call_init(call_data, &f1);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ClientMetadata>();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// A succeeding call
|
||||
|
|
@ -588,9 +582,7 @@ TEST(StackDataTest,
|
|||
// Check promise init
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
d.filter_constructor[0].call_init(call_data, &f1);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ClientMetadata>();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// A succeeding call
|
||||
|
|
@ -648,9 +640,7 @@ TEST(StackDataTest, PromiseClientInitialMetadataReturningAbslStatus) {
|
|||
// Check promise init
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
d.filter_constructor[0].call_init(call_data, &f1);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ClientMetadata>();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// A succeeding call
|
||||
|
|
@ -731,9 +721,7 @@ TEST(StackDataTest,
|
|||
// Check promise init
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
d.filter_constructor[0].call_init(call_data, &f1);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ClientMetadata>();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// A succeeding call
|
||||
|
|
@ -801,9 +789,7 @@ TEST(StackDataTest, InstantServerInitialMetadataReturningVoid) {
|
|||
EXPECT_EQ(d.server_initial_metadata.ops[0].poll, nullptr);
|
||||
EXPECT_EQ(d.server_initial_metadata.ops[0].early_destroy, nullptr);
|
||||
// Check promise init
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ServerMetadata>();
|
||||
EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
|
||||
char call_data;
|
||||
|
|
@ -838,9 +824,7 @@ TEST(StackDataTest, InstantClientToServerMessagesReturningVoid) {
|
|||
EXPECT_EQ(d.client_to_server_messages.ops[0].poll, nullptr);
|
||||
EXPECT_EQ(d.client_to_server_messages.ops[0].early_destroy, nullptr);
|
||||
// Check promise init
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto message = Arena::MakePooled<Message>(SliceBuffer(), 0);
|
||||
char call_data;
|
||||
auto r = d.client_to_server_messages.ops[0].promise_init(
|
||||
|
|
@ -873,9 +857,7 @@ TEST(StackDataTest, InstantServerToClientMessagesReturningVoid) {
|
|||
EXPECT_EQ(d.server_to_client_messages.ops[0].poll, nullptr);
|
||||
EXPECT_EQ(d.server_to_client_messages.ops[0].early_destroy, nullptr);
|
||||
// Check promise init
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto message = Arena::MakePooled<Message>(SliceBuffer(), 0);
|
||||
char call_data;
|
||||
auto r = d.server_to_client_messages.ops[0].promise_init(
|
||||
|
|
@ -908,9 +890,7 @@ TEST(StackDataTest, InstantServerTrailingMetadataReturningVoid) {
|
|||
EXPECT_EQ(d.server_trailing_metadata.ops[0].poll, nullptr);
|
||||
EXPECT_EQ(d.server_trailing_metadata.ops[0].early_destroy, nullptr);
|
||||
// Check promise init
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ServerMetadata>();
|
||||
EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
|
||||
char call_data;
|
||||
|
|
@ -948,9 +928,7 @@ TEST(StackDataTest,
|
|||
EXPECT_EQ(d.server_trailing_metadata.ops[0].poll, nullptr);
|
||||
EXPECT_EQ(d.server_trailing_metadata.ops[0].early_destroy, nullptr);
|
||||
// Check promise init
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto md = Arena::MakePooled<ServerMetadata>();
|
||||
EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
|
||||
char call_data;
|
||||
|
|
@ -1038,9 +1016,7 @@ TEST(OperationExecutorTest, InstantTwo) {
|
|||
d.filter_constructor[0].call_init(call_data1, &f1);
|
||||
d.filter_constructor[1].call_init(call_data2, &f2);
|
||||
OperationExecutor<ClientMetadataHandle> transformer;
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// First call succeeds
|
||||
auto md = Arena::MakePooled<ServerMetadata>();
|
||||
|
|
@ -1103,9 +1079,7 @@ TEST(OperationExecutorTest, PromiseTwo) {
|
|||
d.filter_constructor[0].call_init(call_data1, &f1);
|
||||
d.filter_constructor[1].call_init(call_data2, &f2);
|
||||
OperationExecutor<ClientMetadataHandle> transformer;
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
// First call succeeds after two sets of two step delays.
|
||||
auto md = Arena::MakePooled<ServerMetadata>();
|
||||
|
|
@ -1175,9 +1149,7 @@ TEST(InfallibleOperationExecutor, InstantTwo) {
|
|||
ASSERT_EQ(d.server_trailing_metadata.ops.size(), 2u);
|
||||
void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
|
||||
InfallibleOperationExecutor<ServerMetadataHandle> transformer;
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
auto md = Arena::MakePooled<ServerMetadata>();
|
||||
EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
|
||||
|
|
@ -1381,9 +1353,7 @@ TEST(CallFiltersTest, UnaryCall) {
|
|||
CallFilters::StackBuilder builder;
|
||||
builder.Add(&f1);
|
||||
builder.Add(&f2);
|
||||
auto memory_allocator =
|
||||
MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
CallFilters filters(Arena::MakePooled<ClientMetadata>());
|
||||
filters.SetStack(builder.Build());
|
||||
promise_detail::Context<Arena> ctx(arena.get());
|
||||
|
|
|
|||
|
|
@ -141,9 +141,8 @@ class ClientTransportTest : public ::testing::Test {
|
|||
}
|
||||
|
||||
auto MakeCall(ClientMetadataHandle client_initial_metadata) {
|
||||
auto* arena = call_arena_allocator_->MakeArena();
|
||||
return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
|
||||
arena, call_arena_allocator_, nullptr);
|
||||
call_arena_allocator_->MakeArena(), nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -103,9 +103,7 @@ void Run(const frame_fuzzer::Test& test) {
|
|||
LOG(INFO) << "Read frame header: " << r->ToString();
|
||||
control_data += 24;
|
||||
control_size -= 24;
|
||||
MemoryAllocator memory_allocator = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
TestContext<Arena> ctx(arena.get());
|
||||
BufferPair buffers{
|
||||
SliceBuffer(Slice::FromCopiedBuffer(control_data, control_size)),
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void AssertRoundTrips(const T& input, FrameType expected_frame_type) {
|
|||
MemoryAllocator allocator = MakeResourceQuota("test-quota")
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test-allocator");
|
||||
ScopedArenaPtr arena = MakeScopedArena(1024, &allocator);
|
||||
RefCountedPtr<Arena> arena = SimpleArenaAllocator()->MakeArena();
|
||||
auto deser =
|
||||
output.Deserialize(&hpack_parser, header.value(), absl::BitGenRef(bitgen),
|
||||
arena.get(), std::move(serialized), TestFrameLimits());
|
||||
|
|
|
|||
|
|
@ -36,16 +36,17 @@ class TransportTest : public ::testing::Test {
|
|||
return event_engine_;
|
||||
}
|
||||
|
||||
Arena* MakeArena() { return call_arena_allocator_->MakeArena(); }
|
||||
RefCountedPtr<Arena> MakeArena() {
|
||||
return call_arena_allocator_->MakeArena();
|
||||
}
|
||||
|
||||
RefCountedPtr<CallArenaAllocator> call_arena_allocator() {
|
||||
return call_arena_allocator_;
|
||||
}
|
||||
|
||||
auto MakeCall(ClientMetadataHandle client_initial_metadata) {
|
||||
auto* arena = call_arena_allocator_->MakeArena();
|
||||
return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
|
||||
arena, call_arena_allocator_, nullptr);
|
||||
MakeArena(), nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -153,12 +153,6 @@ grpc_slice EncodeHeaderIntoBytes(
|
|||
const std::vector<std::pair<std::string, std::string>>& header_fields) {
|
||||
std::unique_ptr<grpc_core::HPackCompressor> compressor =
|
||||
std::make_unique<grpc_core::HPackCompressor>();
|
||||
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch b;
|
||||
|
||||
for (const auto& field : header_fields) {
|
||||
|
|
@ -307,7 +301,6 @@ static void verify_continuation_headers(const char* key, const char* value,
|
|||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_slice_buffer output;
|
||||
grpc_metadata_batch b;
|
||||
b.Append(key, grpc_core::Slice::FromStaticString(value), CrashOnAppendError);
|
||||
|
|
@ -344,11 +337,6 @@ TEST(HpackEncoderTest, TestContinuationHeaders) {
|
|||
}
|
||||
|
||||
TEST(HpackEncoderTest, EncodeBinaryAsBase64) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch b;
|
||||
// Haiku by Bard
|
||||
b.Append("grpc-trace-bin",
|
||||
|
|
@ -374,11 +362,6 @@ TEST(HpackEncoderTest, EncodeBinaryAsBase64) {
|
|||
}
|
||||
|
||||
TEST(HpackEncoderTest, EncodeBinaryAsTrueBinary) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch b;
|
||||
// Haiku by Bard
|
||||
b.Append("grpc-trace-bin",
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ DEFINE_PROTO_FUZZER(const hpack_parser_fuzzer::Msg& msg) {
|
|||
bool can_update_max_length = true;
|
||||
bool can_add_priority = true;
|
||||
for (int i = 0; i < msg.frames_size(); i++) {
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = grpc_core::SimpleArenaAllocator()->MakeArena();
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
grpc_metadata_batch b;
|
||||
const auto& frame = msg.frames(i);
|
||||
|
|
|
|||
|
|
@ -82,9 +82,7 @@ bool IsStreamError(const absl::Status& status) {
|
|||
|
||||
absl::StatusOr<std::string> TestVector(grpc_slice_split_mode mode,
|
||||
Slice input) {
|
||||
MemoryAllocator memory_allocator = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
auto arena = SimpleArenaAllocator()->MakeArena();
|
||||
ExecCtx exec_ctx;
|
||||
grpc_slice* slices;
|
||||
size_t nslices;
|
||||
|
|
|
|||
|
|
@ -107,10 +107,6 @@ class ParseTest : public ::testing::TestWithParam<Test> {
|
|||
absl::optional<size_t> max_metadata_size,
|
||||
std::string hexstring, absl::StatusOr<std::string> expect,
|
||||
uint32_t flags) {
|
||||
MemoryAllocator memory_allocator = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test"));
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
ExecCtx exec_ctx;
|
||||
auto input = ParseHexstring(hexstring);
|
||||
grpc_slice* slices;
|
||||
|
|
|
|||
|
|
@ -117,10 +117,6 @@ void FuzzOneInput(const hpack_sync_fuzzer::Msg& msg) {
|
|||
|
||||
// STAGE 2: Decode the buffer (encode_output) into a list of headers
|
||||
HPackParser parser;
|
||||
auto memory_allocator =
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
|
||||
"test-allocator");
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator);
|
||||
ExecCtx exec_ctx;
|
||||
grpc_metadata_batch read_metadata;
|
||||
parser.BeginFrame(
|
||||
|
|
|
|||
|
|
@ -230,9 +230,8 @@ class InterceptionChainTest : public ::testing::Test {
|
|||
|
||||
// Run a call through a UnstartedCallDestination until it's complete.
|
||||
FinishedCall RunCall(UnstartedCallDestination* destination) {
|
||||
auto* arena = call_arena_allocator_->MakeArena();
|
||||
auto call = MakeCallPair(Arena::MakePooled<ClientMetadata>(), nullptr,
|
||||
arena, call_arena_allocator_, nullptr);
|
||||
call_arena_allocator_->MakeArena(), nullptr);
|
||||
Poll<ServerMetadataHandle> trailing_md;
|
||||
call.initiator.SpawnInfallible(
|
||||
"run_call", [destination, &call, &trailing_md]() mutable {
|
||||
|
|
|
|||
|
|
@ -56,24 +56,11 @@ struct StreamNetworkStateMetadataMap
|
|||
GrpcStreamNetworkState>::MetadataMap;
|
||||
};
|
||||
|
||||
class MetadataMapTest : public ::testing::Test {
|
||||
protected:
|
||||
MemoryAllocator memory_allocator_ = MemoryAllocator(
|
||||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
|
||||
};
|
||||
TEST(MetadataMapTest, Noop) { EmptyMetadataMap(); }
|
||||
|
||||
TEST_F(MetadataMapTest, Noop) {
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
EmptyMetadataMap();
|
||||
}
|
||||
TEST(MetadataMapTest, NoopWithDeadline) { TimeoutOnlyMetadataMap(); }
|
||||
|
||||
TEST_F(MetadataMapTest, NoopWithDeadline) {
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
TimeoutOnlyMetadataMap();
|
||||
}
|
||||
|
||||
TEST_F(MetadataMapTest, SimpleOps) {
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
TEST(MetadataMapTest, SimpleOps) {
|
||||
TimeoutOnlyMetadataMap map;
|
||||
EXPECT_EQ(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
|
||||
EXPECT_EQ(map.get(GrpcTimeoutMetadata()), absl::nullopt);
|
||||
|
|
@ -110,17 +97,15 @@ class FakeEncoder {
|
|||
std::string output_;
|
||||
};
|
||||
|
||||
TEST_F(MetadataMapTest, EmptyEncodeTest) {
|
||||
TEST(MetadataMapTest, EmptyEncodeTest) {
|
||||
FakeEncoder encoder;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
TimeoutOnlyMetadataMap map;
|
||||
map.Encode(&encoder);
|
||||
EXPECT_EQ(encoder.output(), "");
|
||||
}
|
||||
|
||||
TEST_F(MetadataMapTest, TimeoutEncodeTest) {
|
||||
TEST(MetadataMapTest, TimeoutEncodeTest) {
|
||||
FakeEncoder encoder;
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
TimeoutOnlyMetadataMap map;
|
||||
map.Set(GrpcTimeoutMetadata(),
|
||||
Timestamp::FromMillisecondsAfterProcessEpoch(1234));
|
||||
|
|
@ -128,13 +113,12 @@ TEST_F(MetadataMapTest, TimeoutEncodeTest) {
|
|||
EXPECT_EQ(encoder.output(), "grpc-timeout: deadline=1234\n");
|
||||
}
|
||||
|
||||
TEST_F(MetadataMapTest, NonEncodableTrait) {
|
||||
TEST(MetadataMapTest, NonEncodableTrait) {
|
||||
struct EncoderWithNoTraitEncodeFunctions {
|
||||
void Encode(const Slice&, const Slice&) {
|
||||
abort(); // should not be called
|
||||
}
|
||||
};
|
||||
auto arena = MakeScopedArena(1024, &memory_allocator_);
|
||||
StreamNetworkStateMetadataMap map;
|
||||
map.Set(GrpcStreamNetworkState(), GrpcStreamNetworkState::kNotSentOnWire);
|
||||
EXPECT_EQ(map.get(GrpcStreamNetworkState()),
|
||||
|
|
|
|||
|
|
@ -26,50 +26,36 @@
|
|||
#include "test/cpp/microbenchmarks/helpers.h"
|
||||
#include "test/cpp/util/test_config.h"
|
||||
|
||||
using grpc_core::Arena;
|
||||
|
||||
static void BM_Arena_NoOp(benchmark::State& state) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto factory = grpc_core::SimpleArenaAllocator();
|
||||
for (auto _ : state) {
|
||||
Arena::Create(state.range(0), &memory_allocator)->Destroy();
|
||||
factory->MakeArena();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Arena_NoOp)->Range(1, 1024 * 1024);
|
||||
|
||||
static void BM_Arena_ManyAlloc(benchmark::State& state) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
Arena* a = Arena::Create(state.range(0), &memory_allocator);
|
||||
auto allocator = grpc_core::SimpleArenaAllocator(state.range(0));
|
||||
auto a = allocator->MakeArena();
|
||||
const size_t realloc_after =
|
||||
1024 * 1024 * 1024 / ((state.range(1) + 15) & 0xffffff0u);
|
||||
while (state.KeepRunning()) {
|
||||
a->Alloc(state.range(1));
|
||||
// periodically recreate arena to avoid OOM
|
||||
if (state.iterations() % realloc_after == 0) {
|
||||
a->Destroy();
|
||||
a = Arena::Create(state.range(0), &memory_allocator);
|
||||
a = allocator->MakeArena();
|
||||
}
|
||||
}
|
||||
a->Destroy();
|
||||
}
|
||||
BENCHMARK(BM_Arena_ManyAlloc)->Ranges({{1, 1024 * 1024}, {1, 32 * 1024}});
|
||||
|
||||
static void BM_Arena_Batch(benchmark::State& state) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto allocator = grpc_core::SimpleArenaAllocator(state.range(0));
|
||||
for (auto _ : state) {
|
||||
Arena* a = Arena::Create(state.range(0), &memory_allocator);
|
||||
auto a = allocator->MakeArena();
|
||||
for (int i = 0; i < state.range(1); i++) {
|
||||
a->Alloc(state.range(2));
|
||||
}
|
||||
a->Destroy();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Arena_Batch)->Ranges({{1, 64 * 1024}, {1, 64}, {1, 1024}});
|
||||
|
|
@ -82,30 +68,20 @@ struct TestThingToAllocate {
|
|||
};
|
||||
|
||||
static void BM_Arena_MakePooled_Small(benchmark::State& state) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
Arena* a = Arena::Create(1024, &memory_allocator);
|
||||
auto a = grpc_core::SimpleArenaAllocator()->MakeArena();
|
||||
for (auto _ : state) {
|
||||
a->MakePooled<TestThingToAllocate>();
|
||||
}
|
||||
a->Destroy();
|
||||
}
|
||||
BENCHMARK(BM_Arena_MakePooled_Small);
|
||||
|
||||
static void BM_Arena_MakePooled3_Small(benchmark::State& state) {
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
Arena* a = Arena::Create(1024, &memory_allocator);
|
||||
auto a = grpc_core::SimpleArenaAllocator()->MakeArena();
|
||||
for (auto _ : state) {
|
||||
auto x = a->MakePooled<TestThingToAllocate>();
|
||||
auto y = a->MakePooled<TestThingToAllocate>();
|
||||
auto z = a->MakePooled<TestThingToAllocate>();
|
||||
}
|
||||
a->Destroy();
|
||||
}
|
||||
BENCHMARK(BM_Arena_MakePooled3_Small);
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ static void BM_HpackEncoderEncodeDeadline(benchmark::State& state) {
|
|||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch b;
|
||||
b.Set(grpc_core::GrpcTimeoutMetadata(),
|
||||
saved_now + grpc_core::Duration::Seconds(30));
|
||||
|
|
@ -107,11 +106,6 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State& state) {
|
|||
grpc_core::ExecCtx exec_ctx;
|
||||
static bool logged_representative_output = false;
|
||||
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch b;
|
||||
Fixture::Prepare(&b);
|
||||
|
||||
|
|
@ -345,12 +339,6 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
|
|||
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
grpc_core::HPackParser p;
|
||||
const int kArenaSize = 4096 * 4096;
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto* arena = grpc_core::Arena::Create(kArenaSize, &memory_allocator);
|
||||
grpc_core::ManualConstructor<grpc_metadata_batch> b;
|
||||
b.Init();
|
||||
p.BeginFrame(&*b, std::numeric_limits<uint32_t>::max(),
|
||||
|
|
@ -373,25 +361,11 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
|
|||
b->Clear();
|
||||
parse_vec(benchmark_slices);
|
||||
grpc_core::ExecCtx::Get()->Flush();
|
||||
// Recreate arena every 4k iterations to avoid oom
|
||||
if (0 == (state.iterations() & 0xfff)) {
|
||||
b.Destroy();
|
||||
arena->Destroy();
|
||||
arena = grpc_core::Arena::Create(kArenaSize, &memory_allocator);
|
||||
b.Init();
|
||||
p.BeginFrame(&*b, std::numeric_limits<uint32_t>::max(),
|
||||
std::numeric_limits<uint32_t>::max(),
|
||||
grpc_core::HPackParser::Boundary::None,
|
||||
grpc_core::HPackParser::Priority::None,
|
||||
grpc_core::HPackParser::LogInfo{
|
||||
1, grpc_core::HPackParser::LogInfo::kHeaders, false});
|
||||
}
|
||||
}
|
||||
// Clean up
|
||||
b.Destroy();
|
||||
for (auto slice : init_slices) grpc_slice_unref(slice);
|
||||
for (auto slice : benchmark_slices) grpc_slice_unref(slice);
|
||||
arena->Destroy();
|
||||
}
|
||||
|
||||
namespace hpack_parser_fixtures {
|
||||
|
|
@ -405,12 +379,6 @@ class FromEncoderFixture {
|
|||
private:
|
||||
static std::vector<grpc_slice> Generate(int iteration) {
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
|
||||
grpc_core::MemoryAllocator memory_allocator =
|
||||
grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
|
||||
->memory_quota()
|
||||
->CreateMemoryAllocator("test"));
|
||||
auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
|
||||
grpc_metadata_batch b;
|
||||
EncoderFixture::Prepare(&b);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue