jemalloc_nodump_allocator.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #pragma once
  6. #include <atomic>
  7. #include <vector>
  8. #include "port/jemalloc_helper.h"
  9. #include "port/port.h"
  10. #include "rocksdb/memory_allocator.h"
  11. #include "util/thread_local.h"
  12. #include "utilities/memory_allocators.h"
  13. #if defined(ROCKSDB_JEMALLOC) && defined(ROCKSDB_PLATFORM_POSIX)
  14. #include <sys/mman.h>
  15. #if (JEMALLOC_VERSION_MAJOR >= 5) && defined(MADV_DONTDUMP)
  16. #define ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  17. #endif // (JEMALLOC_VERSION_MAJOR >= 5) && MADV_DONTDUMP
  18. #endif // ROCKSDB_JEMALLOC && ROCKSDB_PLATFORM_POSIX
  19. namespace ROCKSDB_NAMESPACE {
  20. // Allocation requests are randomly sharded across
  21. // `JemallocAllocatorOptions::num_arenas` arenas to reduce contention on per-
  22. // arena mutexes.
  23. class JemallocNodumpAllocator : public BaseMemoryAllocator {
  24. public:
  25. explicit JemallocNodumpAllocator(const JemallocAllocatorOptions& options);
  26. #ifdef ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  27. ~JemallocNodumpAllocator();
  28. #endif // ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  29. static const char* kClassName() { return "JemallocNodumpAllocator"; }
  30. const char* Name() const override { return kClassName(); }
  31. static bool IsSupported() {
  32. std::string unused;
  33. return IsSupported(&unused);
  34. }
  35. static bool IsSupported(std::string* why);
  36. bool IsMutable() const { return !init_; }
  37. Status PrepareOptions(const ConfigOptions& config_options) override;
  38. #ifdef ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  39. void* Allocate(size_t size) override;
  40. void Deallocate(void* p) override;
  41. size_t UsableSize(void* p, size_t allocation_size) const override;
  42. #endif // ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  43. private:
  44. #ifdef ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  45. Status InitializeArenas();
  46. uint32_t GetArenaIndex() const;
  47. // Custom alloc hook to replace jemalloc default alloc.
  48. static void* Alloc(extent_hooks_t* extent, void* new_addr, size_t size,
  49. size_t alignment, bool* zero, bool* commit,
  50. unsigned arena_ind);
  51. // Destroy arena on destruction of the allocator, or on failure.
  52. static Status DestroyArena(uint32_t arena_index);
  53. // Destroy tcache on destruction of the allocator, or thread exit.
  54. static void DestroyThreadSpecificCache(void* ptr);
  55. // Get or create tcache. Return flag suitable to use with `mallocx`:
  56. // either MALLOCX_TCACHE_NONE or MALLOCX_TCACHE(tc).
  57. int GetThreadSpecificCache(size_t size);
  58. #endif // ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  59. JemallocAllocatorOptions options_;
  60. #ifdef ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  61. // A function pointer to jemalloc default alloc. Use atomic to make sure
  62. // NewJemallocNodumpAllocator is thread-safe.
  63. //
  64. // Hack: original_alloc_ needs to be static for Alloc() to access it.
  65. // alloc needs to be static to pass to jemalloc as function pointer. We can
  66. // use a single process-wide value as long as we assume that any newly created
  67. // arena has the same original value in its `alloc` function pointer.
  68. static std::atomic<extent_alloc_t*> original_alloc_;
  69. // Custom hooks has to outlive corresponding arena.
  70. std::vector<std::unique_ptr<extent_hooks_t>> per_arena_hooks_;
  71. // Hold thread-local tcache index.
  72. ThreadLocalPtr tcache_;
  73. std::vector<uint32_t> arena_indexes_;
  74. #endif // ROCKSDB_JEMALLOC_NODUMP_ALLOCATOR
  75. bool init_ = false;
  76. };
  77. } // namespace ROCKSDB_NAMESPACE