Commit d562292
committed
perf(agtype): arena passthrough + binary-direct id extraction
Targets the agtype value-tree allocation cost that dominates LDBC IC4 and
other sort/comparator-bound queries. Two complementary optimizations
(A1 arena, A2 fast-id) plus the sanitizer issues uncovered while
verifying the change.
A1 — per-tuple agtype arena (Pattern B applied):
Add agt_arena_begin / AGT_ARENA_BEGIN_SHARED / agt_arena_reset /
agt_arena_end helpers (agtype_util.c, agtype.h). Two usage patterns:
disposable per-call arenas for one-shot tree builds, and a long-lived
shared arena (file-static, parented under CacheMemoryContext) for hot
inner loops that would otherwise pay AllocSetCreate cost per call.
Apply to compare_agtype_scalar_containers: when the comparator
deserializes VERTEX/EDGE/PATH composites via fill_agtype_value_no_copy,
route those allocations into a shared arena and reset (O(1)) at the
end of the comparison instead of recursively pfree'ing the tree (O(N)).
Master IC4 spent 17.64% of total CPU in pfree_agtype_value_content from
this comparator; the arena collapses that walk to one MemoryContextReset.
A2 — binary-direct id extraction:
When compare_agtype_scalar_containers compares two VERTEX or two EDGE
values, only the graphid 'id' determines order (compare_agtype_scalar_values
ignores all other fields). Master IC4 spent 73.48% inclusive in
ag_deserialize_composite called from this comparator, building the entire
agtype_value tree (label, properties, nested values) just to read one int64.
Add extract_composite_id_fast: walks the binary VERTEX/EDGE container
directly and reads the int64 id at field index 0 (always 'id' due to
length-sorted key ordering established by uniqueify_agtype_object — the
same invariant PR #2302 leveraged for direct array indexing).
Wired into compare_agtype_scalar_containers as a fast path before the
existing arena+slow path. Falls through on cross-type comparisons
(VERTEX vs EDGE), PATH, and malformed extended-type entries.
ASAN/UBSan fixes (10 issues found while verifying A1+A2 under
-fsanitize=address -fsanitize=undefined; 1 introduced by A2, 9 pre-existing).
The 11th finding (uninitialized parent_cpstate fields in cypher_analyze.c)
was independently fixed upstream by PR #2423; this branch is rebased on
top of that fix and no longer carries a duplicate change.
- HIGH: heap-buffer-overflow in agtype_raw.c:write_container — VARSIZE
included the 4-byte varlena header but copy started past it, reading
VARHDRSZ bytes past source allocation. Subtract VARHDRSZ. ASan flagged
4 times in installcheck.
- 7 unaligned int64/float8 reads/writes (AGT_HEADER is 4 bytes, leaving
payload 4-byte- but not 8-byte-aligned). UB under strict-alignment
rules. Replaced typed loads/stores with memcpy in agtype_ext.c (4 sites),
agtype_util.c (3 sites incl. extract_composite_id_fast), agtype_raw.c
(write_graphid).
- agtype.c:agtype_hash_cmp: reading r->val.array.raw_scalar at
WAGT_END_ARRAY where the iterator does not populate *val. Replaced
with explicit raw_scalar bool stack tracked across BEGIN/END pairs.
Hash output unchanged.
- agtype_util.c:copy_to_buffer: memcpy(NULL, NULL, 0) is UB. Guard with
if (len > 0).
Performance (SF3 LDBC, paired same-session vs master):
IC sum: 201,930 -> 157,129 ms = -22.19%
IC4: 50,570 -> 7,615 ms = -84.94%
IC5: 21,779 -> 20,646 ms = -5.20%
IS, IU: within noise (<= +/-3% on sub-second queries)
Tests:
34/34 installcheck on production PG18.3
34/34 installcheck on ASAN+UBSan PG18.3 (zero unique runtime errors,
zero heap-buffer-overflows; the original audit found 10 unique
runtime issues plus 1 HBO with 4 instances, all addressed here
or upstream)
Co-authored-by: Claude <noreply@anthropic.com>
modified: src/backend/utils/adt/agtype.c
modified: src/backend/utils/adt/agtype_ext.c
modified: src/backend/utils/adt/agtype_raw.c
modified: src/backend/utils/adt/agtype_util.c
modified: src/include/utils/agtype.h1 parent a1b749a commit d562292
5 files changed
Lines changed: 396 additions & 25 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4871 | 4871 | | |
4872 | 4872 | | |
4873 | 4873 | | |
| 4874 | + | |
| 4875 | + | |
| 4876 | + | |
| 4877 | + | |
| 4878 | + | |
| 4879 | + | |
| 4880 | + | |
| 4881 | + | |
| 4882 | + | |
| 4883 | + | |
| 4884 | + | |
| 4885 | + | |
| 4886 | + | |
| 4887 | + | |
| 4888 | + | |
| 4889 | + | |
4874 | 4890 | | |
4875 | 4891 | | |
4876 | 4892 | | |
| |||
4887 | 4903 | | |
4888 | 4904 | | |
4889 | 4905 | | |
4890 | | - | |
4891 | | - | |
| 4906 | + | |
| 4907 | + | |
| 4908 | + | |
| 4909 | + | |
| 4910 | + | |
| 4911 | + | |
| 4912 | + | |
| 4913 | + | |
| 4914 | + | |
| 4915 | + | |
| 4916 | + | |
| 4917 | + | |
| 4918 | + | |
| 4919 | + | |
| 4920 | + | |
| 4921 | + | |
| 4922 | + | |
4892 | 4923 | | |
4893 | 4924 | | |
4894 | | - | |
4895 | | - | |
| 4925 | + | |
| 4926 | + | |
| 4927 | + | |
| 4928 | + | |
| 4929 | + | |
| 4930 | + | |
| 4931 | + | |
| 4932 | + | |
| 4933 | + | |
| 4934 | + | |
| 4935 | + | |
| 4936 | + | |
| 4937 | + | |
4896 | 4938 | | |
4897 | 4939 | | |
4898 | 4940 | | |
4899 | 4941 | | |
4900 | 4942 | | |
4901 | 4943 | | |
| 4944 | + | |
| 4945 | + | |
4902 | 4946 | | |
4903 | 4947 | | |
4904 | 4948 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
61 | 68 | | |
62 | 69 | | |
63 | 70 | | |
| |||
68 | 75 | | |
69 | 76 | | |
70 | 77 | | |
71 | | - | |
| 78 | + | |
| 79 | + | |
72 | 80 | | |
73 | 81 | | |
74 | 82 | | |
| |||
154 | 162 | | |
155 | 163 | | |
156 | 164 | | |
157 | | - | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
158 | 170 | | |
159 | 171 | | |
160 | 172 | | |
161 | 173 | | |
162 | | - | |
| 174 | + | |
| 175 | + | |
163 | 176 | | |
164 | 177 | | |
165 | 178 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
197 | 197 | | |
198 | 198 | | |
199 | 199 | | |
200 | | - | |
201 | | - | |
202 | | - | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
203 | 214 | | |
204 | 215 | | |
205 | 216 | | |
| |||
214 | 225 | | |
215 | 226 | | |
216 | 227 | | |
217 | | - | |
218 | | - | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
219 | 237 | | |
220 | 238 | | |
221 | 239 | | |
| |||
0 commit comments