{"thread":{"id":"4718","subject":"Abstract out accesses to object hash array","startedAt":"2006-06-30T04:38:55Z","lastAt":"2006-06-30T04:38:55Z","messageCount":1,"participants":["Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"22884","messageId":"Pine.LNX.4.64.0606292122570.12404@g5.osdl.org","threadId":"4718","inReplyTo":null,"subject":"Abstract out accesses to object hash array","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-30T04:38:55Z","receivedAt":"2006-06-30T04:38:55Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nThere are a few special places where some programs accessed the object \nhash array directly, which bothered me because I wanted to play with some \nsimple re-organizations.\n\nSo this patch makes the object hash array data structures all entirely \nlocal to object.c, and the few users who wanted to look at it now get to \nuse a function to query how many object index entries there can be, and to \nactually access the array.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\nIt turns out that \"lookup_object()\" and \"memcmp()\" are the two hottest \nroutines by far in git-rev-list, and the problem is that the object array \ngrows pretty big. On its own, the object array would generally fit pretty \nwell in the CPU caches, but when it ends up only containing a pointer, and \nwe then do a memory compare on the result, the CPU cache ends up being \ntoast.\n\nNow, the object array actually has two bits free, and I was going to hide \ntwo bits of the SHA1 name in there, allowing me to avoid doing a memcmp() \nfor 75% of the collision cases.\n\nSadly, my crazy evil scheme doesn't actually help (the hashes work so well \nthat we have comparatively few collisions), but this cleanup seemed a \nworthwhile result of my temporary insanity.\n\ndiff --git a/fsck-objects.c b/fsck-objects.c\nindex 769bb2a..ef54a8a 100644\n--- a/fsck-objects.c\n+++ b/fsck-objects.c\n@@ -60,12 +60,13 @@ static int objwarning(struct object *obj\n \n static void check_connectivity(void)\n {\n-\tint i;\n+\tint i, max;\n \n \t/* Look up all the requirements, warn about missing objects.. */\n-\tfor (i = 0; i < obj_allocs; i++) {\n+\tmax = get_max_object_index();\n+\tfor (i = 0; i < max; i++) {\n \t\tconst struct object_refs *refs;\n-\t\tstruct object *obj = objs[i];\n+\t\tstruct object *obj = get_indexed_object(i);\n \n \t\tif (!obj)\n \t\t\tcontinue;\ndiff --git a/name-rev.c b/name-rev.c\nindex 3a5ac35..6a23f2d 100644\n--- a/name-rev.c\n+++ b/name-rev.c\n@@ -234,12 +234,15 @@ #define ishex(x) (isdigit((x)) || ((x) >\n \t\t\t\tfwrite(p_start, p - p_start, 1, stdout);\n \t\t}\n \t} else if (all) {\n-\t\tint i;\n+\t\tint i, max;\n \n-\t\tfor (i = 0; i < obj_allocs; i++)\n-\t\t\tif (objs[i])\n-\t\t\t\tprintf(\"%s %s\\n\", sha1_to_hex(objs[i]->sha1),\n-\t\t\t\t\t\tget_rev_name(objs[i]));\n+\t\tmax = get_max_object_index();\n+\t\tfor (i = 0; i < max; i++) {\n+\t\t\tstruct object * obj = get_indexed_object(i);\n+\t\t\tif (!obj)\n+\t\t\t\tcontinue;\n+\t\t\tprintf(\"%s %s\\n\", sha1_to_hex(obj->sha1), get_rev_name(obj));\n+\t\t}\n \t} else {\n \t\tint i;\n \t\tfor (i = 0; i < revs.nr; i++)\ndiff --git a/object.c b/object.c\nindex 37784ce..31c77ea 100644\n--- a/object.c\n+++ b/object.c\n@@ -5,9 +5,18 @@ #include \"tree.h\"\n #include \"commit.h\"\n #include \"tag.h\"\n \n-struct object **objs;\n-static int nr_objs;\n-int obj_allocs;\n+static struct object **objs;\n+static int nr_objs, obj_allocs;\n+\n+unsigned int get_max_object_index(void)\n+{\n+\treturn obj_allocs;\n+}\n+\n+struct object *get_indexed_object(unsigned int idx)\n+{\n+\treturn objs[idx];\n+}\n \n const char *type_names[] = {\n \t\"none\", \"blob\", \"tree\", \"commit\", \"bad\"\ndiff --git a/object.h b/object.h\nindex 6f23a9a..e0125e1 100644\n--- a/object.h\n+++ b/object.h\n@@ -40,10 +40,11 @@ struct object {\n };\n \n extern int track_object_refs;\n-extern int obj_allocs;\n-extern struct object **objs;\n extern const char *type_names[];\n \n+extern unsigned int get_max_object_index(void);\n+extern struct object *get_indexed_object(unsigned int);\n+\n static inline const char *typename(unsigned int type)\n {\n \treturn type_names[type > TYPE_TAG ? TYPE_BAD : type];\n"}]}