浏览代码

better performance for table operations (mainly for integer indices)

Roberto Ierusalimschy 24 年之前
父节点
当前提交
654b16e83a
共有 3 个文件被更改,包括 86 次插入65 次删除
  1. 75 50
      ltable.c
  2. 8 10
      ltable.h
  3. 3 5
      ltests.c

+ 75 - 50
ltable.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltable.c,v 1.81 2001/06/15 20:36:57 roberto Exp roberto $
+** $Id: ltable.c,v 1.82 2001/06/26 13:20:45 roberto Exp roberto $
 ** Lua tables (hash)
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -41,14 +41,14 @@
 ** returns the `main' position of an element in a table (that is, the index
 ** returns the `main' position of an element in a table (that is, the index
 ** of its hash value)
 ** of its hash value)
 */
 */
-Node *luaH_mainposition (const Hash *t, const Node *n) {
-  switch (ttype(key(n))) {
+Node *luaH_mainposition (const Hash *t, const TObject *key) {
+  switch (ttype(key)) {
     case LUA_TNUMBER:
     case LUA_TNUMBER:
-      return hashnum(t, nvalue(key(n)));
+      return hashnum(t, nvalue(key));
     case LUA_TSTRING:
     case LUA_TSTRING:
-      return hashstr(t, tsvalue(key(n)));
+      return hashstr(t, tsvalue(key));
     default:  /* all other types are hashed as (void *) */
     default:  /* all other types are hashed as (void *) */
-      return hashpointer(t, tsvalue(key(n)));
+      return hashpointer(t, tsvalue(key));
   }
   }
 }
 }
 
 
@@ -61,8 +61,8 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) {
     const TObject *v = luaH_get(t, key);
     const TObject *v = luaH_get(t, key);
     if (v == &luaO_nilobject)
     if (v == &luaO_nilobject)
       luaD_error(L, l_s("invalid key for `next'"));
       luaD_error(L, l_s("invalid key for `next'"));
-    i = (int)(((const l_char *)v -
-               (const l_char *)(val(node(t, 0)))) / sizeof(Node)) + 1;
+    i = (int)(((const lu_byte *)v -
+               (const lu_byte *)(val(node(t, 0)))) / sizeof(Node)) + 1;
   }
   }
   for (; i<t->size; i++) {
   for (; i<t->size; i++) {
     Node *n = node(t, i);
     Node *n = node(t, i);
@@ -74,7 +74,7 @@ Node *luaH_next (lua_State *L, Hash *t, const TObject *key) {
 
 
 
 
 int luaH_nexti (Hash *t, int i) {
 int luaH_nexti (Hash *t, int i) {
-  for (i++; i<t->size; i++) {
+  while ((++i)<t->size) {
     if (ttype(val(node(t, i))) != LUA_TNIL)  /* a non-nil value? */
     if (ttype(val(node(t, i))) != LUA_TNIL)  /* a non-nil value? */
       return i;
       return i;
   }
   }
@@ -177,9 +177,10 @@ static void rehash (lua_State *L, Hash *t) {
 ** put new key in its main position; otherwise (colliding node is in its main 
 ** put new key in its main position; otherwise (colliding node is in its main 
 ** position), new key goes to an empty position. 
 ** position), new key goes to an empty position. 
 */
 */
-static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) {
+static TObject *newkey (lua_State *L, Hash *t, const TObject *key) {
+  Node *mp = luaH_mainposition(t, key);
   if (ttype(val(mp)) != LUA_TNIL) {  /* main position is not free? */
   if (ttype(val(mp)) != LUA_TNIL) {  /* main position is not free? */
-    Node *othern = luaH_mainposition(t, mp);  /* `mp' of colliding node */
+    Node *othern = luaH_mainposition(t, key(mp));  /* `mp' of colliding node */
     Node *n = t->firstfree;  /* get a free place */
     Node *n = t->firstfree;  /* get a free place */
     if (othern != mp) {  /* is colliding node out of its main position? */
     if (othern != mp) {  /* is colliding node out of its main position? */
       /* yes; move colliding node into free position */
       /* yes; move colliding node into free position */
@@ -210,68 +211,92 @@ static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) {
 
 
 
 
 /*
 /*
-** search function for numbers
+** generic search function
 */
 */
-TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key) {
-  TObject kobj;
-  Node *mp = hashnum(t, key);
-  Node *n = mp;
+static const TObject *luaH_getany (Hash *t, const TObject *key) {
+  if (ttype(key) == LUA_TNIL) return &luaO_nilobject;
+  else {
+    Node *n = luaH_mainposition(t, key);
+    do {  /* check whether `key' is somewhere in the chain */
+      if (luaO_equalObj(key(n), key)) return val(n);  /* that's it */
+      else n = n->next;
+    } while (n);
+    return &luaO_nilobject;
+  }
+}
+
+
+/*
+** search function for integers
+*/
+const TObject *luaH_getnum (Hash *t, int key) {
+  Node *n = hashnum(t, key);
   do {  /* check whether `key' is somewhere in the chain */
   do {  /* check whether `key' is somewhere in the chain */
-    if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == key)
-      return val(n);  /* that's all */
+    if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key)
+      return val(n);  /* that's it */
     else n = n->next;
     else n = n->next;
   } while (n);
   } while (n);
-  if (L == NULL) return (TObject *)&luaO_nilobject;  /* get option */
-  /* `key' not found; must insert it */
-  setnvalue(&kobj, key);
-  return newkey(L, t, mp, &kobj);
+  return &luaO_nilobject;
 }
 }
 
 
 
 
 /*
 /*
 ** search function for strings
 ** search function for strings
 */
 */
-TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) {
-  TObject kobj;
-  Node *mp = hashstr(t, key);
-  Node *n = mp;
+const TObject *luaH_getstr (Hash *t, TString *key) {
+  Node *n = hashstr(t, key);
   do {  /* check whether `key' is somewhere in the chain */
   do {  /* check whether `key' is somewhere in the chain */
     if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key)
     if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key)
-      return val(n);  /* that's all */
+      return val(n);  /* that's it */
     else n = n->next;
     else n = n->next;
   } while (n);
   } while (n);
-  if (L == NULL) return (TObject *)&luaO_nilobject;  /* get option */
-  /* `key' not found; must insert it */
-  setsvalue(&kobj, key);
-  return newkey(L, t, mp, &kobj);
+  return &luaO_nilobject;
 }
 }
 
 
 
 
 /*
 /*
-** search function for 'pointer' types
+** main search function
 */
 */
-static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) {
-  Node *mp = hashpointer(t, hvalue(key));
-  Node *n = mp;
-  do {  /* check whether `key' is somewhere in the chain */
-    /* compare as `tsvalue', but may be other pointers (it is the same) */
-    if (ttype(key(n)) == ttype(key) && tsvalue(key(n)) == tsvalue(key))
-      return val(n);  /* that's all */
-    else n = n->next;
-  } while (n);
-  if (L == NULL) return (TObject *)&luaO_nilobject;  /* get option */
-  return newkey(L, t, mp, key);  /* `key' not found; must insert it */
+const TObject *luaH_get (Hash *t, const TObject *key) {
+  switch (ttype(key)) {
+    case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
+    case LUA_TNUMBER: {
+      int k = (int)nvalue(key);
+      if ((lua_Number)k == nvalue(key))  /* is an integer index? */
+        return luaH_getnum(t, k);  /* use specialized version */
+      /* else go through */
+    }
+    default: return luaH_getany(t, key);
+  }
 }
 }
 
 
 
 
 TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
 TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
-  switch (ttype(key)) {
-    case LUA_TNUMBER: return luaH_setnum(L, t, nvalue(key));
-    case LUA_TSTRING: return luaH_setstr(L, t, tsvalue(key));
-    case LUA_TNIL:
-      if (L) luaD_error(L, l_s("table index is nil"));
-      return (TObject *)&luaO_nilobject;  /* get option */
-    default:         return luaH_setany(L, t, key);
+  const TObject *p = luaH_get(t, key);
+  if (p != &luaO_nilobject) return (TObject *)p;
+  else if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil"));
+  return newkey(L, t, key);
+}
+
+
+TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) {
+  const TObject *p = luaH_getstr(t, key);
+  if (p != &luaO_nilobject) return (TObject *)p;
+  else {
+    TObject k;
+    setsvalue(&k, key);
+    return newkey(L, t, &k);
+  }
+}
+
+
+TObject *luaH_setnum (lua_State *L, Hash *t, int key) {
+  const TObject *p = luaH_getnum(t, key);
+  if (p != &luaO_nilobject) return (TObject *)p;
+  else {
+    TObject k;
+    setnvalue(&k, key);
+    return newkey(L, t, &k);
   }
   }
 }
 }
 
 

+ 8 - 10
ltable.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltable.h,v 1.32 2001/02/02 16:32:00 roberto Exp roberto $
+** $Id: ltable.h,v 1.33 2001/06/26 13:20:45 roberto Exp roberto $
 ** Lua tables (hash)
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -14,21 +14,19 @@
 #define key(_n)		(&(_n)->key)
 #define key(_n)		(&(_n)->key)
 #define val(_n)		(&(_n)->val)
 #define val(_n)		(&(_n)->val)
 
 
-
-#define luaH_get(_t,_k)		luaH_set(NULL,_t,_k)
-#define luaH_getnum(_t,_k)	luaH_setnum(NULL,_t,_k)
-#define luaH_getstr(_t,_k)	luaH_setstr(NULL,_t,_k)
-
+const TObject *luaH_getnum (Hash *t, int key);
+TObject *luaH_setnum (lua_State *L, Hash *t, int key);
+const TObject *luaH_getstr (Hash *t, TString *key);
+TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
+const TObject *luaH_get (Hash *t, const TObject *key);
+TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
 Hash *luaH_new (lua_State *L, int nhash);
 Hash *luaH_new (lua_State *L, int nhash);
 void luaH_free (lua_State *L, Hash *t);
 void luaH_free (lua_State *L, Hash *t);
-TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
 Node *luaH_next (lua_State *L, Hash *t, const TObject *r);
 Node *luaH_next (lua_State *L, Hash *t, const TObject *r);
 int luaH_nexti (Hash *t, int i);
 int luaH_nexti (Hash *t, int i);
-TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key);
-TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
 
 
 /* exported only for debugging */
 /* exported only for debugging */
-Node *luaH_mainposition (const Hash *t, const Node *n);
+Node *luaH_mainposition (const Hash *t, const TObject *key);
 
 
 
 
 #endif
 #endif

+ 3 - 5
ltests.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltests.c,v 1.85 2001/06/28 15:06:20 roberto Exp roberto $
+** $Id: ltests.c,v 1.86 2001/06/28 19:58:57 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -251,13 +251,11 @@ static int hash_query (lua_State *L) {
     lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash);
     lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash);
   }
   }
   else {
   else {
-    Hash *t;
-    Node n;
     TObject *o = luaA_index(L, 1);
     TObject *o = luaA_index(L, 1);
+    Hash *t;
     luaL_checktype(L, 2, LUA_TTABLE);
     luaL_checktype(L, 2, LUA_TTABLE);
     t = hvalue(luaA_index(L, 2));
     t = hvalue(luaA_index(L, 2));
-    setobj(key(&n), o);
-    lua_pushnumber(L, luaH_mainposition(t, &n) - t->node);
+    lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
   }
   }
   return 1;
   return 1;
 }
 }