Yes this is part of the js spec I assume you mean undefined not null.
> On Dec 7, 2016, at 7:40 PM, Jesus Luzon <jlu...@riotgames.com> wrote: > > Looks like the memory leak is due to the way we wrote our code and how > javascript works. I was expecting the line response[summoner.id > <http://summoner.id/>] = summoner; to build a map but it turns out that if > you use a number as the "key", javscript automatically fills the indexes in > the middle with null (Undefined type?). When these IDs are very large, it is > creating huge arrays that take longer to garbage collect than the code > executing. I am about to start testing this on our end to make sure we see > the improvements we expect. > > Does this idea seem like it is reasonably possible? > > On Wed, Dec 7, 2016 at 11:23 AM, Jesus Luzon <jlu...@riotgames.com > <mailto:jlu...@riotgames.com>> wrote: > Yes, it's an array of objects which I'll paste. And yes, I'm just calling > invokeFunction from many many different threads. I'm also going to go back > and take a look at all the heap dumps we have to re-confirm what I mentioned. > > "[\n" + > " {\n" + > " \"id\": 6011511,\n" + > " \"accountId\": 203192481,\n" + > " \"name\": \"Adam Pro Qardaş\",\n" + > " \"profileIconId\": 25,\n" + > " \"level\": 5,\n" + > " \"expPoints\": 83,\n" + > " \"infPoints\": 1475,\n" + > " \"revisionDate\": 1406631727000\n" + > " },\n" + > " {\n" + > " \"id\": 2810674,\n" + > " \"accountId\": 200706913,\n" + > " \"name\": \"ABZ Devrim\",\n" + > " \"profileIconId\": 663,\n" + > " \"level\": 13,\n" + > " \"expPoints\": 982,\n" + > " \"infPoints\": 10472,\n" + > " \"revisionDate\": 1450791227000\n" + > " },\n" + > " {\n" + > " \"id\": 5411195,\n" + > " \"accountId\": 202647689,\n" + > " \"name\": \"Ace HypcronN\",\n" + > " \"profileIconId\": 911,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 73,\n" + > " \"infPoints\": 182445,\n" + > " \"revisionDate\": 1480781650000\n" + > " },\n" + > " {\n" + > " \"id\": 1363020,\n" + > " \"accountId\": 1357837,\n" + > " \"name\": \"AdanaLee\",\n" + > " \"profileIconId\": 502,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 125,\n" + > " \"infPoints\": 719299,\n" + > " \"revisionDate\": 1480530778000\n" + > " },\n" + > " {\n" + > " \"id\": 8261198,\n" + > " \"accountId\": 205027096,\n" + > " \"name\": \"Achilehuz\",\n" + > " \"profileIconId\": 1381,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 10,\n" + > " \"infPoints\": 158603,\n" + > " \"revisionDate\": 1480770307000\n" + > " },\n" + > " {\n" + > " \"id\": 12685857,\n" + > " \"accountId\": 207591166,\n" + > " \"name\": \"acımasızpicc\",\n" + > " \"profileIconId\": 9,\n" + > " \"level\": 21,\n" + > " \"expPoints\": 840,\n" + > " \"infPoints\": 16659,\n" + > " \"revisionDate\": 1480515325000\n" + > " },\n" + > " {\n" + > " \"id\": 10860127,\n" + > " \"accountId\": 206507727,\n" + > " \"name\": \"AAngelFlyy\",\n" + > " \"profileIconId\": 1395,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 10,\n" + > " \"infPoints\": 73111,\n" + > " \"revisionDate\": 1480787870000\n" + > " },\n" + > " {\n" + > " \"id\": 3292376,\n" + > " \"accountId\": 201048714,\n" + > " \"name\": \"ACAB1907\",\n" + > " \"profileIconId\": 20,\n" + > " \"level\": 6,\n" + > " \"expPoints\": 305,\n" + > " \"infPoints\": 2107,\n" + > " \"revisionDate\": 1402448089000\n" + > " },\n" + > " {\n" + > " \"id\": 461671,\n" + > " \"accountId\": 446571,\n" + > " \"name\": \"Acta Est Fabulâ\",\n" + > " \"profileIconId\": 1435,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 47,\n" + > " \"infPoints\": 644672,\n" + > " \"revisionDate\": 1480626505000\n" + > " },\n" + > " {\n" + > " \"id\": 394183,\n" + > " \"accountId\": 379083,\n" + > " \"name\": \"acekse4\",\n" + > " \"profileIconId\": 27,\n" + > " \"level\": 5,\n" + > " \"expPoints\": 223,\n" + > " \"infPoints\": 908,\n" + > " \"revisionDate\": 1348116544000\n" + > " },\n" + > " {\n" + > " \"id\": 5941247,\n" + > " \"accountId\": 203106300,\n" + > " \"name\": \"abdul7878\",\n" + > " \"profileIconId\": 26,\n" + > " \"level\": 3,\n" + > " \"expPoints\": 10,\n" + > " \"infPoints\": 401,\n" + > " \"revisionDate\": 1406029148000\n" + > " },\n" + > " {\n" + > " \"id\": 2467446,\n" + > " \"accountId\": 200459837,\n" + > " \"name\": \"ActionC\",\n" + > " \"profileIconId\": 986,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 74,\n" + > " \"infPoints\": 401367,\n" + > " \"revisionDate\": 1480808608000\n" + > " },\n" + > " {\n" + > " \"id\": 9402979,\n" + > " \"accountId\": 205698832,\n" + > " \"name\": \"Ablenia \",\n" + > " \"profileIconId\": 1129,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 19,\n" + > " \"infPoints\": 163518,\n" + > " \"revisionDate\": 1480687603000\n" + > " },\n" + > " {\n" + > " \"id\": 13187505,\n" + > " \"accountId\": 207898213,\n" + > " \"name\": \"aDaMiYiM\",\n" + > " \"profileIconId\": 1301,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 116,\n" + > " \"infPoints\": 45214,\n" + > " \"revisionDate\": 1480793258000\n" + > " },\n" + > " {\n" + > " \"id\": 4141059,\n" + > " \"accountId\": 201688290,\n" + > " \"name\": \"AbiminÇarı\",\n" + > " \"profileIconId\": 898,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 152,\n" + > " \"infPoints\": 752477,\n" + > " \"revisionDate\": 1480635961000\n" + > " },\n" + > " {\n" + > " \"id\": 5702134,\n" + > " \"accountId\": 202899395,\n" + > " \"name\": \"Above the Clouds\",\n" + > " \"profileIconId\": 684,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 110,\n" + > " \"infPoints\": 288096,\n" + > " \"revisionDate\": 1471011372000\n" + > " },\n" + > " {\n" + > " \"id\": 5810740,\n" + > " \"accountId\": 202985228,\n" + > " \"name\": \"aBimm\",\n" + > " \"profileIconId\": 11,\n" + > " \"level\": 13,\n" + > " \"expPoints\": 1180,\n" + > " \"infPoints\": 10736,\n" + > " \"revisionDate\": 1409832684000\n" + > " },\n" + > " {\n" + > " \"id\": 5817751,\n" + > " \"accountId\": 203050678,\n" + > " \"name\": \"AD Glorıam\",\n" + > " \"profileIconId\": 982,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 111,\n" + > " \"infPoints\": 304658,\n" + > " \"revisionDate\": 1480795250000\n" + > " },\n" + > " {\n" + > " \"id\": 9851802,\n" + > " \"accountId\": 206011054,\n" + > " \"name\": \"AdarAllame\",\n" + > " \"profileIconId\": 911,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 48,\n" + > " \"infPoints\": 73763,\n" + > " \"revisionDate\": 1479422812000\n" + > " },\n" + > " {\n" + > " \"id\": 12735622,\n" + > " \"accountId\": 207587019,\n" + > " \"name\": \"absinthe666\",\n" + > " \"profileIconId\": 903,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 83,\n" + > " \"infPoints\": 40302,\n" + > " \"revisionDate\": 1480782923000\n" + > " },\n" + > " {\n" + > " \"id\": 6371389,\n" + > " \"accountId\": 203416952,\n" + > " \"name\": \"adamsatıcı\",\n" + > " \"profileIconId\": 3,\n" + > " \"level\": 4,\n" + > " \"expPoints\": 17,\n" + > " \"infPoints\": 685,\n" + > " \"revisionDate\": 1409320171000\n" + > " },\n" + > " {\n" + > " \"id\": 7828139,\n" + > " \"accountId\": 204927980,\n" + > " \"name\": \"AbsoluteForce\",\n" + > " \"profileIconId\": 950,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 139,\n" + > " \"infPoints\": 208789,\n" + > " \"revisionDate\": 1480804396000\n" + > " },\n" + > " {\n" + > " \"id\": 1373229,\n" + > " \"accountId\": 1358441,\n" + > " \"name\": \"AbsoluteDeath\",\n" + > " \"profileIconId\": 7,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 34,\n" + > " \"infPoints\": 223655,\n" + > " \"revisionDate\": 1471867646000\n" + > " },\n" + > " {\n" + > " \"id\": 7694972,\n" + > " \"accountId\": 204803668,\n" + > " \"name\": \"ac pnp\",\n" + > " \"profileIconId\": 937,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 161,\n" + > " \"infPoints\": 249681,\n" + > " \"revisionDate\": 1480801507000\n" + > " },\n" + > " {\n" + > " \"id\": 1373524,\n" + > " \"accountId\": 1350474,\n" + > " \"name\": \"Abdüü\",\n" + > " \"profileIconId\": 1301,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 103,\n" + > " \"infPoints\": 286803,\n" + > " \"revisionDate\": 1476621827000\n" + > " },\n" + > " {\n" + > " \"id\": 1650227,\n" + > " \"accountId\": 200000503,\n" + > " \"name\": \"AD Ambrosia\",\n" + > " \"profileIconId\": 1152,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 139,\n" + > " \"infPoints\": 156333,\n" + > " \"revisionDate\": 1480805320000\n" + > " },\n" + > " {\n" + > " \"id\": 8331358,\n" + > " \"accountId\": 205073925,\n" + > " \"name\": \"acarmanyust2\",\n" + > " \"profileIconId\": 0,\n" + > " \"level\": 2,\n" + > " \"expPoints\": 43,\n" + > " \"infPoints\": 318,\n" + > " \"revisionDate\": 1423915139000\n" + > " },\n" + > " {\n" + > " \"id\": 1862106,\n" + > " \"accountId\": 200139838,\n" + > " \"name\": \"aboU\",\n" + > " \"profileIconId\": 1155,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 0,\n" + > " \"infPoints\": 412616,\n" + > " \"revisionDate\": 1480771055000\n" + > " },\n" + > " {\n" + > " \"id\": 2362628,\n" + > " \"accountId\": 685649,\n" + > " \"name\": \"AcıFısTık\",\n" + > " \"profileIconId\": 1074,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 48,\n" + > " \"infPoints\": 233882,\n" + > " \"revisionDate\": 1480786233000\n" + > " },\n" + > " {\n" + > " \"id\": 4323909,\n" + > " \"accountId\": 201917672,\n" + > " \"name\": \"Addrenalin\",\n" + > " \"profileIconId\": 603,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 55,\n" + > " \"infPoints\": 220605,\n" + > " \"revisionDate\": 1432647338000\n" + > " },\n" + > " {\n" + > " \"id\": 377206,\n" + > " \"accountId\": 362106,\n" + > " \"name\": \"Aburame Shino\",\n" + > " \"profileIconId\": 844,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 84,\n" + > " \"infPoints\": 354087,\n" + > " \"revisionDate\": 1477666556000\n" + > " },\n" + > " {\n" + > " \"id\": 5377433,\n" + > " \"accountId\": 202697921,\n" + > " \"name\": \"AcEcolton35\",\n" + > " \"profileIconId\": 984,\n" + > " \"level\": 25,\n" + > " \"expPoints\": 751,\n" + > " \"infPoints\": 30061,\n" + > " \"revisionDate\": 1475503024000\n" + > " },\n" + > " {\n" + > " \"id\": 2381404,\n" + > " \"accountId\": 200333680,\n" + > " \"name\": \"adafakaaa\",\n" + > " \"profileIconId\": 663,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 8,\n" + > " \"infPoints\": 534204,\n" + > " \"revisionDate\": 1480719827000\n" + > " },\n" + > " {\n" + > " \"id\": 1281203,\n" + > " \"accountId\": 1259342,\n" + > " \"name\": \"AC Klondike\",\n" + > " \"profileIconId\": 898,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 27,\n" + > " \"infPoints\": 191429,\n" + > " \"revisionDate\": 1480294973000\n" + > " },\n" + > " {\n" + > " \"id\": 13161471,\n" + > " \"accountId\": 207847181,\n" + > " \"name\": \"adar21\",\n" + > " \"profileIconId\": 26,\n" + > " \"level\": 10,\n" + > " \"expPoints\": 143,\n" + > " \"infPoints\": 3558,\n" + > " \"revisionDate\": 1476529855000\n" + > " },\n" + > " {\n" + > " \"id\": 5841915,\n" + > " \"accountId\": 202998794,\n" + > " \"name\": \"Achilles29\",\n" + > " \"profileIconId\": 666,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 41,\n" + > " \"infPoints\": 219714,\n" + > " \"revisionDate\": 1480777744000\n" + > " },\n" + > " {\n" + > " \"id\": 2853062,\n" + > " \"accountId\": 200726707,\n" + > " \"name\": \"AbIanStarBebegim\",\n" + > " \"profileIconId\": 909,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 64,\n" + > " \"infPoints\": 297580,\n" + > " \"revisionDate\": 1480556859000\n" + > " },\n" + > " {\n" + > " \"id\": 8323114,\n" + > " \"accountId\": 205093515,\n" + > " \"name\": \"Absuruk\",\n" + > " \"profileIconId\": 6,\n" + > " \"level\": 30,\n" + > " \"expPoints\": 21,\n" + > " \"infPoints\": 121086,\n" + > " \"revisionDate\": 1480820801000\n" + > " }\n" + > "]" > > On Wed, Dec 7, 2016 at 7:01 AM, Hannes Wallnöfer > <hannes.wallnoe...@oracle.com <mailto:hannes.wallnoe...@oracle.com>> wrote: > Hi Jesus, > > I’m trying to reproduce the problem, and just want to make sure I get the > missing pieces right. > > You already showed us how you’re setting up the engine and the JS code you’re > running. I assume the JSON code you’re parsing is a simple array of objects? > And you’re just calling Invocable.invokeFunction on the ScriptEngine from > multiple threads in parallel, right? > > Thanks, > Hannes > > > > Am 07.12.2016 um 00:03 schrieb Jesus Luzon <jlu...@riotgames.com > > <mailto:jlu...@riotgames.com>>: > > > > When we share one invocable across many threads and run invokeFunction it > > happens, such as this: > > > > ExecutorService executor = Executors.newFixedThreadPool(50); > >> > >> Invocable invocable = generateInvocable(script); > >> > >> AtomicLong count = new AtomicLong(); > >> > >> for (int i = 0; i < 50; i++) { > >> > >> executor.submit(new Runnable() { > >> > >> @Override > >> > >> public void run() { > >> > >> try { > >> > >> while(true) { > >> > >> invocable.invokeFunction("transform", > >>> something); > >> > >> count.incrementAndGet(); > >> > >> } > >> > >> } catch (NoSuchMethodException | ScriptException > >>> e) { > >> > >> e.printStackTrace(); > >> > >> } > >> > >> } > >> > >> }); > >> > >> } > >> > >> > > > > > > On Tue, Dec 6, 2016 at 2:59 PM, Jim Laskey (Oracle) > > <james.las...@oracle.com <mailto:james.las...@oracle.com> > >> wrote: > > > >> Intersting. The example you posted demonstrates this behaviour? If so > >> I’ll file a bug and dig in. It sounds like an object is being reused > >> across invocations and accumulating changes to the property map. > >> > >> — Jim > >> > >> > >> On Dec 6, 2016, at 5:12 PM, Jesus Luzon <jlu...@riotgames.com > >> <mailto:jlu...@riotgames.com>> wrote: > >> > >> With more threads you are impacting the same 8 cores, so it will taper off > >>> after 8 threads. If it’s a 2x4 core machine then I can see 4 being a > >>> threshold depending on System performance. Transport: I meant if you were > >>> using sockets to provide the script. > >> > >> This makes sense. This one's on me then. > >> > >> > >>> So you are using the same invocable instance for all threads? If so, > >>> then you are probably good to go. As far as leaks are concerned, not sure > >>> how you would get leaks from Nashorn. The JSON object is written in Java, > >>> and little JavaScript involved. > >> > >> > >> > >>> In your example, pull up Invocable invocable = generateInvocable(script); > >>> out of the loop and use the same invocable for all threads. > >> > >> > >> We were using one invocable across all threads and we were getting > >> slowdowns on execution, high CPU Usage and memory leaks that led to > >> OutOfMemory errors. I could trace the leak to > >> > >> jdk.nashorn.internal.objects.Global -> *objectSpill* Object[8] -> > >> jdk.nashorn.internal.scripts.JO4 -> *arrayData* > >> jdk.nashorn.internal.runtime.arrays.SparseArraysData -> *underlying* > >> jdk.nashorn.internal.runtime.arrays.DeletedArrayFilter > >> > >> which just keeps growing forever. > >> > >> On Tue, Dec 6, 2016 at 6:30 AM, Jim Laskey (Oracle) < > >> james.las...@oracle.com <mailto:james.las...@oracle.com>> wrote: > >> > >>> > >>> On Dec 6, 2016, at 9:56 AM, Jesus Luzon <jlu...@riotgames.com > >>> <mailto:jlu...@riotgames.com>> wrote: > >>> > >>> The cost of creating a new engine is significant. So share an engine > >>>> across threads but use *eval > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html#eval(java.lang.String,%20javax.script.ScriptContext) > >>>> > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html#eval(java.lang.String,%20javax.script.ScriptContext)>>* > >>>> (String > >>>> <https://docs.oracle.com/javase/7/docs/api/java/lang/String.html > >>>> <https://docs.oracle.com/javase/7/docs/api/java/lang/String.html>> > >>>> script, ScriptContext > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptContext.html > >>>> > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptContext.html>> > >>>> context) instead, separate context per execution. If your JavaScript > >>>> code does not modify globals you can get away with using the same engine, > >>>> same compiled script on each thread. > >>> > >>> > >>> I guess there's a few things here I don't understand. One thing I'm > >>> trying to do is sharing a CompiledScript (which is why I'm using > >>> invocable). Also, what exactly does modify globals mean? All our filters > >>> do > >>> the same thing, make a function that takes a JSON String, turns it into a > >>> JSON, modifies it and then stringifies it back. No state is changed of > >>> anything else but there are temporary vars created inside the scope of the > >>> function. When we run this multithreaded, running invokeFunction slows > >>> down > >>> significantly and we get crazy memory leaks. > >>> > >>> > >>> So you are using the same invocable instance for all threads? If so, > >>> then you are probably good to go. As far as leaks are concerned, not sure > >>> how you would get leaks from Nashorn. The JSON object is written in Java, > >>> and little JavaScript involved. > >>> > >>> > >>> Of course there are many factors involved n performance. How many cores > >>>> do you have on the test machine? How much memory in the process? What > >>>> transport are you using between threads? That sort of thing. Other than > >>>> constructing then engine and context Nashorn performance should scale. > >>> > >>> I'm using an 8 core machine to test with 2.5Gs of RAM allocated to the > >>> process. Not sure what transports between threads means, but this is the > >>> code I'm benchmarking with. Increasing the number of threads actually > >>> makes > >>> it go faster until about 4 threads, then adding more threads takes the > >>> same > >>> amount to get to 1000 and and after a certain point it is just slower to > >>> get to 1000 counts. Some of our filters need to be able to run over 1000 > >>> times a second (across all threads) and the fastest time I could actually > >>> get with this was about 2.4 seconds for a 1000 counts. > >>> > >>>> ExecutorService executor = Executors.newFixedThreadPool(50); > >>>> > >>>> AtomicLong count = new AtomicLong(); > >>>> > >>>> for (int i = 0; i < 50; i++) { > >>>> > >>>> executor.submit(new Runnable() { > >>>> > >>>> @Override > >>>> > >>>> public void run() { > >>>> > >>>> > >>>>> try { > >>>> > >>>> Invocable invocable = > >>>>> generateInvocable(script); > >>>> > >>>> while(true) { > >>>> > >>>> invocable.invokeFunction("transform", > >>>>> something); > >>>> > >>>> count.incrementAndGet(); > >>>> > >>>> } > >>>> > >>>> } catch (NoSuchMethodException | ScriptException > >>>>> e) { > >>>> > >>>> e.printStackTrace(); > >>>> > >>>> } > >>>> > >>>> } > >>>> > >>>> }); > >>>> > >>>> } > >>>> > >>>> long lastTimestamp = System.currentTimeMillis(); > >>>> > >>>> while(true) { > >>>> > >>>> > >>>>> if (count.get() > 1000) { > >>>> > >>>> count.getAndAdd(-1000); > >>>> > >>>> System.out.println((System.currentTimeMillis() - > >>>>> lastTimestamp)/1000.0); > >>>> > >>>> lastTimestamp = System.currentTimeMillis(); > >>>> > >>>> } > >>>> > >>>> } > >>>> > >>>> > >>> With more threads you are impacting the same 8 cores, so it will taper > >>> off after 8 threads. If it’s a 2x4 core machine then I can see 4 being a > >>> threshold depending on System performance. Transport: I meant if you were > >>> using sockets to provide the script. > >>> > >>> In your example, pull up Invocable invocable = generateInvocable(script); > >>> out of the loop and use the same invocable for all threads. > >>> > >>> - Jim > >>> > >>> > >>> > >>> > >>> On Tue, Dec 6, 2016 at 5:31 AM, Jim Laskey (Oracle) < > >>> james.las...@oracle.com <mailto:james.las...@oracle.com>> wrote: > >>> > >>>> > >>>> On Dec 6, 2016, at 9:19 AM, Jesus Luzon <jlu...@riotgames.com > >>>> <mailto:jlu...@riotgames.com>> wrote: > >>>> > >>>> Hey Jim, > >>>> > >>>> I looked at it and I will look into loadWithNewGlobal to see what > >>>> exactly it does since it could be relevant. As for the rest, for my use > >>>> case having threads in the JS would not help. We're using Nashorn to > >>>> build > >>>> JSON filters in a Dynamic Proxy Service and need any of the threads > >>>> processing a request to be able to execute the script to filter. > >>>> > >>>> > >>>> The cost of creating a new engine is significant. So share an engine > >>>> across threads but use *eval > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html#eval(java.lang.String,%20javax.script.ScriptContext) > >>>> > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html#eval(java.lang.String,%20javax.script.ScriptContext)>>* > >>>> (String > >>>> <https://docs.oracle.com/javase/7/docs/api/java/lang/String.html > >>>> <https://docs.oracle.com/javase/7/docs/api/java/lang/String.html>> > >>>> script, ScriptContext > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptContext.html > >>>> > >>>> <https://docs.oracle.com/javase/7/docs/api/javax/script/ScriptContext.html>> > >>>> context) instead, separate context per execution. If your JavaScript > >>>> code does not modify globals you can get away with using the same engine, > >>>> same compiled script on each thread. > >>>> > >>>> > >>>> Also, when you say a new engine per threads is the worst case what > >>>> exactly do you mean? I would expect an initial cost of compiling the > >>>> script > >>>> on each thread and then each engine should be able to do its own thing, > >>>> but > >>>> what I'm seeing is that when running with more than 10 threads all my > >>>> engines get slow at executing code, even though they are all completely > >>>> separate from each other. > >>>> > >>>> > >>>> Of course there are many factors involved n performance. How many cores > >>>> do you have on the test machine? How much memory in the process? What > >>>> transport are you using between threads? That sort of thing. Other than > >>>> constructing then engine and context Nashorn performance should scale. > >>>> > >>>> > >>>> On Tue, Dec 6, 2016 at 5:07 AM, Jim Laskey (Oracle) < > >>>> james.las...@oracle.com <mailto:james.las...@oracle.com>> wrote: > >>>> > >>>>> Jesus, > >>>>> > >>>>> Probably the most informative information is in this blog. > >>>>> > >>>>> https://blogs.oracle.com/nashorn/entry/nashorn_multi_threading_and_mt > >>>>> <https://blogs.oracle.com/nashorn/entry/nashorn_multi_threading_and_mt> > >>>>> > >>>>> This example uses Executors but threads would work as well. > >>>>> > >>>>> I did a talk that looked at different methods to max out multithreading > >>>>> performance. A new engine per thread is the worst case. A new context > >>>>> per > >>>>> thread does much better. A new global per thread is the best while > >>>>> remaining thread safe. > >>>>> > >>>>> Cheers, > >>>>> > >>>>> — Jim > >>>>> > >>>>> > >>>>> > >>>>> > >>>>> > >>>>> On Dec 6, 2016, at 8:45 AM, Jesus Luzon <jlu...@riotgames.com > >>>>> <mailto:jlu...@riotgames.com>> wrote: > >>>>> > >>>>> Hey folks, > >>>>> > >>>>> I've tried many different ways of using Nashorn multithreaded based on > >>>>> what > >>>>> I've found on the internet and I still can't get a single one to scale. > >>>>> Even the most naive method of making many script engines with my script > >>>>> tends to bottleneck itself when I have more than 10 threads invoking > >>>>> functions. > >>>>> > >>>>> I'm using the following code to compile my script and > >>>>> invocable.invokeFunction("transform", input) to execute: > >>>>> > >>>>> static Invocable generateInvocable(String script) throws > >>>>> ScriptException { > >>>>> ScriptEngineManager manager = new ScriptEngineManager(); > >>>>> ScriptEngine engine = > >>>>> manager.getEngineByName(JAVASCRIPT_ENGINE_NAME); > >>>>> Compilable compilable = (Compilable) engine; > >>>>> final CompiledScript compiled = compilable.compile(script); > >>>>> compiled.eval(); > >>>>> return (Invocable) engine; > >>>>> } > >>>>> > >>>>> > >>>>> > >>>>> The script I'm compiling is: > >>>>> > >>>>> String script = "function transform(input) {" + > >>>>> "var result = JSON.parse(input);" + > >>>>> "response = {};\n" + > >>>>> "for (var i = 0; i < result.length; i++) {\n" + > >>>>> " var summoner = {};\n" + > >>>>> " summoner.id <http://summoner.id/> = result[i].id;\n" > >>>>> + > >>>>> " summoner.name <http://summoner.name/> = > >>>>> result[i].name;\n" + > >>>>> " summoner.profileIconId = > >>>>> result[i].profileIconId;\n" + > >>>>> " summoner.revisionDate = result[i].revisionDate;\n" + > >>>>> " summoner.summonerLevel = result[i].level;\n" + > >>>>> " response[summoner.id <http://summoner.id/>] = > >>>>> summoner;\n" + > >>>>> "}\n" + > >>>>> "result = response;" + > >>>>> "return JSON.stringify(result);" + > >>>>> "};"; > >>>>> > >>>>> > >>>>> > >>>>> I've also tried other more scaleable ways to work with scripts > >>>>> concurrently, but given that this is the most naive method where > >>>>> everything > >>>>> is brand new and I still get slowness calling them concurrently I fear > >>>>> that > >>>>> maybe I'm overlooking something extremely basic on my code. > >>>>> > >>>>> Thanks. > >>>>> -Jesus Luzon > >>>>> > >>>>> > >>>> > >>> > >>> > >> > >> > > >