66 Py_ssize_t length; /* current number of elements */ |
70 Py_ssize_t length; /* current number of elements */ |
67 PyObject *added; /* populated on demand */ |
71 PyObject *added; /* populated on demand */ |
68 PyObject *headrevs; /* cache, invalidated on changes */ |
72 PyObject *headrevs; /* cache, invalidated on changes */ |
69 PyObject *filteredrevs;/* filtered revs set */ |
73 PyObject *filteredrevs;/* filtered revs set */ |
70 nodetree *nt; /* base-16 trie */ |
74 nodetree *nt; /* base-16 trie */ |
71 unsigned ntlength; /* # nodes in use */ |
|
72 unsigned ntcapacity; /* # nodes allocated */ |
|
73 int ntdepth; /* maximum depth of tree */ |
|
74 int ntsplits; /* # splits performed */ |
|
75 int ntrev; /* last rev scanned */ |
75 int ntrev; /* last rev scanned */ |
76 int ntlookups; /* # lookups */ |
76 int ntlookups; /* # lookups */ |
77 int ntmisses; /* # lookups that miss the cache */ |
77 int ntmisses; /* # lookups that miss the cache */ |
78 int inlined; |
78 int inlined; |
79 } indexObject; |
79 } indexObject; |
368 } |
366 } |
369 |
367 |
370 if (self->raw_length != self->length - 1) |
368 if (self->raw_length != self->length - 1) |
371 istat(raw_length, "revs on disk"); |
369 istat(raw_length, "revs on disk"); |
372 istat(length, "revs in memory"); |
370 istat(length, "revs in memory"); |
373 istat(ntcapacity, "node trie capacity"); |
|
374 istat(ntdepth, "node trie depth"); |
|
375 istat(ntlength, "node trie count"); |
|
376 istat(ntlookups, "node trie lookups"); |
371 istat(ntlookups, "node trie lookups"); |
377 istat(ntmisses, "node trie misses"); |
372 istat(ntmisses, "node trie misses"); |
378 istat(ntrev, "node trie last rev scanned"); |
373 istat(ntrev, "node trie last rev scanned"); |
379 istat(ntsplits, "node trie splits"); |
374 if (self->nt) { |
|
375 istat(nt->ntcapacity, "node trie capacity"); |
|
376 istat(nt->ntdepth, "node trie depth"); |
|
377 istat(nt->ntlength, "node trie count"); |
|
378 istat(nt->ntsplits, "node trie splits"); |
|
379 } |
380 |
380 |
381 #undef istat |
381 #undef istat |
382 |
382 |
383 return obj; |
383 return obj; |
384 |
384 |
1015 return -4; |
1015 return -4; |
1016 } |
1016 } |
1017 |
1017 |
1018 static int nt_new(indexObject *self) |
1018 static int nt_new(indexObject *self) |
1019 { |
1019 { |
1020 if (self->ntlength == self->ntcapacity) { |
1020 nodetree *nt = self->nt; |
1021 if (self->ntcapacity >= INT_MAX / (sizeof(nodetreenode) * 2)) { |
1021 if (nt->ntlength == nt->ntcapacity) { |
|
1022 if (nt->ntcapacity >= INT_MAX / (sizeof(nodetreenode) * 2)) { |
1022 PyErr_SetString(PyExc_MemoryError, |
1023 PyErr_SetString(PyExc_MemoryError, |
1023 "overflow in nt_new"); |
1024 "overflow in nt_new"); |
1024 return -1; |
1025 return -1; |
1025 } |
1026 } |
1026 self->ntcapacity *= 2; |
1027 nt->ntcapacity *= 2; |
1027 self->nt->nodes = realloc(self->nt->nodes, |
1028 nt->nodes = realloc(nt->nodes, |
1028 self->ntcapacity * sizeof(nodetreenode)); |
1029 nt->ntcapacity * sizeof(nodetreenode)); |
1029 if (self->nt->nodes == NULL) { |
1030 if (nt->nodes == NULL) { |
1030 PyErr_SetString(PyExc_MemoryError, "out of memory"); |
1031 PyErr_SetString(PyExc_MemoryError, "out of memory"); |
1031 return -1; |
1032 return -1; |
1032 } |
1033 } |
1033 memset(&self->nt->nodes[self->ntlength], 0, |
1034 memset(&nt->nodes[nt->ntlength], 0, |
1034 sizeof(nodetreenode) * (self->ntcapacity - self->ntlength)); |
1035 sizeof(nodetreenode) * (nt->ntcapacity - nt->ntlength)); |
1035 } |
1036 } |
1036 return self->ntlength++; |
1037 return nt->ntlength++; |
1037 } |
1038 } |
1038 |
1039 |
1039 static int nt_insert(indexObject *self, const char *node, int rev) |
1040 static int nt_insert(indexObject *self, const char *node, int rev) |
1040 { |
1041 { |
1041 int level = 0; |
1042 int level = 0; |
1069 /* self->nt->nodes may have been changed by realloc */ |
1070 /* self->nt->nodes may have been changed by realloc */ |
1070 self->nt->nodes[off].children[k] = noff; |
1071 self->nt->nodes[off].children[k] = noff; |
1071 off = noff; |
1072 off = noff; |
1072 n = &self->nt->nodes[off]; |
1073 n = &self->nt->nodes[off]; |
1073 n->children[nt_level(oldnode, ++level)] = v; |
1074 n->children[nt_level(oldnode, ++level)] = v; |
1074 if (level > self->ntdepth) |
1075 if (level > self->nt->ntdepth) |
1075 self->ntdepth = level; |
1076 self->nt->ntdepth = level; |
1076 self->ntsplits += 1; |
1077 self->nt->ntsplits += 1; |
1077 } else { |
1078 } else { |
1078 level += 1; |
1079 level += 1; |
1079 off = v; |
1080 off = v; |
1080 } |
1081 } |
1081 } |
1082 } |
1099 } |
1100 } |
1100 if ((size_t)self->raw_length > INT_MAX / sizeof(nodetreenode)) { |
1101 if ((size_t)self->raw_length > INT_MAX / sizeof(nodetreenode)) { |
1101 PyErr_SetString(PyExc_ValueError, "overflow in nt_init"); |
1102 PyErr_SetString(PyExc_ValueError, "overflow in nt_init"); |
1102 return -1; |
1103 return -1; |
1103 } |
1104 } |
1104 self->ntcapacity = self->raw_length < 4 |
1105 self->nt->ntcapacity = self->raw_length < 4 |
1105 ? 4 : (int)self->raw_length / 2; |
1106 ? 4 : (int)self->raw_length / 2; |
1106 |
1107 |
1107 self->nt->nodes = calloc(self->ntcapacity, sizeof(nodetreenode)); |
1108 self->nt->nodes = calloc(self->nt->ntcapacity, sizeof(nodetreenode)); |
1108 if (self->nt->nodes == NULL) { |
1109 if (self->nt->nodes == NULL) { |
1109 free(self->nt); |
1110 free(self->nt); |
1110 self->nt = NULL; |
1111 self->nt = NULL; |
1111 PyErr_NoMemory(); |
1112 PyErr_NoMemory(); |
1112 return -1; |
1113 return -1; |
1113 } |
1114 } |
1114 self->ntlength = 1; |
|
1115 self->ntrev = (int)index_length(self); |
1115 self->ntrev = (int)index_length(self); |
1116 self->ntlookups = 1; |
1116 self->ntlookups = 1; |
1117 self->ntmisses = 0; |
1117 self->ntmisses = 0; |
|
1118 self->nt->ntdepth = 0; |
|
1119 self->nt->ntsplits = 0; |
|
1120 self->nt->ntlength = 1; |
1118 if (nt_insert(self, nullid, -1) == -1) { |
1121 if (nt_insert(self, nullid, -1) == -1) { |
1119 free(self->nt->nodes); |
1122 free(self->nt->nodes); |
1120 free(self->nt); |
1123 free(self->nt); |
1121 self->nt = NULL; |
1124 self->nt = NULL; |
1122 return -1; |
1125 return -1; |
1979 size = self->buf.len; |
1982 size = self->buf.len; |
1980 |
1983 |
1981 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj); |
1984 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj); |
1982 self->data = data_obj; |
1985 self->data = data_obj; |
1983 |
1986 |
1984 self->ntlength = self->ntcapacity = 0; |
|
1985 self->ntdepth = self->ntsplits = 0; |
|
1986 self->ntlookups = self->ntmisses = 0; |
1987 self->ntlookups = self->ntmisses = 0; |
1987 self->ntrev = -1; |
1988 self->ntrev = -1; |
1988 Py_INCREF(self->data); |
1989 Py_INCREF(self->data); |
1989 |
1990 |
1990 if (self->inlined) { |
1991 if (self->inlined) { |