Commit Diff


commit - 9ee99c5ff9b64d01be6bd3b425b442a0a3421fcf
commit + e06b866a738a376b3f75017e7cd76811a5eb594d
blob - e5a41478d3a0377cea133fe0ac9e193fe49b3f3d
blob + f9b2e1b5ba6a61b6d98b7686b525ec83b0f5c170
--- src/box/space_cache.c
+++ src/box/space_cache.c
@@ -22,6 +22,15 @@ static struct mh_strnptr_t *spaces_by_name;
  */
 uint32_t space_cache_version;
 
+/**
+ * Value of space_cache_version at the time of the last space lookup,
+ * see space_by_id_fast().
+ */
+uint32_t prev_space_cache_version;
+
+/** Last looked up space, see space_by_id_fast(). */
+struct space *prev_space;
+
 const char *space_cache_holder_type_strs[SPACE_HOLDER_MAX] = {
 	"foreign key",
 };
@@ -48,9 +57,8 @@ space_cache_destroy(void)
 	mh_strnptr_delete(spaces_by_name);
 }
 
-/** Return space by its number */
 struct space *
-space_by_id(uint32_t id)
+space_by_id_slow(uint32_t id)
 {
 	mh_int_t space = mh_i32ptr_find(spaces, id, NULL);
 	if (space == mh_end(spaces))
@@ -250,3 +258,12 @@ space_cache_is_pinned(struct space *space, enum space_
 	}
 	return false;
 }
+
+#undef space_by_id
+
+/** Define the space_by_id() symbol for FFI. */
+struct space *
+space_by_id(uint32_t id)
+{
+	return space_by_id_fast(id);
+}
blob - 97d64b52b1bf2294777699449d5c464659b0b258
blob + 86ed250a205c5fe97af4f5f47ec3d8ae045fe7e8
--- src/box/space_cache.h
+++ src/box/space_cache.h
@@ -81,6 +81,32 @@ void
 space_cache_destroy(void);
 
 /**
+ * Slow version of space lookup by id.
+ * Performs a direct lookup in the spaces hash table.
+ * Returns NULL if not found (doesn't set diag).
+ */
+struct space *
+space_by_id_slow(uint32_t id);
+
+/**
+ * Fast version of space lookup by id.
+ * Caches the last looked up space.
+ * Returns NULL if not found (doesn't set diag).
+ */
+static inline struct space *
+space_by_id_fast(uint32_t id)
+{
+	extern uint32_t prev_space_cache_version;
+	extern struct space *prev_space;
+	if (prev_space_cache_version == space_cache_version &&
+	    prev_space != NULL && prev_space->def->id == id)
+		return prev_space;
+	prev_space = space_by_id_slow(id);
+	prev_space_cache_version = space_cache_version;
+	return prev_space;
+}
+
+/**
  * Try to look up a space by space number in the space cache.
  * FFI-friendly no-exception-thrown space lookup function.
  *
@@ -89,6 +115,12 @@ space_cache_destroy(void);
 struct space *
 space_by_id(uint32_t id);
 
+/*
+ * Use the inline function for space lookups in Tarantool.
+ * The space_by_id() symbol exists only for FFI.
+ */
+#define space_by_id(id) space_by_id_fast(id)
+
 /**
  * Try to look up a space by space name in the space name cache.
  *
@@ -119,17 +151,9 @@ space_cache_find_next_unused_id(uint32_t cur_id);
 static inline struct space *
 space_cache_find(uint32_t id)
 {
-	static uint32_t prev_space_cache_version;
-	static struct space *space;
-	if (prev_space_cache_version != space_cache_version)
-		space = NULL;
-	if (space && space->def->id == id)
+	struct space *space = space_by_id(id);
+	if (space != NULL)
 		return space;
-	space = space_by_id(id);
-	if (space != NULL) {
-		prev_space_cache_version = space_cache_version;
-		return space;
-	}
 	diag_set(ClientError, ER_NO_SUCH_SPACE, int2str(id));
 	return NULL;
 }
blob - 59ceb6c5691b0fbd9dd9e83c38af46e435238ec4
blob + ab7058df77339f8cc2fe48fa52a2658ad2cf5203
--- test/unit/vy_point_lookup.c
+++ test/unit/vy_point_lookup.c
@@ -12,7 +12,10 @@
 
 uint64_t schema_version;
 uint32_t space_cache_version;
-struct space *space_by_id(uint32_t id) { return NULL; }
+uint32_t prev_space_cache_version;
+struct space *prev_space;
+struct space *
+space_by_id_slow(uint32_t id) { return NULL; }
 struct vy_lsm *vy_lsm(struct index *index) { return NULL; }
 void index_delete(struct index *index) { unreachable(); }