diff --git a/tcmalloc/internal/BUILD b/tcmalloc/internal/BUILD index 8aa66b1ae..bb3d562ec 100644 --- a/tcmalloc/internal/BUILD +++ b/tcmalloc/internal/BUILD @@ -1255,6 +1255,7 @@ cc_test( ":residency", "//tcmalloc:malloc_extension", "//tcmalloc/internal:profile_cc_proto", + "//tcmalloc/testing:testutil", "@com_google_absl//absl/base", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", diff --git a/tcmalloc/internal/CMakeLists.txt b/tcmalloc/internal/CMakeLists.txt index b6bc8e9ea..9a1cdf1fb 100644 --- a/tcmalloc/internal/CMakeLists.txt +++ b/tcmalloc/internal/CMakeLists.txt @@ -1288,6 +1288,7 @@ tcmalloc_cc_test( "tcmalloc::internal_residency" "tcmalloc::malloc_extension" "tcmalloc::tcmalloc" + "tcmalloc::testing_testutil" ) tcmalloc_cc_test( diff --git a/tcmalloc/internal/profile_builder.cc b/tcmalloc/internal/profile_builder.cc index 69a896655..74db047fe 100644 --- a/tcmalloc/internal/profile_builder.cc +++ b/tcmalloc/internal/profile_builder.cc @@ -30,6 +30,7 @@ #include "absl/types/span.h" #include "tcmalloc/internal/compressibility.h" #include "tcmalloc/internal/pageflags.h" +#include "tcmalloc/internal_malloc_extension.h" #include "tcmalloc/malloc_extension.h" #if defined(__linux__) @@ -882,6 +883,9 @@ absl::StatusOr> MakeProfileProto( const ::tcmalloc::Profile& profile, PageFlagsBase* pageflags, Residency* residency) { if (profile.Type() == ProfileType::kDoNotUse) { + if (MallocExtension::GetProfileSamplingInterval() == 0) { + return absl::NotFoundError("Profile sampling is disabled"); + } #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ defined(ABSL_HAVE_LEAK_SANITIZER) || \ defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) diff --git a/tcmalloc/internal/profile_builder_test.cc b/tcmalloc/internal/profile_builder_test.cc index e453311a6..5fd7fd341 100644 --- a/tcmalloc/internal/profile_builder_test.cc +++ b/tcmalloc/internal/profile_builder_test.cc @@ -55,6 +55,7 @@ #include "tcmalloc/internal/residency.h" #include "tcmalloc/internal_malloc_extension.h" #include "tcmalloc/malloc_extension.h" +#include "tcmalloc/testing/testutil.h" namespace tcmalloc { namespace tcmalloc_internal { @@ -1658,6 +1659,23 @@ TEST(BuildId, ZeroOneAndCorruptAlignment) { EXPECT_EQ(GetBuildId(&info), ""); } +TEST(ProfileBuilderTest, DisabledSamplingReturnsNotFound) { + if (MallocExtension::GetProfileSamplingInterval() < 0) { + GTEST_SKIP() << "TCMalloc is not linked in this build configuration"; + } + ScopedProfileSamplingInterval scoped_interval(0); + + Profile heap_profile = MallocExtension::SnapshotCurrent(ProfileType::kHeap); + EXPECT_EQ(heap_profile.Type(), ProfileType::kDoNotUse); + EXPECT_EQ(MakeProfileProto(heap_profile).status().code(), + absl::StatusCode::kNotFound); + + Profile alloc_profile = MallocExtension::StartAllocationProfiling().Stop(); + EXPECT_EQ(alloc_profile.Type(), ProfileType::kDoNotUse); + EXPECT_EQ(MakeProfileProto(alloc_profile).status().code(), + absl::StatusCode::kNotFound); +} + } // namespace } // namespace tcmalloc_internal } // namespace tcmalloc diff --git a/tcmalloc/tcmalloc.cc b/tcmalloc/tcmalloc.cc index a46da909c..9c737ebba 100644 --- a/tcmalloc/tcmalloc.cc +++ b/tcmalloc/tcmalloc.cc @@ -290,6 +290,9 @@ extern "C" size_t TCMalloc_Internal_GetStats(char* buffer, extern "C" const ProfileBase* MallocExtension_Internal_SnapshotCurrent( ProfileType type) { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } switch (type) { case ProfileType::kHeap: return DumpHeapProfile(tc_globals).release(); @@ -302,17 +305,26 @@ extern "C" const ProfileBase* MallocExtension_Internal_SnapshotCurrent( extern "C" AllocationProfilingTokenBase* MallocExtension_Internal_StartAllocationProfiling() { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } return new AllocationSample(&tc_globals.allocation_samples, absl::Now()); } extern "C" tcmalloc_internal::AllocationProfilingTokenBase* MallocExtension_Internal_StartLifetimeProfiling() { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } return new deallocationz::DeallocationSample(&tc_globals.deallocation_samples, deallocationz::Mode::kLifetimes); } extern "C" tcmalloc_internal::AllocationProfilingTokenBase* MallocExtension_Internal_StartEventTracing() { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } return new deallocationz::DeallocationSample( &tc_globals.deallocation_samples, deallocationz::Mode::kEventTrace); }