when I execute a simple apache benchmark test (ab.exe @ windows 7) with concurrency level greater than 1, I'm getting failed requests and following exception in server log. It seems to be related to the fact that NashornScriptEngine instance is shared.
jdk.nashorn.internal.runtime.ECMAException: Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref.
at jdk.nashorn.internal.scripts.Script$\^eval\_$17._L4-1$_L17101$_L17126(<eval>:17150)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12185$_L12256(<eval>:12258)
at jdk.nashorn.internal.scripts.Script$\^eval\_$6._L4-1$_L4757$_L5004(<eval>:5015)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.call(NativeFunction.java:161)
at jdk.nashorn.internal.scripts.Script$\^eval\_$7._L4-1$_L5318$_L6083(<eval>:6084)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.apply(NativeFunction.java:129)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12339$_L12379$_L12382(<eval>:12389)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L11653$_L11834(<eval>:11848)
at jdk.nashorn.internal.scripts.Script$\^eval\_$8._L4-1$_L7098$_L7344(<eval>:7358)
at jdk.nashorn.internal.scripts.Script$\^eval\_$8._L4-1$_L7098$_L7269(<eval>:7280)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.apply(NativeFunction.java:129)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12339$_L12379$_L12382(<eval>:12389)
at jdk.nashorn.internal.scripts.Script$\^eval\_$7._L4-1$_L5318$_L6083(<eval>:6126)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.apply(NativeFunction.java:129)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12339$_L12379$_L12382(<eval>:12389)
at jdk.nashorn.internal.scripts.Script$\^eval\_$7._L4-1$_L5318$_L6083(<eval>:6126)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.apply(NativeFunction.java:129)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12339$_L12379$_L12382(<eval>:12389)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L11653$_L11834(<eval>:11848)
at jdk.nashorn.internal.scripts.Script$\^eval\_$8._L4-1$_L7098$_L7344(<eval>:7358)
at jdk.nashorn.internal.scripts.Script$\^eval\_$8._L4-1$_L7098$_L7269(<eval>:7280)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.apply(NativeFunction.java:129)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12339$_L12379$_L12382(<eval>:12389)
at jdk.nashorn.internal.scripts.Script$\^eval\_$7._L4-1$_L5318$_L6083(<eval>:6126)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:504)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.apply(NativeFunction.java:129)
at jdk.nashorn.internal.scripts.Script$\^eval\_$13._L4-1$_L12339$_L12379$_L12382(<eval>:12389)
at jdk.nashorn.internal.scripts.Script$\^eval\_$14._L4-1$_L13253$renderToString$_L13291(<eval>:13293)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:498)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.internal.objects.NativeFunction.call(NativeFunction.java:161)
at jdk.nashorn.internal.scripts.Script$\^eval\_$16._L4-1$_L15298$_L15416(<eval>:15432)
at jdk.nashorn.internal.scripts.Script$\^eval\_$14._L4-1$_L13253$renderToString(<eval>:13291)
at jdk.nashorn.internal.scripts.Script$\^eval\_._L113(<eval>:116)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:500)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.api.scripting.ScriptObjectMirror.callMember(ScriptObjectMirror.java:179)
at jdk.nashorn.api.scripting.NashornScriptEngine.invokeImpl(NashornScriptEngine.java:508)
at jdk.nashorn.api.scripting.NashornScriptEngine.invokeFunction(NashornScriptEngine.java:229)
at com.winterbe.react.React.renderCommentBox(React.java:33)
at com.winterbe.react.MainController.index(MainController.java:33)
at sun.reflect.GeneratedMethodAccessor49.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
I've tried creating new NashornScriptEngine for each request and while it actually solves the issue, it's slow as hell (as expected) :)
Alternative solution that fixes the mentioned issue is to leave NashornScriptEngine pre-initialized and shared as it is, but make renderCommentBox method synchronized. This seems to work fine and the performance is also quite good (614 req/s with concurency level 4), but not ideal (400 req.s with concurency level 1).
There must be some better way than synchronizing the whole method. Any idea?
> D:\tools\abwin\ab.exe -n 5000 -c 4 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Server Software: Apache-Coyote/1.1
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 1516 bytes
Concurrency Level: 4
Time taken for tests: 8.133 seconds
Complete requests: 5000
Failed requests: 4557
(Connect: 0, Receive: 0, Length: 4557, Exceptions: 0)
Write errors: 0
Total transferred: 8937688 bytes
HTML transferred: 7622688 bytes
Requests per second: 614.78 [#/sec] (mean)
Time per request: 6.506 [ms] (mean)
Time per request: 1.627 [ms] (mean, across all concurrent requests)
Transfer rate: 1073.18 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.3 0 10
Processing: 0 6 5.1 10 30
Waiting: 0 6 5.1 10 30
Total: 0 6 5.1 10 30
Percentage of the requests served within a certain time (ms)
50% 10
66% 10
75% 10
80% 10
90% 10
95% 10
98% 10
99% 20
100% 30 (longest request)