-
Notifications
You must be signed in to change notification settings - Fork 24
Fix bug in small allocator in case of small slab_alloc_factor #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bug in small allocator in case of small slab_alloc_factor #27
Conversation
caed2ff
to
a2bd37d
Compare
I didn't look at the patch carefully, but generally we split bugfix and optimizations into separate commits. From this commit message I see that you fixed the bug and did an optimization. Can you split it? |
Ok! Now I am testing the performance of my changes, if it turns out that it is lower than it was before, then I will only fix the bug. If the performance is better, I will split the patch into several parts. |
6ec1f65
to
09d459a
Compare
09d459a
to
30995ca
Compare
perf/small_alloc_perf.c
Outdated
static inline | ||
long long int timediff(struct timespec *tm1, struct timespec *tm2) | ||
{ | ||
return NANOSEC_PER_SEC * (tm2->tv_sec - tm1->tv_sec) + (tm2->tv_nsec - tm1->tv_nsec); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you declare to return value as long long you should cast to long long before multiplication.
Imagine a system that has time_t = int = long = int32_t, long long = int64_t.
NANOSEC_PER_SEC is int32, tm2->tv_sec is int32, their product could overflow.
I would define NANOSEC_PER_SEC as const unsigned long long, that would be enough.
perf/small_alloc_perf.c
Outdated
OBJECTS_MAX = 1000 | ||
}; | ||
|
||
#define SLAB_SIZE_MIN 4 * 1024 * 1024 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use macros as constants.
Usually we use enums, I prerer static const (I like static const has a explicit type).
perf/small_alloc_perf.c
Outdated
} else { | ||
size = floor(256 * pow(pow_factor, pos)); | ||
} | ||
fail_unless(size > 0 && size <= size_max); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove all consistency check in perf test.
perf/small_alloc_perf.c
Outdated
{ | ||
struct timespec tm1, tm2; | ||
if(human) { | ||
fprintf(stderr, "| SMALL RANDOM ALLOCATION RESULT TABLE |\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually limit code width with 80 symbols. Even in tests.
perf/small_alloc_perf.c
Outdated
slab_arena_create(&arena, "a, 0, slab_size, MAP_PRIVATE); | ||
slab_cache_create(&cache, &arena); | ||
if (human) { | ||
fprintf(stderr, "|__________________________________|_________________________________|\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the output!
perf/small_alloc_perf.c
Outdated
fprintf(stderr, "%s\n", json_output); | ||
} | ||
return EXIT_SUCCESS; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It says that there is no newline at the end of file. It's better to avoid it.
perf/small_alloc_perf.c
Outdated
if (human) { | ||
fprintf(stderr, "| LARGE RANDOM ALLOCATION RESULT TABLE |\n"); | ||
fprintf(stderr, "|____________________________________________________________________|\n"); | ||
fprintf(stderr, "| alloc_factor | time, s |\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I see in seconds all periods are very small, like 0.007
. I think we should measure time in milliseconds.
small/small.c
Outdated
factor_tree_new(&alloc->factor_pools); | ||
(void) factor_pool_create(alloc, NULL, alloc->objsize_max); | ||
small_class_create(&alloc->small_class, sizeof(intptr_t), alloc->factor, objsize_min); | ||
(void) factor_pool_create(alloc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need (void)
cast?
small/small.c
Outdated
*/ | ||
return upper_bound; | ||
size_t objsize = 0; | ||
for (alloc->factor_pool_cache_size = 0; objsize < alloc->objsize_max && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make a new line after ;
. I've just started to write a review comment because I didn't noticed objsize < alloc->objsize_max
condition.
725b4e8
to
47aea0a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except commit about CentOS6 built. It's not relevant to this task and must be linked to another issue.
7b1a812
to
6bb3dfc
Compare
Since fcac155 mempool.c depends on trivia/util.h, that is not a part of small library but a part of tarantool. Actually there's only one thing that is needed from the header - alignof macro. Extract it and make small library independent from tarantool. This issue has been fixed but this patch is more correct
b8224e8
to
e6b5807
Compare
89ef1fe
to
bdbe73c
Compare
small_alloc uses a collection of mempools of different sizes. If small_alloc stores all mempools in an array then it have to determine an offset in that array where the most suitable mempool is. Let's name the offset as 'size class' and the size that the corresponding mempool allocates as 'class size'. Historically the class sizes grow incrementally up to some point and then (at some size class) grow exponentially with user-provided factor. Apart from incremental part the exponential part is not very obvious. Binary search and floating-point logarithm could be used for size class determination but both approaches seem to be too slow. This patch implements faster size class evaluation based on integral operations. Part of #5216
In previous version allocator created new pool if necessary and inserted it in the pools tree. Now we allocate pools on the stage of allocator creation according alloc_factor. We use small_alloc class for this purpose also we use it to find necessary pool when we alloc memory. This is faster then previous allocator behavior and also fixes #5216. Closes #5216
bdbe73c
to
e78e5a3
Compare
In case of small slab_alloc_factor, factor_pool_cache
array have no enought place. This caused us to use a pool
with incorrect object sizes. This patch changed allocator
behavior, now we allocate pools on the stage of allocator
creation. Also we search for the desired pool using binary
search in an ordered array, which is generally faster
than searching in a red-black tree.
Closes #5216