Why?
If you know beforehand that you'll execute some piece of code many times, the most efficient approach is to JIT-compile it right away, and not only after a lot of time has passed.
The JVM ecosystem has given up on jit warm up time for hotspot. There are other solutions like graal.
Whenever I have to deal with Java projects I'm always astonished at how completely "normal" a 4 minute startup time for a REST endpoint project on a single core machine.
That's right, Java doesn't do what the NativeJIT library does: Hotspot starts in an interpreted mode and only later JIT-compiles frequently executed code; NativeJIT, in contrast, immediately compiles the generated code, at least according to this description:
Bing formulates a custom expression for each query and then uses NativeJIT to compile the expression into x64 code that will be run on a large set of candidate documents spread across a cluster of machines.
I don't know the specifics, but my guess is that by the time Hotspot would even start compiling, the user has already received the results for their query. Ergo, Java – at least with the Hotspot VM – wouldn't be suitable for this task.
> I cannot be convinced otherwise.
made me think "why bother?". If you insist on being wrong, go on being wrong.
> The scoring process attempts to gauge how well each document matches the user's intent, and as such, depends on the specifics of how each query was phrased. Bing formulates a custom expression for each query and then uses NativeJIT to compile the expression into x64 code that will be run on a large set of candidate documents spread across a cluster of machines.
If this is "wrong" to you, then I would like to remain wrong. In fact I would like to have my mental faculties as acutely orthogonally aligned as possible compared to yours in every possible dimension.
As I said multiple times, we disagree on this point. There is a scoring process during runtime which mirrors what hotspot does in the non-literal sense. And again, I'm ok with being "wrong" so off you go.
Both have always supported building libraries/assemblies and loading them (the ASM library+custom classloaders for Java and AssemblyBuilder in .NET are about equally capable).
However .NET also has DynamicMethod that is specifically built to quickly build just small functions that aren't tied to larger contexts (similar API to asm/assemblybuilder).
But an even easier option for stuff exactly like in the article that people don't widely really seem to know about is that Linq (yes that "sql-like" stuff) actually contains parts for deferred method building that can be easily leveraged to quickly produce customized native code methods.
The neat part about the Linq-code generator is that you can just drop in plain C# code-blocks to be translataed by the C# compiler into Linq snippets and then with some helpers transform everything to Linq-tree's that can then be compiled.
The benefit over Asm/AssemblyBuilder/DynamicMethod is that Linq nodes are basically an built-in AST that can be directly leveraged whereas the other API's requires some mapping of your own AST's to the respective stack-machines.
https://learn.microsoft.com/en-us/dotnet/api/system.reflecti...
https://learn.microsoft.com/en-us/dotnet/api/system.reflecti...
https://learn.microsoft.com/en-us/dotnet/api/system.linq.exp...
This is C++, no? Why not use operator overloading for the project?
I love it when libraries like this do that. z3 in python is similar, you just build your constraints using normal syntax and it all just works. Great use of operator overloading.
AST<float> p1 = exp.GetP1();
AST<float> rsqr = p1 * p1; // AST<float> implements an operator* overload that produces an AST<float> object
Even if many frown upon operator overloading due to the annoying magical-ness of the standard-librarys appropriation of the shift operators for "piping" (<< and >>), it's still what makes many people prefer C++ for vector-math,etc tasks.
So whilst the result isn't a direct multiplication it should still be an acceptable use since the resulting code will actually be doing multiplications.
Considering what goes on under the hood however, I guess there might be some compiler optimization reasons to keep everything in the expression object in the example as the holder of data instead of spread out in an allocation tree with lots of pointer-chasing.
First, nope, if it's not multiplication it should not be using the * operator, period. Operator overloading is already overused and it leads to so much problematic code that looks fine to the untrained eye (string concat using operator+ being a famous example).
That said, you may also want to pass more options to the Mul node in the future and operator*() can only accept two arguments.
As another example, run the following Python code to see how python represents its own AST:
import ast;print(ast.dump(ast.parse("2*PI*r*r"),indent=2))As I said, I fully agree that operator overloading is horribly overused but the purpose of this JIT is to quickly create JIT code with customized expressions then those expressions should be possible to write fairly verbatim instead of following something with a religious zeal (is even matrix multiplication allowed to overload?).
And yes, AST's usually contain a lot more information such as source-location,etc for debugging (here it'd be interesting if an operator overload is able to take C++20 source_location as default parameters), but again this is for a specialized jit.
As for passing more options to mul nodes, a mul node is just that and nothing more (only extra interesting data in a restricted scenario as this would possibly be source_location as noted above).
They built this to translate a search query that is only known at runtime. Presumably they already have an AST or similar, so calling methods as it is being walked isn't any harder than operators.
Compared to even an optimized interpreter this will be somewhere between 4x to 20x faster (mainly due to having far far smaller branch predictor costs), so even if it doesn't generate optimal code it will still be within an magnitude of optimal native code whereas an interpreter will be much further behind.
dlopen/LoadLibrary,etc comes with far more memory pressure and OS bookkeeping.
Bing uses internally a better version, but improvements are not merged back to github. See https://github.com/BitFunnel/NativeJIT/issues/84#issuecommen...
I did this for ruby-libjit, and it made writing a JIT compiler much easier to read. Here's an example: https://github.com/cout/ruby-libjit/blob/master/sample/fib.r...
And a real-world example (one of the very earliest JIT compilers for ruby, written in ruby, dates back to the ruby 1.8.x days): https://github.com/cout/ludicrous/blob/master/lib/ludicrous/...
anon-3988•7mo ago
Twirrim•7mo ago
cout•7mo ago
Twirrim•7mo ago
globalnode•7mo ago
anon-3988•7mo ago
def sum(N): x = 0 for i in range(N): x += i return x
There's absolute zero reason why this code has to involve pushing and popping stuff on the python virtual stack. This should be compiled into assembly with a small conversion between C/PyObject.
The goal is to get to a point where we can even do non-trivial things inside this optimized context.
Python will never be able to go down to assembly because Python support doing "weird shit" like dynamically creating modules, hell, even creating a Python file, running eval on that, and loading it as a new module. How are you even going to transpile that to assembly?
So I approach the problem the same way numba is approaching. But hopefully more modern and simpler (implementation wise). Planning on doing it using Rust and the backend should be agnostic (GCC, Clang, whatever C compiler there is)
hayley-patton•7mo ago
Expect that you don't, and deoptimise when you do: https://bibliography.selflanguage.org/_static/dynamic-deopti...
It's really not that impossible.
lhames•7mo ago
In particular, this talk might be interesting:
"Unlocking the Power of C++ as a Service: Uniting Python's Usability with C++'s Performance"
Video: https://www.youtube.com/watch?v=rdfBnGjyFrc Slides: https://llvm.org/devmtg/2023-10/slides/techtalks/Vassilev-Un...
almostgotcaught•7mo ago
https://github.com/llvm/llvm-project/tree/main/clang/tools/c...