Skip to content

quiche: Implement QuicStreamBufferAllocator#6550

Merged
jmarantz merged 6 commits intoenvoyproxy:masterfrom
danzh2010:allocator
Apr 12, 2019
Merged

quiche: Implement QuicStreamBufferAllocator#6550
jmarantz merged 6 commits intoenvoyproxy:masterfrom
danzh2010:allocator

Conversation

@danzh2010
Copy link
Contributor

@danzh2010 danzh2010 commented Apr 10, 2019

Implement this API with default SimpleBufferAllocator which use bare new and delete. In light of flag-enabled tcmalloc support, the default implementation will use tcmalloc underneath.

Roll up quiche tar ball to ba6354aa1b39f3d9788ead909ad3e678ac863938

Risk Level: low, not in use
Testing: Added simple test in test/extensions/quic_listeners/quiche/platform:quic_platform_test
Part of #2557

Signed-off-by: Dan Zhang <danzh@google.com>
@danzh2010
Copy link
Contributor Author

/assign @wu-bin @jmarantz

wu-bin
wu-bin previously approved these changes Apr 11, 2019
Copy link
Contributor

@wu-bin wu-bin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says backed by tcmalloc, but it actually just uses the standard malloc/free functions, which may or may not be tcmalloc underneath?

Overall LGTM except some nits.

# Static snapshot of https://quiche.googlesource.com/quiche/+archive/4fbea5de9afdf30611b27afd54c45a596944f9c2.tar.gz
sha256 = "2cf9f5ea62a03ca0d8773fe4f56949b72c28ac5b1bcf43d850a571f4e32add2a",
urls = ["https://storage.googleapis.com/quiche-envoy-integration/4fbea5de9afdf30611b27afd54c45a596944f9c2.tar.gz"],
# Static snapshot of https://quiche.googlesource.com/quiche/+archive/553a966443258b103c97326f94b53b03b933361d.tar.gz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help me update it to a version at or after https://quiche.googlesource.com/quiche/+/a27fd44c5c53a67f3fa772b805363eff039411d5?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

)

cc_library(
name = "quic_buffer_allocator_interface_lib",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about "quic_buffer_allocator_lib", which is the name used internally?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 -- most build targets in envoy end with "_lib" or "_interface", not both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// consumed or referenced directly by other Envoy code. It serves purely as a
// porting layer for QUICHE.

#include "quiche/quic/core/quic_buffer_allocator.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#include <stdlib.h> for malloc&free.

Copy link
Contributor

@jmarantz jmarantz Apr 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or <cstdlib>, which is guaranteed idempotent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

jmarantz
jmarantz previously approved these changes Apr 11, 2019
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great modulo nits.

public:
~QuicStreamBufferAllocatorImpl() override {}

char* New(size_t size) override { return static_cast<char*>(malloc(size)); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

above these put // QuickBufferAllocator per envoy convention.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

char* p = allocator.New(1024);
EXPECT_NE(nullptr, p);
memset(p, 'a', 1024);
allocator.Delete(p);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also in this test ensure that the total allocated bytes was the same before and after this delete, via Memory::Stats::totalCurrentlyAllocated() before and after. See test/common/stats/thread_local_store_test.cc , test HeapStatsThreadLocalStoreTest.MemoryWithoutTls for an example. Only do that test if TestUtil::hasDeterministicMallocStats() is true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@jmarantz
Copy link
Contributor

@wu-bin that's the way tcmalloc works: it overrides malloc and free as well as operator new and delete.

It's worth noting that compiling with tcmalloc enabled is controlled by bazel flags, and I think it might not be enabled on some platform (Mac?)

@wu-bin
Copy link
Contributor

wu-bin commented Apr 11, 2019

@wu-bin that's the way tcmalloc works: it overrides malloc and free as well as operator new and delete.

@jmarantz That's true, but other memory allocators also overrides malloc/free etc.

It's worth noting that compiling with tcmalloc enabled is controlled by bazel flags, and I think it might not be enabled on some platform (Mac?)

@jmarantz
Copy link
Contributor

@wu-bin RE "other memory allocators" -- you're right of course :) The implementation here doesn't really depend on tcmalloc and doesn't claim it does, except in the PR description. It's just delegating to the system memory allocator, which seems fine to me. @danzh2010 maybe just change the description to reflect that?

@danzh2010
Copy link
Contributor Author

@wu-bin that's the way tcmalloc works: it overrides malloc and free as well as operator new and delete.
Quic has another allcator: QuicSimpleBufferAllocator which use bare ::new and ::delete. Could this two ends up with doing the same thing underneath?

Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
@danzh2010 danzh2010 dismissed stale reviews from jmarantz and wu-bin via 1591f79 April 11, 2019 16:10
Copy link
Contributor Author

@danzh2010 danzh2010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the discussion about tcmalloc, it seems that the simplest way is to use quic's SimpleBufferAllocator as the impl. If tcmalloc turns out not to be sufficient, we can consider other buffer pool later.

)

cc_library(
name = "quic_buffer_allocator_interface_lib",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

# Static snapshot of https://quiche.googlesource.com/quiche/+archive/4fbea5de9afdf30611b27afd54c45a596944f9c2.tar.gz
sha256 = "2cf9f5ea62a03ca0d8773fe4f56949b72c28ac5b1bcf43d850a571f4e32add2a",
urls = ["https://storage.googleapis.com/quiche-envoy-integration/4fbea5de9afdf30611b27afd54c45a596944f9c2.tar.gz"],
# Static snapshot of https://quiche.googlesource.com/quiche/+archive/553a966443258b103c97326f94b53b03b933361d.tar.gz
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// consumed or referenced directly by other Envoy code. It serves purely as a
// porting layer for QUICHE.

#include "quiche/quic/core/quic_buffer_allocator.h"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

public:
~QuicStreamBufferAllocatorImpl() override {}

char* New(size_t size) override { return static_cast<char*>(malloc(size)); }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

char* p = allocator.New(1024);
EXPECT_NE(nullptr, p);
memset(p, 'a', 1024);
allocator.Delete(p);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Dan Zhang <danzh@google.com>
jmarantz
jmarantz previously approved these changes Apr 11, 2019
bool deterministic_stats = Envoy::Stats::TestUtil::hasDeterministicMallocStats();
size_t start_mem;
if (deterministic_stats) {
start_mem = Envoy::Memory::Stats::totalCurrentlyAllocated();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well just assign start_mem conditionally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

size_t start_mem;
if (deterministic_stats) {
start_mem = Envoy::Memory::Stats::totalCurrentlyAllocated();
std::cerr << "start mem " << start_mem << "\n";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dd

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Dan Zhang <danzh@google.com>
@danzh2010
Copy link
Contributor Author

/assign @mattklein123

TEST_F(QuicPlatformTest, TestEnvoyQuicBufferAllocator) {
bool deterministic_stats = Envoy::Stats::TestUtil::hasDeterministicMallocStats();
const size_t start_mem =
deterministic_stats ? Envoy::Memory::Stats::totalCurrentlyAllocated() : 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually you don't need to conditionalize this; totalCurrentlyAllocated() will return 0 if deterministic_stats is false.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Dan Zhang <danzh@google.com>
@jmarantz jmarantz merged commit 000d278 into envoyproxy:master Apr 12, 2019
@danzh2010 danzh2010 changed the title Implement QuicStreamBufferAllocator quiche: Implement QuicStreamBufferAllocator Apr 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants