Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error Handling, Update Stability, Improved Java SDK #402

Merged
merged 133 commits into from
Aug 6, 2024
Merged

Conversation

ashvardanian
Copy link
Contributor

@ashvardanian ashvardanian commented May 5, 2024

USearch implementation had 2 layers, the core HNSW structure implemented in index.hpp and the high-level wrapper for dense equidimensional vectors in index_dense.hpp. In this release, we've made the top layer thinner and cleaner, also making this APIs more similar, error-handling more consistent, and builds faster.

Reducing Dependencies & Accelerating Builds

Previously index_dense.hpp had the following STL includes:

#include <thread> // `std::thread`
#include <functional> // `std::function`
#include <vector> // `std::vector`
#include <numeric> // `std::iota`

Those are some of the most common includes in C++ projects, also the ones I like the least. Here are a couple of reasons to hate them, taken from the "C++ Compile Health Watchdog":

name compilation time lines of code binary size
<functional> 82 .. 228 ms 12.9 .. 27.4 kLoC 0 .. 141 kB
<vector> 32 .. 48 ms 7.1 .. 8.0 kLoC 0 .. 8.2 kB
<numeric> 7 .. 13 ms 1.6 .. 2.1 kLoC 0 .. 3.3 kB
<thread> 110 .. 189 ms 17.5 .. 20.3 kLoC 0 .. 153 kB

Reduced Memory Consumption for DBMS-like Users

Most databases using USearch, would prefer to have a smaller index at the cost of some functionality. As mentioned by @rschu1ze, if enable_key_lookups is disabled, and some external DBMS is responsible for "key to vector" mappings, the memory consumption of the index_dense_gt can be further reduced.

Other Improvements

  • In update-heavy workloads, it's possible to encounter an undefined behavior, leading to a corrupt index state.
  • In aligned-alloc an integer overflow was resolved by @antonio2368.
  • Search is now exhaustive by default, so if you have ≥10 items in the index and ask for 10 closest vectors, you are expected to get 10, not ≤10.
  • Extended get, loadFromPath, and viewFromPath APIs for Java by @mccullocht.
  • On GCC 12 and older the #pragma region warning was resolved by @mbautin.
  • Casts to uint40_t slot IDs have been fixed by @Ngalstyan4.
  • Casts to b1x8_t vectors have been fixed by @Ngalstyan4.
  • Python type annotation has been added by @jamesbraza.
  • C++ example was patched by @SheldonFung98.
  • JavaScript duplicate exports patched by @eryue0220 & @johnhorsema.
  • Checking the number of dimensions in Rust by @jbrummack.
  • Marking Rust index views unsafe with @bddap.
  • Documenting reserve-save-load behavior with @GoodKnight.
  • Patching argument types in C# tests with @brittlewis12.

jaysenmarais and others added 14 commits April 29, 2024 00:46
Fixes ClickHouse/ClickHouse#61780

Co-authored-by: Antonio Andelic <antonio2368@users.noreply.github.com>
Relates to the #377 and the comment:
#377 (comment)

This temporarily disables the failing CI pipeline to generate
and update docs.
This commit drops `std::vector` dependency,
making compilation time shorter and error
handling universal across abstraction layers.
In the past, if we got "too lucky" traversing the graph,
we could exit early before accumulating K top matches,
even if the index had more than K entries. This patch
changes that behavior, making output more predicatable.
This patch addresses the issue #399, originally
observed in the Swift layer. Reimplementing it in
C++ helped locate the issue and lead to refactoring
the `update` procedure in the lowest-layer `index_gt`.

Now, `add` and `update` share less code. The `add`
is one branch shorter (not that it would be noticeable),
and `update` brings additional logic to avoid spilling
`updated_slot` into top-results and consequently
introducing self-loops.

Closes #399
ashvardanian and others added 15 commits May 8, 2024 02:49
Both `view` and `load` would `reset` the thread contexts.
After that, the very first `search` and `add` would fail, as
no thread-local contexts are initialized. It would require
a `reserve` call with a non-zero second arcgument to
define the number of concurrent threads, for which the
queues & buffers need to be allocated.

That design is counter-intuitive, so this patch re-inits the
same number of threads as before the `load` & `view` or
one, if none existed.
Co-authored-by: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>
Co-authored-by: Adolfo Garcia <1250775+adolfogc@users.noreply.github.com>
As noted by Robert Schulze, we can avoid populating `slot_lookup_`
during insertions, if `enable_key_lookups` is not set. This would lead
to lower memory consumption for large indexes of tiny vectors,
particularly common in GIS.

Co-authored-by: Robert Schulze <robert@clickhouse.com>
ashvardanian and others added 25 commits July 31, 2024 20:05
This fixes a GitHub CI warning about the
deprecated NodeJS version.
Closes #453

Co-authored-by: Andrew Dirksen <2702854+bddap@users.noreply.github.com>"
Closes #453

Co-authored-by: Andrew Dirksen <2702854+bddap@users.noreply.github.com>
The lack of capacity data is intended.
Reserving memory is a non-persistent operation
by nature, and we shouldn't save that metadata
on the disk.

Closes #452

Co-authored-by: Christopher Yim <4638193+GoodKnight@users.noreply.github.com>
This bug was tough to spot. Apple Clang was the only one
that caught it. The `-O0` flags were explicitly added to expose
more symbols for debugging. More `uint40_t` tests were added.
Co-authored-by: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>
@ashvardanian ashvardanian merged commit 219141c into main Aug 6, 2024
13 checks passed
@rschu1ze rschu1ze mentioned this pull request Aug 6, 2024
19 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.