You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by GitBox <gi...@apache.org> on 2022/11/29 19:25:17 UTC
[GitHub] [daffodil] mbeckerle commented on a diff in pull request #879: Improve SAX parse/unparse performance
mbeckerle commented on code in PR #879:
URL: https://github.com/apache/daffodil/pull/879#discussion_r1035064494
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilUnparseContentHandler.scala:
##########
@@ -17,327 +17,486 @@
package org.apache.daffodil.processors
-import scala.xml.NamespaceBinding
+
+import java.util.concurrent.ArrayBlockingQueue
+import java.util.concurrent.Executors
import javax.xml.XMLConstants
+
+import scala.concurrent.Await
+import scala.concurrent.ExecutionContext
+import scala.concurrent.Future
+import scala.concurrent.duration.Duration
+
+import scala.xml.NamespaceBinding
+import scala.xml.TopScope
+
+import org.xml.sax.Attributes
+import org.xml.sax.Locator
+import org.xml.sax.SAXException
+
import org.apache.daffodil.api.DFDL
import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.infoset.IllegalContentWhereEventExpected
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.EndElement
import org.apache.daffodil.infoset.InfosetInputterEventType.StartDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
import org.apache.daffodil.infoset.SAXInfosetInputter
+import org.apache.daffodil.infoset.SAXInfosetInputterEvent
import org.apache.daffodil.util.MStackOf
-import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.One
import org.apache.daffodil.util.Misc
-import org.xml.sax.Attributes
-import org.xml.sax.Locator
/**
- * DaffodilUnparseContentHandler produces SAXInfosetEvent objects for the SAXInfosetInputter to
- * consume and convert to events that the Dataprocessor unparse can use. The SAXInfosetEvent object
- * is built from information that is passed to the ContentHandler from an XMLReader parser. In
- * order to receive the uri and prefix information from the XMLReader, the XMLReader must have
- * support for XML Namespaces
+ * Provides a cached thread pool that Scala Futures can use so that SAX
+ * unparse() calls can reuse threads, avoiding overhead related to creating new
+ * threads.
+ */
+object DaffodilUnparseContentHandler {
+ val executionContext = new ExecutionContext {
+ private val threadPool = Executors.newCachedThreadPool()
+ def execute(runnable: Runnable): Unit = threadPool.submit(runnable)
+
+ //$COVERAGE-OFF$
+ def reportFailure(t: Throwable): Unit = {} //do nothing
+ //$COVERAGE-ON$
+ }
+}
+
+/**
+ * DaffodilUnparseContentHandler produces SAXInfosetInputterEvent objects for
+ * the SAXInfosetInputter to consume and convert to events that the
+ * Dataprocessor unparse() can use. The SAXInfosetInputterEvents are built base
+ * on information that is passed to this ContentHandler from an XMLReader.
+ *
+ * This class runs the DataProcessor unparse() method in a separate thread,
+ * with a shared ArrayBlockigQueue to provide SAXInfosetInputerEvents. This
+ * queue has a maximum size defined by the saxUnaprseEventBatchSize tunble
Review Comment:
tunble > tunable
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilUnparseContentHandler.scala:
##########
@@ -17,327 +17,486 @@
package org.apache.daffodil.processors
-import scala.xml.NamespaceBinding
+
+import java.util.concurrent.ArrayBlockingQueue
+import java.util.concurrent.Executors
import javax.xml.XMLConstants
+
+import scala.concurrent.Await
+import scala.concurrent.ExecutionContext
+import scala.concurrent.Future
+import scala.concurrent.duration.Duration
+
+import scala.xml.NamespaceBinding
+import scala.xml.TopScope
+
+import org.xml.sax.Attributes
+import org.xml.sax.Locator
+import org.xml.sax.SAXException
+
import org.apache.daffodil.api.DFDL
import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.infoset.IllegalContentWhereEventExpected
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.EndElement
import org.apache.daffodil.infoset.InfosetInputterEventType.StartDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
import org.apache.daffodil.infoset.SAXInfosetInputter
+import org.apache.daffodil.infoset.SAXInfosetInputterEvent
import org.apache.daffodil.util.MStackOf
-import org.apache.daffodil.util.Maybe.Nope
+import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.One
import org.apache.daffodil.util.Misc
-import org.xml.sax.Attributes
-import org.xml.sax.Locator
/**
- * DaffodilUnparseContentHandler produces SAXInfosetEvent objects for the SAXInfosetInputter to
- * consume and convert to events that the Dataprocessor unparse can use. The SAXInfosetEvent object
- * is built from information that is passed to the ContentHandler from an XMLReader parser. In
- * order to receive the uri and prefix information from the XMLReader, the XMLReader must have
- * support for XML Namespaces
+ * Provides a cached thread pool that Scala Futures can use so that SAX
+ * unparse() calls can reuse threads, avoiding overhead related to creating new
+ * threads.
+ */
+object DaffodilUnparseContentHandler {
+ val executionContext = new ExecutionContext {
+ private val threadPool = Executors.newCachedThreadPool()
+ def execute(runnable: Runnable): Unit = threadPool.submit(runnable)
+
+ //$COVERAGE-OFF$
+ def reportFailure(t: Throwable): Unit = {} //do nothing
+ //$COVERAGE-ON$
+ }
+}
+
+/**
+ * DaffodilUnparseContentHandler produces SAXInfosetInputterEvent objects for
+ * the SAXInfosetInputter to consume and convert to events that the
+ * Dataprocessor unparse() can use. The SAXInfosetInputterEvents are built base
+ * on information that is passed to this ContentHandler from an XMLReader.
+ *
+ * This class runs the DataProcessor unparse() method in a separate thread,
+ * with a shared ArrayBlockigQueue to provide SAXInfosetInputerEvents. This
+ * queue has a maximum size defined by the saxUnaprseEventBatchSize tunble
Review Comment:
Can this be set small enough as to enforce sequential behavior, i.e., no parallelism between the caller of the content handler and the unparser?
I continue to be of the opinion that overlap parallelism here is not an advantage. It just muddies the waters about timing and overhead of unparsing.
To reduce overhead, we need to enqueue many events before context switching and allowing the unparser to run. Arguably, we should just queue up events to some max count, or until we get endDocument. For small messages we would then get exactly one context switch per message.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org