commit b95e303
shrub
·
2026-07-06 14:17:37 +0000 UTC
parent ae19da0
use hash table for graph target lookup
5 files changed,
+92,
-29
+9,
-21
1@@ -196,12 +196,8 @@ addrule(struct GraphState *gs, const char *name, const struct RuleNode *rule)
2 return;
3 }
4
5- t = findtarget(gs->graph, name);
6- if (!t) {
7- gs->graph->v = xrealloc(gs->graph->v, (gs->graph->n + 1) * sizeof(gs->graph->v[0]));
8- t = &gs->graph->v[gs->graph->n++];
9- memset(t, 0, sizeof(*t));
10- t->name = intern(name);
11+ t = gettarget(gs->graph, name, 0);
12+ if (!t->defined) {
13 t->dcolon = rule->dcolon;
14 } else if (t->defined && t->dcolon != rule->dcolon) {
15 fprintf(stderr, "target file `%s' has both : and :: entries, i can't handle that!\n", name);
16@@ -243,13 +239,7 @@ addrule(struct GraphState *gs, const char *name, const struct RuleNode *rule)
17
18 if (strchr(prereqs.v[i], '%'))
19 continue;
20- t = findtarget(gs->graph, prereqs.v[i]);
21- if (!t) {
22- gs->graph->v = xrealloc(gs->graph->v, (gs->graph->n + 1) * sizeof(gs->graph->v[0]));
23- t = &gs->graph->v[gs->graph->n++];
24- memset(t, 0, sizeof(*t));
25- t->name = intern(prereqs.v[i]);
26- }
27+ t = gettarget(gs->graph, prereqs.v[i], 0);
28 if (hasword(gs->phony, t->name))
29 t->phony = 1;
30 memset(&penv, 0, sizeof(penv));
31@@ -384,10 +374,7 @@ buildgraph(const struct RuleSet *ruleset, const struct StrList *goals, struct Gr
32 free(gs.tas);
33 return -1;
34 }
35- graph->v = xrealloc(graph->v, (graph->n + 1) * sizeof(graph->v[0]));
36- t = &graph->v[graph->n++];
37- memset(t, 0, sizeof(*t));
38- t->name = intern(goals->v[i]);
39+ t = gettarget(graph, goals->v[i], 0);
40 if (hasword(gs.phony, t->name))
41 t->phony = 1;
42 }
43@@ -453,10 +440,7 @@ buildgraph(const struct RuleSet *ruleset, const struct StrList *goals, struct Gr
44 if (!findtarget(graph, prereq)) {
45 struct Target *nt;
46
47- graph->v = xrealloc(graph->v, (graph->n + 1) * sizeof(graph->v[0]));
48- nt = &graph->v[graph->n++];
49- memset(nt, 0, sizeof(*nt));
50- nt->name = intern(prereq);
51+ nt = gettarget(graph, prereq, 0);
52 if (hasword(gs.phony, nt->name))
53 nt->phony = 1;
54 changed = 1;
55@@ -600,9 +584,13 @@ freegraph(struct Graph *graph)
56 for (i = 0; i < graph->nsubs; i++)
57 freesubgraph(&graph->subs[i]);
58 free(graph->v);
59+ free(graph->targetindex);
60 free(graph->subs);
61 graph->v = 0;
62 graph->n = 0;
63+ graph->targetindex = 0;
64+ graph->ntargetindex = 0;
65+ graph->cap_targetindex = 0;
66 graph->subs = 0;
67 graph->nsubs = 0;
68 }
+1,
-4
1@@ -346,10 +346,7 @@ mergetarget(struct Graph *graph, const struct Target *src)
2
3 dst = findtarget(graph, src->name);
4 if (!dst) {
5- graph->v = xrealloc(graph->v, (graph->n + 1) * sizeof(graph->v[0]));
6- dst = &graph->v[graph->n++];
7- memset(dst, 0, sizeof(*dst));
8- dst->name = src->name;
9+ dst = gettarget(graph, src->name, 0);
10 if (src->owner)
11 dst->owner = xstrdup(src->owner);
12 } else if (!dst->owner && src->owner) {
+1,
-0
1@@ -74,6 +74,7 @@ void envsetvar(struct Env *env, const char *name, char *val, int simple, enum Or
2 int exported);
3 struct Target *findtarget(struct Graph *graph, const char *name);
4 const struct Target *findctarget(const struct Graph *graph, const char *name);
5+struct Target *gettarget(struct Graph *graph, const char *name, int *added);
6 const char *firstprereq(const struct Target *t);
7 char *joinallprereqs(const struct Target *t, const char *sep);
8 size_t totalprereqs(const struct Target *t);
+4,
-0
1@@ -229,10 +229,14 @@ struct Target {
2 };
3
4 struct SubGraph;
5+struct GraphIndexEnt;
6
7 struct Graph {
8 struct Target *v;
9 size_t n;
10+ struct GraphIndexEnt *targetindex;
11+ size_t ntargetindex;
12+ size_t cap_targetindex;
13 struct SubGraph *subs;
14 size_t nsubs;
15 };
+77,
-4
1@@ -181,6 +181,11 @@ static struct InternEntry *intern_table;
2 static size_t intern_n;
3 static size_t intern_cap;
4
5+struct GraphIndexEnt {
6+ const char *name;
7+ size_t idx;
8+};
9+
10 static size_t
11 strhash(const char *s)
12 {
13@@ -652,11 +657,79 @@ findtarget0(const struct Graph *graph, const char *name)
14 size_t i;
15
16 iname = intern(name);
17- for (i = 0; i < graph->n; i++) {
18- if (graph->v[i].name == iname)
19- return &graph->v[i];
20+ if (!graph->cap_targetindex)
21+ return 0;
22+ i = strhash(iname) & (graph->cap_targetindex - 1);
23+ for (;;) {
24+ if (!graph->targetindex[i].name)
25+ return 0;
26+ if (graph->targetindex[i].name == iname)
27+ return &graph->v[graph->targetindex[i].idx];
28+ i = (i + 1) & (graph->cap_targetindex - 1);
29 }
30- return 0;
31+}
32+
33+static void
34+graphindexgrow(struct Graph *graph)
35+{
36+ size_t i, newcap;
37+ struct GraphIndexEnt *newtab;
38+
39+ newcap = graph->cap_targetindex ? graph->cap_targetindex * 2 : 16;
40+ newtab = xmalloc(newcap * sizeof(newtab[0]));
41+ memset(newtab, 0, newcap * sizeof(newtab[0]));
42+ for (i = 0; i < graph->cap_targetindex; i++) {
43+ size_t j;
44+
45+ if (!graph->targetindex[i].name)
46+ continue;
47+ j = strhash(graph->targetindex[i].name) & (newcap - 1);
48+ while (newtab[j].name)
49+ j = (j + 1) & (newcap - 1);
50+ newtab[j] = graph->targetindex[i];
51+ }
52+ free(graph->targetindex);
53+ graph->targetindex = newtab;
54+ graph->cap_targetindex = newcap;
55+}
56+
57+static void
58+graphindexput(struct Graph *graph, const char *name, size_t idx)
59+{
60+ size_t i;
61+
62+ if (!graph->cap_targetindex || graph->ntargetindex * 3 >= graph->cap_targetindex * 2)
63+ graphindexgrow(graph);
64+ i = strhash(name) & (graph->cap_targetindex - 1);
65+ while (graph->targetindex[i].name)
66+ i = (i + 1) & (graph->cap_targetindex - 1);
67+ graph->targetindex[i].name = name;
68+ graph->targetindex[i].idx = idx;
69+ graph->ntargetindex++;
70+}
71+
72+struct Target *
73+gettarget(struct Graph *graph, const char *name, int *added)
74+{
75+ struct Target *t;
76+ const char *iname;
77+
78+ t = findtarget(graph, name);
79+ if (t) {
80+ if (added)
81+ *added = 0;
82+ return t;
83+ }
84+ iname = intern(name);
85+ graph->v = xrealloc(graph->v, (graph->n + 1) * sizeof(graph->v[0]));
86+ t = &graph->v[graph->n];
87+ memset(t, 0, sizeof(*t));
88+ t->name = iname;
89+ graphindexput(graph, iname, graph->n);
90+ graph->n++;
91+ if (added)
92+ *added = 1;
93+ return t;
94 }
95
96 struct Target *