Jint poor performance

534 views
Skip to first unread message

Shlomo Ildar Kazakov

unread,
Jun 11, 2021, 2:42:20 AM6/11/21
to RavenDB - an awesome database
Hi!

I have faced a very poor performance of Jint in index map. What could be a reason for this?

This is modeled with a very simple test database. Its backup is attached (zip).

The test case is very simple. The input collection Dummy conatains the single document "Dummy/1-A". It's content is not used. Then we have  "Performance.Cycle" map-reduce index on this collection.

In the map function we perform the following loop:
    const summary = {}
    for (let idx=0; idx < countIter; idx++) {
       summary.res = 1 + idx
    }

... and return the result:
    return {
        id: id(d),
        summary
    }

Reduce just saves the results to the output collection "Dummy#cycle".

On my local machine in RavenDB 5.1.8 (linux64) with countIter = 10 ** 7 (10 mln iterations) it takes about 8.3 seconds for the map to be executed by Jint (I have increased the Indexing.MaxStepsForScript parameter to 10 ** 9 for testing purpose):
Jint performance.png

At the same time on my local machine in Node.js it takes about 14.5 seconds to execute the same loop with 10 ** 10 iterations :
Node.js performance.png

Nearly twice the same time but 1000 times more iterations. About 570 times performance ratio to be exact (8300 / 14.5).

What could be the reason for this?
Is it possible to improve such a poor Jint performance?


2021-06-10-18-01-02.ravendb-Test.Performance-A-backup.zip

Marko Lahma

unread,
Jun 14, 2021, 8:10:49 AM6/14/21
to RavenDB - an awesome database

V8 compiles code, Jint is a pure interpreter. so there will be performance difference. You can try changing your for loop to use var instead of let for the idx. It should remove the need to have separate context for the loop body. 

-Marko

Shlomo Ildar Kazakov

unread,
Jun 14, 2021, 12:17:09 PM6/14/21
to RavenDB - an awesome database
Marko, I see, thank you!

This loop is just to demonstrate the issue. My code is much more complex.

In general, theoretically, is it possible for RavenDB to use V8.Net engine instead of Jint? Or there are some principal obstacles to that?

Another option could be a workaround to assemble V8.Net to the particular index as NuGet package and run the code with it (code could be stored as attachments to some meta document for the index). Should it work out this way, again, theoretically?

Marko Lahma

unread,
Jun 14, 2021, 12:46:32 PM6/14/21
to RavenDB - an awesome database

I'm not an expert here and not sure what the technical aspects would be integrating V8, but bear in mind that RavenDB injects its own objects into JS engine and allows interop to CLR (documents and functions, like the id() in your example),  you might lose all the performance benefits of V8 just by serializing state between the two processes. I'm sure that Jint project is open to PRs improving performance, usually it means understanding the use cases and how the specific calls can be optimized - in this case reusing/resetting the declarative environment inside the for loop. 

But like you've stated, your use case is more complex so hard to say, it's not that usual to do billions of iterations in for loop.

-Marko

Shlomo Ildar Kazakov

unread,
Jun 15, 2021, 8:55:25 AM6/15/21
to RavenDB - an awesome database
Marko, thank you!

> it's not that usual to do billions of iterations in for loop.

This loop is just to highlight the performance gap. 
My can code has nothing common with it. In V8 it runs about 20 times faster comparing to Jint.

> you might lose all the performance benefits of V8 just by serializing state between the two processes

Not in my case. I just need to call in map a js function with entry document and return the resulting js object. That js function performs complex business logic and needs access to CLR (id, load, metadataFor, attachments).

> but bear in mind that RavenDB injects its own objects into JS engine and allows interop to CLR (documents and functions, like the id() in your example)

V8.Net supports CLR injection. The question is, is it possible to access CLR (id, load, metadataFor, attachments, ...) in "Additional code" to perform their injection to the assembled V8 engine?

Oren Eini (Ayende Rahien)

unread,
Jun 15, 2021, 10:39:46 AM6/15/21
to ravendb
In general, we would love to have better performance here. The Jint integration is fairly well scoped to the SingleRun class and its friends. 
A PR with V8.Net integration would be awesome.

That said, note that we actually do a few things outside of the "norm".
For example, we'll not error on null objects. 

--
You received this message because you are subscribed to the Google Groups "RavenDB - an awesome database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ravendb/285ffa22-2651-4f7a-b8da-e2c4453557f1n%40googlegroups.com.


--
Oren Eini
CEO   /   Hibernating Rhinos LTD
Skype:  ayenderahien
Support:  sup...@ravendb.net
  

Oren Eini (Ayende Rahien)

unread,
Jun 15, 2021, 10:40:55 AM6/15/21
to ravendb
Another important aspect, by the way, going with V8 will give us all the modern JS syntax, which is great, but the question is whatever this is something that make sense and we could support in general.
For example, the integration is key, as well as running on all the supported platforms (such as Arm32, Arm64, etc)

Shlomo Ildar Kazakov

unread,
Jun 15, 2021, 6:18:03 PM6/15/21
to RavenDB - an awesome database
Hi Oren,

> In general, we would love to have better performance here. The Jint integration is fairly well scoped to the SingleRun class and its friends. 
> A PR with V8.Net integration would be awesome.

I completely agree. V8 integration is must-have. Actually, my developments are opening new horizons for RavenDB and make it really shine. They are based on the intensive use of JS-indexes (as well as static cyclic dependencies between them which we discussed some time ago, I have progressed a lot since then). A performant JS engine is necessary to turn them into reality.

I can try to integrate V8.Net, but I have limited resources (I work on my project alone currently) and will need assistance in this.

I want to start with just running V8.Net as an assembly.
I have started with this and got stuck in the very beginning as described below (database backup is attached: Dummy.cycleV8 and Dummy.cycleV8_2 indexes with different lists of assemblies). Do you have any ideas on how to make it work?

First, I have assembled only V8.Net and got the following error messages: 

Index execution error:
Failed to execute mapping function on Dummy/1-A. Exception: System.DllNotFoundException: Unable to load shared library 'V8_Net_Proxy_x64' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libV8_Net_Proxy_x64: cannot open shared object file: No such file or directory

In the terminal of RavenDB.Server:
ravendb> Could not locate the required V8 native libraries.  V8.NET is running in the 'x64' mode.  Some areas to check: 
1. Did you download the DLLs from a ZIP file? If so you may have to unblock the file. On Windows, you must open the file properties of the zip file and 'Unblock' it BEFORE extracting the files.
2. Review the searched paths in the nested errors below and make sure the desired path is accessible to the application for loading the required libraries under the current program's security context.
 Paths searched: ...

So, I have added V8 native assembly and got the following error on saving the index:

IndexCompilationException: Cannot load NuGet package 'v8.Full.redist.v142_clang-x64' version '7.9.317.23' from 'https://api.nuget.org/v3/index.json'., IndexDefinitionProperty='', ProblematicText='' ---> System.BadImageFormatException: Bad IL format. The format of the file '/media/installed/RavenDB/5.1.9/Server/Packages/NuGet/v8.Full.redist.v142_clang-x64.7.9.317.23/lib/Debug/icui18n.dll' is invalid.
2021-06-16-00-52-16.ravendb-Test.Performance-A-backup.zip

Shlomo Ildar Kazakov

unread,
Jun 16, 2021, 8:47:56 AM6/16/21
to RavenDB - an awesome database
I am considering now Javascript.Net (.Net bindings to the V8 JavaScript engine)
It looks more popular and alive than V8.Net

Shlomo Ildar Kazakov

unread,
Jun 18, 2021, 8:29:29 AM6/18/21
to RavenDB - an awesome database
 Javascript.Net does not fit our needs, so I go on with V8.Net

Alexander Nuta

unread,
Jun 24, 2021, 2:46:18 AM6/24/21
to RavenDB - an awesome database
Hello,

Can't you try Microsoft

Shlomo Ildar Kazakov

unread,
Jun 24, 2021, 5:00:15 AM6/24/21
to RavenDB - an awesome database
Hi, Alexander

Thank you! I will take it into account if have problems with V8.Net.
I am elaborating on V8 integration by means of V8.Net. For now it seems that V8.Net fits our needs very well.

Shlomo Ildar Kazakov

unread,
Aug 25, 2021, 7:36:10 AM8/25/21
to RavenDB - an awesome database
Hi,

Just wanted to share the good news) 

I have made RavenDB running JS on the V8 engine based on V8.Net! We have V8 performance and modern JS syntax along with cross-platform support. This is available not only for indexes but for all the usages of JS (like ETL, conflict resolution). Branch V8/5.2

As of now, I have got some of my indexes working perfectly. As soon as I get all of them working and measure the final performance I will write here about it and issue PR.

I had to modify a bit V8.Net as well to build it with the latest V8 version and on Linux (along with other platforms' support). Also, I have corrected an error with the Date. So there is going to be PR as well.

Shlomo Ildar

Oren Eini (Ayende Rahien)

unread,
Aug 25, 2021, 8:11:27 AM8/25/21
to ravendb
I'm *very* happy to hear that, looking forward for the PR.

Oren Eini (Ayende Rahien)

unread,
Sep 19, 2021, 9:12:50 AM9/19/21
to ravendb
Hi,
Any news? We would love to help and see this coming to life.

Shlomo Ildar Kazakov

unread,
Sep 21, 2021, 4:29:46 AM9/21/21
to RavenDB - an awesome database
Hi, Oren,

In general, it works fine! I am working all my time on this case. I hope to make PR by the end of this week and publish my version of V8.Net (I have rather modified and debugged it).

I had already all my indexes (actually complex of interacting indexes) calculated correctly and 3-5 times faster than with Jint, sometimes even x10. I have already started to use modern JS features like conditional chaining .? and spreading ... (it works!). With V8 we also have the full call stack on JS fails (based on assembled file names, missing JS call stack was a real pain with Jint! index just failed and it was a real quest to locate the bug). Now we can also just use (without cloning) parts of the entry and loaded docs in the map and reduce function result objects (with Jint I had to clone them).

After that, I have checked if all the objects have been garbage collected. It appeared that the rooted managed objects had not been removed at all. I am using V8.Net's InternalHandles for better performance (on-stack values without GC involvement as declared in the doc). I have fixed some errors and then have found that V8.Net's implementation of InternalHandles actually relied on GC and used WeakReferences which caused some managed rooted objects to get garbage collected too early. I have fixed it as well and by the way, have refactored InternalHandle implementation to avoid GC as it is declared in the docs. Now all the handles and managed objects are removed in time in an accurate and deterministic way. This accuracy has highlighted some places where I had wrong dealing with InternalHandles. I am fixing them one by one on my complex indexes (the more simple test index had already worked correctly). So it seems to be a matter of several days to finalize this work.

I have also started to elaborate on the feature of debugging JS with V8 inspector capabilities as described in this conversation as at some moment I felt a need for this. But it requires more effort. I am out of resources to continue with this feature.

I need help with the cross-platform building the V8.Net-Proxy c++ project (it is a part of V8.Net initially built for Windows only). I have refactored it to CMake with toolchains to build on Linux (I work on Ubuntu) and other platforms. But I have not succeeded to build it for other platforms on my Linux machine (I always get .so file).

חג סוכות שמח!
Shlomo Ildar Kazakov

Grzegorz Lachowski

unread,
Sep 21, 2021, 6:22:01 AM9/21/21
to RavenDB - 2nd generation document database
Hi Shlomo,

Great to hear it works. 
Do you need some help with CMake and DLL output? If so, can you share the relevant pieces?
Would you like to meet and go over your solution tomorrow with us?

Thanks,



--
Grzegorz Lachowski
Team Leader   /   Hibernating Rhinos LTD

Shlomo Ildar Kazakov

unread,
Sep 21, 2021, 9:54:49 AM9/21/21
to RavenDB - an awesome database

Hi Grzegorz,

> Do you need some help with CMake and DLL output? If so, can you share the relevant pieces?

Yes, I need some help here. I will share my version of V8.Net at the nearest time.

> Would you like to meet and go over your solution tomorrow with us?

In general with pleasure! I live in Israel and could even arrive at your office. But not tomorrow. First, I want all my indexes work with the new version of V8.Net. I hope to achieve this today or tomorrow)

Best regards!

Shlomo Ildar Kazakov

unread,
Sep 22, 2021, 8:02:17 AM9/22/21
to RavenDB - an awesome database
Here is my version of V8.Net (branch RavenDB, v1.1.9).

V8.Net solution consists of 5 projects:
  • C# project V8.Net
  • C++ project V8.Net-Proxy containing V8 itself and a wrapper around it which interacts with V8.Net
  • Other tree projects in the solution are just rudiments so I haven't touched them.
V8.Net-Proxy contains folder V8 where on my Ubuntu machine I have placed a symbolic to V8 folder. V8 is to be built beforehand as described here.

I have used build scripts of RavenDB as a basis. So I build the solution with ./build.sh -LinuxX64 or ./build.sh -LinuxX64 -Debug.
So we get in the ./Source/bin/netstandard/Release or Debug folder V8.Net.dll and libV8_Net_Proxy_x86_64.so binaries. In the release version we also get V8.Net.1.1.9.nupkg package (which is placed in Ravendb's libs folder). 

V8.Net.dll dynamically loads V8.Net-Proxy library named depending on the platform like *V8_Net_Proxy_* (the code for naming is in ./Source/V8.Net/Proxy/Loader.cs). V8.Net-Proxy is built with CMake (./CMakeLists.txt and toolchain files in ./cmake folder). On my Linux machine I've succeeded to build Linux binaries only, with the cross-platform building I haven't succeeded. 

Another problem to be fixed is that  V8.Net.1.1.9.nupkg doesn't contain V8.Net-Proxy binaries (so I have to put libV8_Net_Proxy_x86_64.so in it manually as it was in the original package v1.1.8).

Oren Eini (Ayende Rahien)

unread,
Sep 23, 2021, 9:14:47 AM9/23/21
to ravendb
I'll let Greg look at the actual CMake details, but about our offices, would love to host you there.
After the holidays?

Shlomo Ildar Kazakov

unread,
Sep 23, 2021, 6:18:08 PM9/23/21
to RavenDB - an awesome database
Great! I work as usual these days and can come any day starting from Sunday)
I am happy to say that I have just got all my indexes working correctly and stable! 
The sources in GitHub are up to date for both projects. 

Shlomo Ildar Kazakov

unread,
Sep 24, 2021, 7:17:39 AM9/24/21
to RavenDB - an awesome database
>  I work as usual these days and can come any day starting from Sunday)

Except for Wednesday

Reply all
Reply to author
Forward
0 new messages