Skip to content
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

[RDY] Use jemalloc instead of libc allocator #2415

Merged
merged 5 commits into from Apr 13, 2015

Conversation

tarruda
Copy link
Member

@tarruda tarruda commented Apr 12, 2015

  • Add free wrapper to memory.c(xfree). Required for customizing the memory allocator.
  • Remove code that uses memory pools, use xmalloc/xfree instead. This simplifies code and memory caching can still be implemented in the allocator layer(see below)
  • Add option to use jemalloc instead of libc allocator

I'm doing this more in preparation for #2371 which will require thread safety when dealing with memory allocated for queued events(memory pools would need to be explicitly synchronized, increasing complexity even more), but it should also improve overall allocation/deallocation efficiency due to reduced fragmentation and jemalloc's thread cache for small objects.

Could possibly fix #650, (cc @aktau)

@marvim marvim added the RFC label Apr 12, 2015
@justinmk justinmk added the refactor changes that are not features or bugfixes label Apr 12, 2015
/// free wrapper that returns delegates to the backing memory manager
void xfree(void *ptr)
{
free(ptr);
Copy link
Member

Choose a reason for hiding this comment

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

What's the purpose of xfree(), if we redefine free()? Is the plan to call je_* explicitly from the xfoo family, in the future?

Copy link
Member Author

Choose a reason for hiding this comment

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

In this module, free is only a placeholder for the actual free implementation(which is je_free when USE_JEMALLOC is defined). We still need a fixed function address for the other modules to link against. Redefining free as a macro globally is definitely not a good approach(we lose sanity when setting breakpoints, for example)

Is the plan to call je_* explicitly from the xfoo family, in the future?

No, but we could eventually use this as a slot for extra deallocation logic. For example, see how redis keeps track of how much memory is currently used in zmalloc.c.

Copy link
Member

Choose a reason for hiding this comment

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

We still need a fixed function address for the other modules to link against. Redefining free as a macro globally is definitely not a good approach(we lose sanity when setting breakpoints, for example)

That makes perfect sense, thanks.

@tarruda tarruda force-pushed the use-jemalloc branch 3 times, most recently from 96152be to 6988907 Compare April 12, 2015 20:13
This causes a "read after free" error when kmp_free is replaced by `free`.
Klib pools were used to improve allocation efficiency for some small objects,
but it is not a thread-safe approach. Thread safety in allocations will be
required for implementing neovim#2371).
@tarruda tarruda force-pushed the use-jemalloc branch 2 times, most recently from 03a23fb to dbebead Compare April 12, 2015 21:29
@tarruda
Copy link
Member Author

tarruda commented Apr 12, 2015

@jszakmeister any idea what is causing the quickbuild failure? It seems to be bumping into jemalloc Makefile errors

@@ -95,7 +95,7 @@
kmp_free(name, kl->mp, p); \
kmp_free(name, kl->mp, p); \
kmp_destroy(name, kl->mp); \
free(kl); \
xfree(kl); \

Choose a reason for hiding this comment

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

alignment

Copy link
Member Author

Choose a reason for hiding this comment

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

👍

@splinterofchaos
Copy link

I'm doing this more in preparation for #2371 which will require thread safety when dealing with memory

I've been under the impression for a long time that GNU's malloc implementation is thread safe (when compiled with -pthreads), and some light googling suggests BSD uses jemalloc already, but is this not true for Mac or Windows?

Some reading suggests that jemalloc is very good, even if thread safety isn't the main advantage, although I haven't seen a comparison against other allocation strategies yet.

-DTARGET=jemalloc
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND sh ${DEPS_BUILD_DIR}/src/jemalloc/autogen.sh &&
Copy link
Contributor

Choose a reason for hiding this comment

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

This is failing on FreeBSD because the default BUILD_COMMAND invokes make, which is BSD make on FreeBSD. The install should build everything required, so all you need to do here is add BUILD_COMMAND "". HTH!

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 thanks

We already use wrappers for allocation, the new `xfree` function is the
equivalent for deallocation and provides a way to fully replace the malloc
implementation used by Neovim.
Jemalloc will be used if the cmake option `USE_JEMALLOC` is enabled(which is the
default). To avoid trouble with clang's ASAN, it is disabled by default if the
`SANITIZE` option is enabled.

Since jemalloc has thread cache for small objects, it fills the gap created by
removing klib memory pools.

The `xstrdup` funciton(memory.c) had to be reimplemented on top of `xmalloc` to
make it work with a custom allocator.
@tarruda
Copy link
Member Author

tarruda commented Apr 13, 2015

I've been under the impression for a long time that GNU's malloc implementation is thread safe (when compiled with -pthreads), and some light googling suggests BSD uses jemalloc already, but is this not true for Mac or Windows?

What I meant is that we relied on klib memory pools to optimize some event data allocations, and this would require synchronization for #2371 since the event producer and consumer would be running in different threads.

The commit with replaces klib mempool by malloc/free takes care of the thread-safety problem, and the commit which adds jemalloc as a dependency fills the memory pool gap since it maintains thread-local cache for small allocations(it's also much simpler to leave caching to the allocator due to code simplification.

@tarruda tarruda changed the title [RFC] Use jemalloc instead of libc allocator [RDY] Use jemalloc instead of libc allocator Apr 13, 2015
@marvim marvim added RDY and removed RFC labels Apr 13, 2015
@tarruda tarruda merged commit 2d104f1 into neovim:master Apr 13, 2015
@jszakmeister jszakmeister removed the RDY label Apr 13, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactor changes that are not features or bugfixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Is the nfa regex engine slow?
5 participants