Repository navigation
Conversation
reindex_uri capped disk files at 2MB but indexed open buffers of any size, allowing one huge buffer to force an unbounded index build. The gate now covers both paths; oversized entries are dropped and marked skipped exactly like oversized disk files.
Inserting thousands of entries one by one doubles the map backing store repeatedly; a late doubling can abort under a fragmented heap (GC_alloc_large on big trees). Reserve once from the walk's file count.
|
Local AI Finding P2: Pre-sizing is skipped for incomplete walks. When |
A walk that hits the 20k file or entry limit used to insert what it found one by one until the global cap, keeping the repeated-growth and allocation-failure behavior. Both branches now share one bounded target.
|
Good catch — agreed, and fixed in d94fbc9. The reservation no longer depends on the walk being complete. Both branches now share one bounded target: if !walk_complete {
app.index_incomplete_scopes[scope] = true
}
target := index_reserve_target(app.symbol_index.len, files.len)
if target > 0 {
app.symbol_index.reserve(u32(target))
}
Tests: |
medvednikov
left a comment
There was a problem hiding this comment.
Reviewed the latest head (d94fbc9), focusing on code behavior and ignoring CI as requested. The earlier incomplete-walk reservation concern has been addressed, but I found three remaining edge cases:
-
[P2] Clamp the reservation instead of dropping it when the projected count exceeds the cap (
index.v,index_reserve_target). For example,index_reserve_target(12_000, 10_000)returns0, althoughensure_dirs_indexedmay still insert another 8,000 entries before reachingindex_max_files. In multi-root/partially indexed workspaces, that brings back the incremental map growth this change is meant to prevent. Consider returningmin(indexed + found, index_max_files)whenindexed < index_max_files, and test the crossing-cap case. Also,test_partial_walk_still_reserves_what_it_foundcurrently performs a complete 20-file walk, so it doesn't actually exercise the partial-walk branch. -
[P2] Mark oversized unsaved open buffers as incomplete for rename (
reindex_uri/index_is_complete_for_scope). The new open-buffer size check setsindex_skipped_uris[uri], butindex_is_complete_for_scopeonly rejects a skipped URI ifos.is_file(uri_to_path(uri))is true. An unsaved new file (>2 MB) in a project has no on-disk file, so rename can proceed as if indexing were complete while silently omitting its references. The completeness check should also recognize skipped URIs that are still inapp.open_files. -
[P2] Apply the oversized-buffer guard to the occurrence cache too (
occurrences_for).reindex_uridropsref_occurrencesfor large buffers, butoccurrences_forreads the same open buffer without any size gate and rebuilds the full token-occurrence map. The normal local-binding hover path calls it, so hovering an identifier in a large file can still trigger the unbounded index allocation that this change is trying to avoid. Short-circuit occurrence indexing for oversized sources and cover that call path with a test.
These are independent of CI status.
|
Can you fix the 3 items from Alex's review? |
On it |
… as incomplete index_reserve_target clamps to index_max_files instead of dropping the reservation when the projection crosses the cap; occurrences_for applies the same oversized-source gate as reindex_uri; index_is_complete_for_scope and index_is_complete treat a skipped open buffer with no file on disk as not indexed, so rename refuses instead of silently omitting references.
All three addressed |
@medvednikov's review of the index-memory change asked for three things, and this branch predates those fixes. Ported across, adapted to this tree: index_reserve_target clamps to index_max_files instead of dropping the reservation when the projection crosses the cap; occurrences_for applies the same oversized-source gate reindex_uri uses; index_is_complete_for_scope and index_is_complete treat a skipped URI still in open_files as not indexed, so an unsaved oversized buffer stops a rename. Verified: v -check, v fmt -verify, and the full index_test.v green on Windows.
Fixes Windows CI abort
Too many retries in GC_alloc_largeintest_large_vlang_v_workspace_from_env: indexing the wholevlang/vtree inserts thousands of rich entries one by one, and a late doubling
of the map backing store fails under a fragmented heap (backtrace:
map__set→DenseArray__expandviareindex_uri).(
map.reserve), so bulk walks allocate up front instead ofdoubling repeatedly.
only disk files were capped, so one huge buffer could force an
unbounded index build.
Both changes are behavior-preserving for normal sizes; oversized
entries are dropped and marked skipped exactly like oversized disk
files. Verified with targeted tests (one proves teeth by failing
with the gate disabled) plus the existing large-project suites.