oversize_threshold.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include "test/jemalloc_test.h"
  2. #include "jemalloc/internal/ctl.h"
  3. static void
  4. arena_mallctl(const char *mallctl_str, unsigned arena, void *oldp,
  5. size_t *oldlen, void *newp, size_t newlen) {
  6. int err;
  7. char buf[100];
  8. malloc_snprintf(buf, sizeof(buf), mallctl_str, arena);
  9. err = mallctl(buf, oldp, oldlen, newp, newlen);
  10. expect_d_eq(0, err, "Mallctl failed; %s", buf);
  11. }
  12. TEST_BEGIN(test_oversize_threshold_get_set) {
  13. int err;
  14. size_t old_threshold;
  15. size_t new_threshold;
  16. size_t threshold_sz = sizeof(old_threshold);
  17. unsigned arena;
  18. size_t arena_sz = sizeof(arena);
  19. err = mallctl("arenas.create", (void *)&arena, &arena_sz, NULL, 0);
  20. expect_d_eq(0, err, "Arena creation failed");
  21. /* Just a write. */
  22. new_threshold = 1024 * 1024;
  23. arena_mallctl("arena.%u.oversize_threshold", arena, NULL, NULL,
  24. &new_threshold, threshold_sz);
  25. /* Read and write */
  26. new_threshold = 2 * 1024 * 1024;
  27. arena_mallctl("arena.%u.oversize_threshold", arena, &old_threshold,
  28. &threshold_sz, &new_threshold, threshold_sz);
  29. expect_zu_eq(1024 * 1024, old_threshold, "Should have read old value");
  30. /* Just a read */
  31. arena_mallctl("arena.%u.oversize_threshold", arena, &old_threshold,
  32. &threshold_sz, NULL, 0);
  33. expect_zu_eq(2 * 1024 * 1024, old_threshold, "Should have read old value");
  34. }
  35. TEST_END
  36. static size_t max_purged = 0;
  37. static bool
  38. purge_forced_record_max(extent_hooks_t* hooks, void *addr, size_t sz,
  39. size_t offset, size_t length, unsigned arena_ind) {
  40. if (length > max_purged) {
  41. max_purged = length;
  42. }
  43. return false;
  44. }
  45. static bool
  46. dalloc_record_max(extent_hooks_t *extent_hooks, void *addr, size_t sz,
  47. bool comitted, unsigned arena_ind) {
  48. if (sz > max_purged) {
  49. max_purged = sz;
  50. }
  51. return false;
  52. }
  53. extent_hooks_t max_recording_extent_hooks;
  54. TEST_BEGIN(test_oversize_threshold) {
  55. max_recording_extent_hooks = ehooks_default_extent_hooks;
  56. max_recording_extent_hooks.purge_forced = &purge_forced_record_max;
  57. max_recording_extent_hooks.dalloc = &dalloc_record_max;
  58. extent_hooks_t *extent_hooks = &max_recording_extent_hooks;
  59. int err;
  60. unsigned arena;
  61. size_t arena_sz = sizeof(arena);
  62. err = mallctl("arenas.create", (void *)&arena, &arena_sz, NULL, 0);
  63. expect_d_eq(0, err, "Arena creation failed");
  64. arena_mallctl("arena.%u.extent_hooks", arena, NULL, NULL, &extent_hooks,
  65. sizeof(extent_hooks));
  66. /*
  67. * This test will fundamentally race with purging, since we're going to
  68. * check the dirty stats to see if our oversized allocation got purged.
  69. * We don't want other purging to happen accidentally. We can't just
  70. * disable purging entirely, though, since that will also disable
  71. * oversize purging. Just set purging intervals to be very large.
  72. */
  73. ssize_t decay_ms = 100 * 1000;
  74. ssize_t decay_ms_sz = sizeof(decay_ms);
  75. arena_mallctl("arena.%u.dirty_decay_ms", arena, NULL, NULL, &decay_ms,
  76. decay_ms_sz);
  77. arena_mallctl("arena.%u.muzzy_decay_ms", arena, NULL, NULL, &decay_ms,
  78. decay_ms_sz);
  79. /* Clean everything out. */
  80. arena_mallctl("arena.%u.purge", arena, NULL, NULL, NULL, 0);
  81. max_purged = 0;
  82. /* Set threshold to 1MB. */
  83. size_t threshold = 1024 * 1024;
  84. size_t threshold_sz = sizeof(threshold);
  85. arena_mallctl("arena.%u.oversize_threshold", arena, NULL, NULL,
  86. &threshold, threshold_sz);
  87. /* Allocating and freeing half a megabyte should leave them dirty. */
  88. void *ptr = mallocx(512 * 1024, MALLOCX_ARENA(arena));
  89. dallocx(ptr, MALLOCX_TCACHE_NONE);
  90. if (!is_background_thread_enabled()) {
  91. expect_zu_lt(max_purged, 512 * 1024, "Expected no 512k purge");
  92. }
  93. /* Purge again to reset everything out. */
  94. arena_mallctl("arena.%u.purge", arena, NULL, NULL, NULL, 0);
  95. max_purged = 0;
  96. /*
  97. * Allocating and freeing 2 megabytes should have them purged because of
  98. * the oversize threshold.
  99. */
  100. ptr = mallocx(2 * 1024 * 1024, MALLOCX_ARENA(arena));
  101. dallocx(ptr, MALLOCX_TCACHE_NONE);
  102. expect_zu_ge(max_purged, 2 * 1024 * 1024, "Expected a 2MB purge");
  103. }
  104. TEST_END
  105. int
  106. main(void) {
  107. return test_no_reentrancy(
  108. test_oversize_threshold_get_set,
  109. test_oversize_threshold);
  110. }