filter performance
I'm reading the post about normal ts filters, and it says it works "with the same performance as built-in Convex filters". Do the q.eq, q.neq, q.lt (...) objects not compile to something more efficient than JS?
https://stack.convex.dev/complex-filters-in-convex
11 Replies
the query builder for
.filter
compiles to filters that run in Rust, which is slightly more efficient than JS. But not much, since the JS itself runs on the Rust/C++ V8 runtime (the same one Chrome uses). As the article's footnote mentions, efficiency of executing a filter is overshadowed by changes to the data scanned, like .withIndex
.I see. But there is a difference from using the q... objects, and using js operators/functions, correct?
Yes, i'm just saying the performance difference is negligible. You can measure it if you want 🙂 and if you want to see how the operators execute, the source code is https://github.com/get-convex/convex-backend/blob/main/crates/common/src/query.rs#959
GitHub
convex-backend/crates/common/src/query.rs at main · get-convex/conv...
Open source single-machine version of the Convex backend - get-convex/convex-backend
no problem, thanks a lot
so... some more curiosities on the runtime. since convex limits npm packages for queries and mutations, does 100% of the js code get transpiled to rust? 👀
or is it interpreted
It's interpreted, running in the same JS runtime that Chrome uses https://v8.dev/ . The restriction in packages is because it doesn't implement the node apis, just the browser ones, and doesn't allow nondeterminism or side effects in queries or mutations (so anything that uses
fetch
)V8 JavaScript engine
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
I see. So what parts of convex get special treatment by rust?
1. anything called on
ctx
(like ctx.db.query(...).filter(...)
)
2. anything V8 doesn't implement that is part of standard browsers, like fetch
3. parts of V8 we tweak for determinism and side effects, like console.log
, Date.now()
, and Math.random()
See source code https://github.com/get-convex/convex-backend/tree/main/npm-packages/udf-runtime/srcGitHub
convex-backend/npm-packages/udf-runtime/src at main · get-convex/co...
Open source single-machine version of the Convex backend - get-convex/convex-backend
I see. I'm surprised that there isn't a significant difference for filters that run in rust vs js, but I believe you :) Thanks for the info
@Lee is there a chance we also get map() reduce() with some more builtin operators? I'm looking for ways to auto-generate indexes (or materialized views) based on the shape of the query, and it would for these to be compiled to rust instead of plain js
we've discussed adding built-in joins and field selection. But we haven't added it yet because anything we add
a. will be custom syntax you need to learn
b. won't be able to cover all use-cases
c. won't be much of a performance improvement.
If we do add this support, the main reasons will be:
a. make the pattern look more supported / "blessed"
b. allow automated detection of inefficient cases that can be replaced by indexes (this is the main reason why
.filter
exists, even though we don't do this right now)
So we recommend doing maps and joins and reduce in js. If you're seeing bad performance, please measure it (like with console.time
) and reach out to see how we can help.I see. If in future testing there aren't any complaints about raw js performance, will you guys considering keeping the JS filter by default?
i'm not sure what you're asking. We're likely going to keep both the rust-executing
db.query(...).filter(...)
and js-executing filter(db.query(...), ...)
as options, for backwards compatibility if nothing else.