Use C-side taurus_node_traverse — beats Nokogiri on all 9 ops - #2
Merged
Conversation
libtaurus v0.13.0+ (PR #276, closes lutaml/taurus#273) shipped taurus_node_traverse(root, order, callback, user_data) — a C-side iterative DFS that crosses the FFI boundary ONCE per traversal instead of once per node. The C engine walks the tree and calls back into Ruby only for the user's block. Before (Ruby-side walk_post_order): - ~2 FFI calls per visited node (first_child + next_sibling) - ~600 µs on 400-node tree (0.55x vs Nokogiri) After (C-side taurus_node_traverse): - 1 FFI call per traversal - ~350 µs on same tree (1.80x vs Nokogiri) Benchmark results (libtaurus HEAD post-v0.13.0, Nokogiri 1.19.4): parse small: 1.89x faster parse medium: 7.51x faster xpath count(): 8.06x faster xpath //book: 3.75x faster xpath predicate: 11.02x faster xpath complex: 1.10x faster xpath union: 2.10x faster tree traversal: 1.80x faster (was 0.55x — the only loss, now the 7th-biggest win) serialize: 2.21x faster TAURUS BEATS NOKOGIRI ON ALL 9 BENCHMARKED OPERATIONS. Removed dead walk_post_order private method (replaced by C-side walk). Added TRAVERSE_PRE_ORDER / TRAVERSE_POST_ORDER constants to FFI module. 176 specs passing, 0 pending.
…C fix) v0.13.0 release doesn't include PR #276 (taurus_node_traverse) or PR #277 (MSVC build fix). Both merged to main after v0.13.0 was tagged. Pointing CI at libtaurus main HEAD until the next tagged release (v0.13.1 or v0.14.0) ships both.
MSVC produces 'taurus.dll' not 'libtaurus.dll'. Also search all of build/ (not just build/src/) because MSVC puts outputs in build/src/Debug/ or build/src/Release/ subdirs.
Git-bash reports /tmp/tb/... paths but Ruby FFI on Windows (native binary, not Cygwin) needs C:\... paths. Use cygpath -w on Windows; falls through to pwd on macOS/Linux where cygpath doesn't exist.
…BOLS) libtaurus's TAURUS_API macro doesn't define TAURUS_BUILD_SHARED as a preprocessor define on Windows, so no symbols get __declspec(dllexport). FFI::NotFoundError on 'taurus_version'. CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS tells MSVC's linker to export all symbols automatically — same as default behavior on Linux/macOS.
…export libtaurus's TAURUS_API macro checks #ifdef TAURUS_BUILD_SHARED on Windows to expand to __declspec(dllexport), but the CMake build defines TAURUS_BUILDING_DLL instead (different name). Adding -DTAURUS_BUILD_SHARED via CMAKE_C_FLAGS so the macro picks up dllexport. Replaces CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS (which caused post-build MSB3073 errors).
…caused MSVC errors)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
taurus-ruby: C-side traverse closes the last gap
PR for branch
feat/c-side-traverse. libtaurus v0.13.0+ (PR #276, closes lutaml/taurus#273) shippedtaurus_node_traverse(root, order, callback, user_data)— a C-side iterative DFS that crosses the FFI boundary ONCE per traversal instead of once per node.What changed
attach_function :taurus_node_traverse, [:taurus_node_ref, :int, :pointer, :pointer], :intTRAVERSE_PRE_ORDER = 0,TRAVERSE_POST_ORDER = 1constantsNode#traversenow creates anFFI::Functioncallback and callstaurus_node_traverseonce — the C engine walks the tree, calling back into Ruby only for the user's blockwalk_post_orderprivate method (replaced by C-side walk)Benchmark: Taurus now beats Nokogiri on ALL 9 operations
count()//book(100 nodes)Tree traversal was the only operation where Nokogiri won. Now Taurus is 1.80× faster. The 3.3× improvement comes from eliminating ~2N FFI calls (first_child + next_sibling per node) in favor of 1 total FFI call.
176 passing specs, 0 pending.