Recognize -zfollow,ssl,ascii,0 for compatibility
[metze/wireshark/wip.git] / doc / README.wmem
index f203e74fd3b8993364414ea0edb3bee0bcb788ad..79ec946df3a8db71cbf7cab087401b4a1f0acd51 100644 (file)
@@ -1,86 +1,97 @@
-$Id$
-
 1. Introduction
 
-The 'emem' memory manager (described in README.malloc) has been a part of
-Wireshark since 2005 and has served us well, but is starting to show its age.
-The framework has become increasingly difficult to maintain, and limitations
-in the API have blocked progress on other long-term goals such as multi-
-threading, and opening multiple files at once.
+The 'wmem' memory manager is Wireshark's memory management framework, replacing
+the old 'emem' framework which was removed in Wireshark 2.0.
+
+In order to make memory management easier and to reduce the probability of
+memory leaks, Wireshark provides its own memory management API. This API is
+implemented inside epan/wmem/ and provides memory pools and functions that make
+it easy to manage memory even in the face of exceptions (which many dissector
+functions can raise).
 
-The 'wmem' memory manager is a new memory management framework that replaces
-emem. It provides a significantly updated API, a more modular design, and it
-isn't all jammed into one 2500-line file.
+Correct use of these functions will make your code faster, and greatly reduce
+the chances that it will leak memory in exceptional cases.
 
 Wmem was originally conceived in this email to the wireshark-dev mailing list:
 https://www.wireshark.org/lists/wireshark-dev/201210/msg00178.html
 
-The wmem code can now be found in epan/wmem/ in the Wireshark source tree.
-
 2. Usage for Consumers
 
 If you're writing a dissector, or other "userspace" code, then using wmem
-should be very similar to using emem. All you need to do is include the header
-(epan/wmem/wmem.h) and get a handle to a memory pool (if you want to *create*
-a memory pool, see the section "3. Usage for Producers" below).
+should be very similar to using malloc or g_malloc or whatever else you're used
+to. All you need to do is include the header (epan/wmem/wmem.h) and optionally
+get a handle to a memory pool (if you want to *create* a memory pool, see the
+section "3. Usage for Producers" below).
 
 A memory pool is an opaque pointer to an object of type wmem_allocator_t, and
 it is the very first parameter passed to almost every call you make to wmem.
-Other than that parameter (and the fact that functions are prefixed wmem_
-instead of ep_ or se_) usage is exactly like that of emem. For example:
+Other than that parameter (and the fact that functions are prefixed wmem_)
+usage is very similar to glib and other utility libraries. For example:
 
     wmem_alloc(myPool, 20);
 
 allocates 20 bytes in the pool pointed to by myPool.
 
-2.1 Available Pools
+2.1 Memory Pool Lifetimes
+
+Every memory pool should have a defined lifetime, or scope, after which all the
+memory in that pool is unconditionally freed. When you choose to allocate memory
+in a pool, you *must* be aware of its lifetime: if the lifetime is shorter than
+you need, your code will contain use-after-free bugs; if the lifetime is longer
+than you need, your code may contain undetectable memory leaks. In either case,
+the risks outweigh the benefits.
 
-2.1.1 (Sort Of) Global Pools
+If no pool exists whose lifetime matches the lifetime of your memory, you have
+two options: create a new pool (see section 3 of this document) or use the NULL
+pool. Any function that takes a pointer to a wmem_allocator_t can also be passed
+NULL instead, in which case the memory is managed manually (just like malloc or
+g_malloc). Memory allocated like this *must* be manually passed to wmem_free()
+in order to prevent memory leaks (however these memory leaks will at least show
+up in valgrind). Note that passing wmem_allocated memory directly to free()
+or g_free() is not safe; the backing type of manually managed memory may be
+changed without warning.
+
+2.2 Wireshark Global Pools
 
 Dissectors that include the wmem header file will have three pools available
 to them automatically: wmem_packet_scope(), wmem_file_scope() and
 wmem_epan_scope();
 
-The packet pool is scoped to the dissection of each packet, replacing
-emem's ep_ allocators. The file pool is scoped to the dissection of each file,
-replacing emem's se_ allocators. For example:
-
-    ep_malloc(32);
-    se_malloc(sizeof(guint));
-
-could be replaced with
+The packet pool is scoped to the dissection of each packet, meaning that any
+memory allocated in it will be automatically freed at the end of the current
+packet. The file pool is similarly scoped to the dissection of each file,
+meaning that any memory allocated in it will be automatically freed when the
+current capture file is closed.
 
-    wmem_alloc(wmem_packet_scope(), 32);
-    wmem_alloc(wmem_file_scope(),   sizeof(guint));
-
-NB: Using these pools outside of the appropriate scope (eg using the packet
+NB: Using these pools outside of the appropriate scope (e.g. using the packet
     pool when there isn't a packet being dissected) will throw an assertion.
     See the comment in epan/wmem/wmem_scopes.c for details.
 
 The epan pool is scoped to the library's lifetime - memory allocated in it is
-not freed until epan_cleanup() is called, which is typically at the end of the
-program. 
+not freed until epan_cleanup() is called, which is typically but not necessarily
+at the very end of the program.
 
-2.1.2 Pinfo Pool
+2.3 The Pinfo Pool
 
-Certain places (such as AT_STRINGZ address allocations) need their memory to
-stay around a little longer than the usual packet scope - basically until the
-next packet is dissected. This is effectively the scope of Wireshark's pinfo
+Certain allocations (such as AT_STRINGZ address allocations and anything that
+might end up being passed to add_new_data_source) need their memory to stick
+around a little longer than the usual packet scope - basically until the
+next packet is dissected. This is, in fact, the scope of Wireshark's pinfo
 structure, so the pinfo struct has a 'pool' member which is a wmem pool scoped
 to the lifetime of the pinfo struct.
 
-2.2 API
+2.4 API
 
 Full documentation for each function (parameters, return values, behaviours)
 lives (or will live) in Doxygen-format in the header files for those functions.
 This is just an overview of which header files you should be looking at.
 
-2.2.1 Core API
+2.4.1 Core API
 
 wmem_core.h
- - Basic memory management functions like malloc, realloc and free.
+ - Basic memory management functions (wmem_alloc, wmem_realloc, wmem_free).
 
-2.2.2 Strings
+2.4.2 Strings
 
 wmem_strutl.h
  - Utility functions for manipulating null-terminated C-style strings.
@@ -90,23 +101,32 @@ wmem_strbuf.h
  - A managed string object implementation, similar to std::string in C++ or
    GString from Glib.
 
-2.2.3 Container Data Structures
+2.4.3 Container Data Structures
+
+wmem_array.h
+ - A growable array (AKA vector) implementation.
+
+wmem_list.h
+ - A doubly-linked list implementation.
+
+wmem_map.h
+ - A hash map (AKA hash table) implementation.
 
-wmem_slist.h
- - A singly-linked list implementation.
+wmem_queue.h
+ - A queue implementation (first-in, first-out).
 
 wmem_stack.h
- - A stack implementation (push, pop, etc).
+ - A stack implementation (last-in, first-out).
 
 wmem_tree.h
- - A red-black tree implementation.
+ - A balanced binary tree (red-black tree) implementation.
 
-2.2.4 Miscellanious Utilities
+2.4.4 Miscellaneous Utilities
 
 wmem_miscutl.h
  - Misc. utility functions like memdup.
 
-2.3 Callbacks
+2.5 Callbacks
 
 WARNING: You probably don't actually need these; use them only when you're
          sure you understand the dangers.
@@ -114,7 +134,7 @@ WARNING: You probably don't actually need these; use them only when you're
 Sometimes (though hopefully rarely) it may be necessary to store data in a wmem
 pool that requires additional cleanup before it is freed. For example, perhaps
 you have a pointer to a file-handle that needs to be closed. In this case, you
-can register a callback with the wmem_register_cleanup_callback function
+can register a callback with the wmem_register_callback function
 declared in wmem_user_cb.h. Every time the memory in a pool is freed, all
 registered cleanup functions are called first.
 
@@ -235,24 +255,24 @@ read-only by the allocator implementation.
 
 4.1.2 Consumer Functions
 
- - alloc()
- - free()
- - realloc()
+ - walloc()
+ - wfree()
+ - wrealloc()
 
 These function pointers should be set to functions with semantics obviously
 similar to their standard-library namesakes. Each one takes an extra parameter
 that is a copy of the allocator's private_data pointer.
 
-Note that realloc() and free() are not expected to be called directly by user
-code in most cases - they are primarily optimisations for use by data
-structures that wmem might want to implement (it's hard, for example, to
+Note that wrealloc() and wfree() are not expected to be called directly by user
+code in most cases - they are primarily optimizations for use by data
+structures that wmem might want to implement (it's inefficient, for example, to
 implement a dynamically sized array without some form of realloc).
 
 Also note that allocators do not have to handle NULL pointers or 0-length
 requests in any way - those checks are done in an allocator-agnostic way
 higher up in wmem. Allocator authors can assume that all incoming pointers
-(to realloc and free) are non-NULL, and that all incoming lengths (to malloc
-and realloc) are non-0.
+(to wrealloc and wfree) are non-NULL, and that all incoming lengths (to walloc
+and wrealloc) are non-0.
 
 4.1.3 Producer/Manager Functions
 
@@ -274,8 +294,8 @@ structures, etc.
 
 The cleanup() function should do any final cleanup and free any and all memory.
 It is basically the equivalent of a destructor function. For simplicity, wmem
-is guaranteed to call free_all() immediately before this function. There is no
-such guarantee that gc() has (ever) been called.
+is guaranteed to call free_all() immediately before calling this function. There
+is no such guarantee that gc() has (ever) been called.
 
 4.2 Pool-Agnostic API
 
@@ -310,6 +330,10 @@ type is requested normally by the code. It currently has three valid values:
    currently used by any scripts, but is useful for stress-testing the block
    allocator.
 
+ - The value "block_fast" forces the use of WMEM_ALLOCATOR_BLOCK_FAST. This is
+   not currently used by any scripts, but is useful for stress-testing the fast
+   block allocator.
+
 Note that regardless of the value of this variable, it will always be safe to
 call allocator-specific helpers functions. They are required to be safe no-ops
 if the allocator argument is of the wrong type.
@@ -320,24 +344,47 @@ There is a simple test suite for wmem that lives in the file wmem_test.c and
 should get automatically built into the binary 'wmem_test' when building
 Wireshark. It contains at least basic tests for all existing functionality.
 The suite is run automatically by the build-bots via the shell script
-test/test.sh which calls out to test/suite-unittests.sh.
+test/test.py which calls out to test/suite_unittests.py.
 
 New features added to wmem (allocators, data structures, utility
-functions, etc.) must also have tests added to this suite.
+functions, etc.) MUST also have tests added to this suite.
 
 The test suite could potentially use a clean-up by someone more
 intimately familiar with Glib's testing framework, but it does the job.
 
-5. TODO List
-
-The following is a list of things that emem didn't provide but that it might
-be nice if wmem did:
-
- - radix tree
- - hash table
+5. A Note on Performance
+
+Because of my own bad judgment, there is the persistent idea floating around
+that wmem is somehow magically faster than other allocators in the general case.
+This is false.
+
+First, wmem supports multiple different allocator backends (see sections 3 and 4
+of this document), so it is confusing and misleading to try and compare the
+performance of "wmem" in general with another system anyways.
+
+Second, any modern system-provided malloc already has a very clever and
+efficient allocator algorithm that makes use of blocks, arenas and all sorts of
+other fancy tricks. Trying to be faster than libc's allocator is generally a
+waste of time unless you have a specific allocation pattern to optimize for.
+
+Third, while there were historically arguments to be made for putting something
+in front of the kernel to reduce the number of context-switches, modern libc
+implementations should already do that. Making a dynamic library call is still
+marginally more expensive than calling a locally-defined linker-optimized
+function, but it's a difference too small to care about.
+
+With all that said, it is true that *some* of wmem's allocators can be
+substantially faster than your standard libc malloc, in *some* use cases:
+ - The BLOCK and BLOCK_FAST allocators both provide very efficient free_all
+   operations, which can be many orders of magnitude faster than calling free()
+   on each individual allocation.
+ - The BLOCK_FAST allocator in particular is optimized for Wireshark's packet
+   scope pool. It has an extremely short, well-defined lifetime, and a very
+   regular pattern of allocations; I was able to use that knowledge to beat libc
+   rather handily, *in that specific use case*.
 
 /*
- * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
  *
  * Local variables:
  * c-basic-offset: 4