From d28c0fef58ba5a1282401034915340369fcf9e28 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Wed, 18 Dec 2013 13:00:23 +0400
Subject: [PATCH] Add a few optimizations for the small object allocator.

---
 src/box/tuple.cc        |  2 +-
 src/lib/small/mempool.c |  9 ---------
 src/lib/small/mempool.h | 14 ++++++++++++--
 src/lib/small/small.c   | 21 ++-------------------
 src/lib/small/small.h   | 29 +++++++++++++++++++++++++++--
 5 files changed, 42 insertions(+), 33 deletions(-)

diff --git a/src/box/tuple.cc b/src/box/tuple.cc
index e0fd30e325..c21a02f121 100644
--- a/src/box/tuple.cc
+++ b/src/box/tuple.cc
@@ -277,7 +277,7 @@ tuple_delete(struct tuple *tuple)
 	struct tuple_format *format = tuple_format(tuple);
 	char *ptr = (char *) tuple - format->field_map_size;
 	tuple_format_ref(format, -1);
-	if (tuple->version == snapshot_version)
+	if (!talloc.is_delayed_free_mode || tuple->version == snapshot_version)
 		smfree(&talloc, ptr);
 	else
 		smfree_delayed(&talloc, ptr);
diff --git a/src/lib/small/mempool.c b/src/lib/small/mempool.c
index 09b9add5db..99dd415508 100644
--- a/src/lib/small/mempool.c
+++ b/src/lib/small/mempool.c
@@ -221,15 +221,6 @@ mempool_alloc_nothrow(struct mempool *pool)
 	return mslab_alloc(slab);
 }
 
-void
-mempool_free(struct mempool *pool, void *obj)
-{
-	struct mslab *slab = (struct mslab *)
-		slab_from_ptr(pool->cache, obj, pool->slab_order);
-	pool->slabs.stats.used -= pool->objsize;
-	mslab_free(pool, slab, obj);
-}
-
 void
 mempool_stats(struct mempool *pool, struct mempool_stats *stats)
 {
diff --git a/src/lib/small/mempool.h b/src/lib/small/mempool.h
index a747e3f4f6..b21aef5879 100644
--- a/src/lib/small/mempool.h
+++ b/src/lib/small/mempool.h
@@ -225,12 +225,22 @@ mempool_destroy(struct mempool *pool);
 void *
 mempool_alloc_nothrow(struct mempool *pool);
 
+void
+mslab_free(struct mempool *pool, struct mslab *slab, void *ptr);
+
 /**
  * Free a single object.
  * @pre the object is allocated in this pool.
  */
-void
-mempool_free(struct mempool *pool, void *ptr);
+static inline void
+mempool_free(struct mempool *pool, void *ptr)
+{
+	struct mslab *slab = (struct mslab *)
+		slab_from_ptr(pool->cache, ptr, pool->slab_order);
+	pool->slabs.stats.used -= pool->objsize;
+	mslab_free(pool, slab, ptr);
+}
+
 
 /** How much memory is used by this pool. */
 static inline size_t
diff --git a/src/lib/small/small.c b/src/lib/small/small.c
index b9aa2c30a6..f28cb098c3 100644
--- a/src/lib/small/small.c
+++ b/src/lib/small/small.c
@@ -230,27 +230,10 @@ smalloc_nothrow(struct small_alloc *alloc, size_t size)
 	return mempool_alloc_nothrow(pool);
 }
 
-/**
- * Free a small objects.
- *
- * This boils down to finding the object's mempool and delegating
- * to mempool_free().
- *
- * If the pool becomes completely empty, and it's a factored pool,
- * and the factored pool's cache is empty, put back the empty
- * factored pool into the factored pool cache.
- */
+
 void
-smfree(struct small_alloc *alloc, void *ptr)
+small_recycle_pool(struct small_alloc *alloc, struct mempool *pool)
 {
-	struct mslab *slab = (struct mslab *)
-		slab_from_ptr(alloc->cache, ptr, alloc->slab_order);
-	struct mempool *pool = slab->pool;
-	mempool_free(pool, ptr);
-	/*
-	 * Don't keep around empty factored pools
-	 * if the allocator is out of them.
-	 */
 	if (mempool_used(pool) == 0 &&
 	    pool->objsize > alloc->step_pool_objsize_max &&
 	    alloc->factor_pool_next == NULL) {
diff --git a/src/lib/small/small.h b/src/lib/small/small.h
index e1f1a8390b..08a30da847 100644
--- a/src/lib/small/small.h
+++ b/src/lib/small/small.h
@@ -186,9 +186,34 @@ small_alloc_destroy(struct small_alloc *alloc);
 void *
 smalloc_nothrow(struct small_alloc *alloc, size_t size);
 
-/** Free memory chunk allocated by the small allocator. */
 void
-smfree(struct small_alloc *alloc, void *ptr);
+small_recycle_pool(struct small_alloc *alloc, struct mempool *pool);
+
+/** Free memory chunk allocated by the small allocator. */
+/**
+ * Free a small objects.
+ *
+ * This boils down to finding the object's mempool and delegating
+ * to mempool_free().
+ *
+ * If the pool becomes completely empty, and it's a factored pool,
+ * and the factored pool's cache is empty, put back the empty
+ * factored pool into the factored pool cache.
+ */
+static inline void
+smfree(struct small_alloc *alloc, void *ptr)
+{
+	struct mslab *slab = (struct mslab *)
+		slab_from_ptr(alloc->cache, ptr, alloc->slab_order);
+	struct mempool *pool = slab->pool;
+	mempool_free(pool, ptr);
+	/*
+	 * Don't keep around empty factored pools
+	 * if the allocator is out of them.
+	 */
+	if (mempool_used(pool) == 0)
+		small_recycle_pool(alloc, pool);
+}
 
 /**
  * Free memory chunk allocated by the small allocator
-- 
GitLab