Gareth Carter created OFBIZ-6621:
------------------------------------

             Summary: MapContext.entrySet() slows down when ByteBuffer objects 
are in the context
                 Key: OFBIZ-6621
                 URL: https://issues.apache.org/jira/browse/OFBIZ-6621
             Project: OFBiz
          Issue Type: Improvement
          Components: framework
    Affects Versions: Trunk
            Reporter: Gareth Carter
            Priority: Critical


When MapContext is used anywhere (eg FlexibleStringExpander) and the context 
contains ByteBuffer objects (either key or value), java will slow down when 
calling MapContext.entrySet().

Here is the code in ofbiz, highlighted is the line of code that I believe is 
the culprit

{code:title=MapContext.java}
public Set<Map.Entry<K, V>> entrySet() {
    // walk the stackList and the entries for each Map and if nothing is in for 
the current key, put it in
    Set<K> resultKeySet = new HashSet<K>();
    culprit --> Set<Map.Entry<K, V>> resultEntrySet = new ListSet<Map.Entry<K, 
V>>();
    for (Map<K, V> curMap: this.stackList) {
        for (Map.Entry<K, V> curEntry: curMap.entrySet()) {
            if (!resultKeySet.contains(curEntry.getKey())) {
                resultKeySet.add(curEntry.getKey());
                resultEntrySet.add(curEntry);
            }
        }
    }
    return Collections.unmodifiableSet(resultEntrySet);
}
{code}

Looking at the java api for Map.Entry, the hashCode method for Map.Entry is the 
result of the hashCode from both key and value. ByteBuffer hash code is 
dependent upon its content. If a 2mb file is uploaded, the hashCode method
of ByteBuffer will scan 2mb to generate the hashCode

ByteBuffer
http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#hashCode()
{quote}Because buffer hash codes are content-dependent, it is inadvisable to 
use buffers as keys in hash maps or similar data structures unless it is known 
that their contents will not change.{quote}

Map.Entry
http://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html#hashCode()
{quote}(e.getKey()==null   ? 0 : e.getKey().hashCode()) ^ (e.getValue()==null ? 
0 : e.getValue().hashCode()){quote}

HashSet
http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html
{quote}This class implements the Set interface, backed by a hash table 
(actually a HashMap instance{quote}

Example where ByteBuffer objects are created
{code}org.ofbiz.webapp.event.ServiceEventHandler{code}

Example stack trace
{noformat}
"ajp-bio-8009-exec-1894" daemon prio=10 tid=0x00007fa52c070000 nid=0x5c73 
runnable [0x00007fa51151b000]
   java.lang.Thread.State: RUNNABLE
        at java.nio.HeapByteBuffer.ix(HeapByteBuffer.java:131)
        at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:139)
        at java.nio.ByteBuffer.hashCode(ByteBuffer.java:1083)
        at java.util.Objects.hashCode(Objects.java:96)
        at java.util.HashMap$Entry.hashCode(HashMap.java:847)
        at java.util.AbstractMap.hashCode(AbstractMap.java:494)
        at java.util.Objects.hashCode(Objects.java:96)
        at java.util.HashMap$Entry.hashCode(HashMap.java:847)
        at java.util.HashMap.hash(HashMap.java:362)
        at java.util.HashMap.put(HashMap.java:492)
        at java.util.HashSet.add(HashSet.java:217)
        at 
org.ofbiz.base.util.collections.MapContext.entrySet(MapContext.java:306)
        at java.util.HashMap.putAll(HashMap.java:642)
        at 
org.ofbiz.widget.model.ModelFormField$ListOptions.addOptionValues(ModelFormField.java:2716)
        at 
org.ofbiz.widget.model.ModelFormField$FieldInfoWithOptions.getAllOptionValues(ModelFormField.java:1985)
        at 
org.ofbiz.widget.renderer.macro.MacroFormRenderer.renderDropDownField(MacroFormRenderer.java:747)
        at 
org.ofbiz.widget.model.ModelFormField$DropDownField.renderFieldString(ModelFormField.java:1739)
        at 
org.ofbiz.widget.model.ModelFormField.renderFieldString(ModelFormField.java:693)
        at 
org.ofbiz.widget.renderer.FormRenderer.renderSingleFormString(FormRenderer.java:1195)
        at org.ofbiz.widget.renderer.FormRenderer.render(FormRenderer.java:261)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Form.renderWidgetString(ModelScreenWidget.java:1052)
        at 
org.ofbiz.widget.renderer.macro.MacroScreenRenderer.renderScreenletSubWidget(MacroScreenRenderer.java:677)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Screenlet.renderWidgetString(ModelScreenWidget.java:598)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreen.renderScreenString(ModelScreen.java:164)
        at 
org.ofbiz.widget.model.ScreenFactory.renderReferencedScreen(ScreenFactory.java:211)
        at 
org.ofbiz.widget.model.ModelScreenWidget$IncludeScreen.renderWidgetString(ModelScreenWidget.java:779)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Container.renderWidgetString(ModelScreenWidget.java:459)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorSection.renderWidgetString(ModelScreenWidget.java:905)
        at 
org.ofbiz.widget.model.ModelScreenWidget$SectionsRenderer.render(ModelScreenWidget.java:127)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorSectionInclude.renderWidgetString(ModelScreenWidget.java:942)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorSection.renderWidgetString(ModelScreenWidget.java:905)
        at 
org.ofbiz.widget.model.ModelScreenWidget$SectionsRenderer.render(ModelScreenWidget.java:127)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorSectionInclude.renderWidgetString(ModelScreenWidget.java:942)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorSection.renderWidgetString(ModelScreenWidget.java:905)
        at 
org.ofbiz.widget.model.ModelScreenWidget$SectionsRenderer.render(ModelScreenWidget.java:127)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorSectionInclude.renderWidgetString(ModelScreenWidget.java:942)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Container.renderWidgetString(ModelScreenWidget.java:459)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Container.renderWidgetString(ModelScreenWidget.java:459)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Container.renderWidgetString(ModelScreenWidget.java:459)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreen.renderScreenString(ModelScreen.java:164)
        at 
org.ofbiz.widget.model.ScreenFactory.renderReferencedScreen(ScreenFactory.java:211)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorScreen.renderWidgetString(ModelScreenWidget.java:859)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreen.renderScreenString(ModelScreen.java:164)
        at 
org.ofbiz.widget.model.ScreenFactory.renderReferencedScreen(ScreenFactory.java:211)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorScreen.renderWidgetString(ModelScreenWidget.java:859)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreen.renderScreenString(ModelScreen.java:164)
        at 
org.ofbiz.widget.model.ScreenFactory.renderReferencedScreen(ScreenFactory.java:211)
        at 
org.ofbiz.widget.model.ModelScreenWidget$DecoratorScreen.renderWidgetString(ModelScreenWidget.java:859)
        at 
org.ofbiz.widget.model.ModelScreenWidget.renderSubWidgetsString(ModelScreenWidget.java:98)
        at 
org.ofbiz.widget.model.ModelScreenWidget$Section.renderWidgetString(ModelScreenWidget.java:280)
        at 
org.ofbiz.widget.model.ModelScreen.renderScreenString(ModelScreen.java:164)
        at 
org.ofbiz.widget.renderer.ScreenRenderer.render(ScreenRenderer.java:136)
        at 
org.ofbiz.widget.renderer.ScreenRenderer.render(ScreenRenderer.java:98)
        at 
org.ofbiz.widget.renderer.macro.MacroScreenViewHandler.render(MacroScreenViewHandler.java:157)
        at 
org.ofbiz.webapp.control.RequestHandler.renderView(RequestHandler.java:989)
        at 
org.ofbiz.webapp.control.RequestHandler.doRequest(RequestHandler.java:676)
        at 
org.ofbiz.webapp.control.ControlServlet.doGet(ControlServlet.java:221)
        at 
org.ofbiz.webapp.control.ControlServlet.doPost(ControlServlet.java:89)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at 
org.ofbiz.webapp.control.ContextFilter.doFilter(ContextFilter.java:321)
        at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
        at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
        at 
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
        at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
        at 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at 
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
        at 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
        at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:190)
        at 
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
        at 
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
        - locked <0x00000006f95b1cf0> (a 
org.apache.tomcat.util.net.SocketWrapper)
        at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at 
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
{noformat}
    
The solution would be not to use HashSet but instead a simpler Set class such 
as a Set backed by a List. 




--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to