This is an automated email from the ASF dual-hosted git repository.
harbs pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push:
new fe5f7d2 Speed up XML parsing of larger datasets by 30-50% by using
faster DOM APIs, shorter string lookups, eliminating unnecessary string copies,
and other changes.
new 41ee8ed Merge pull request #1025 from estanglerbm/xml-faster-parse
fe5f7d2 is described below
commit fe5f7d2c3858957a53e732b251495ef6350a32de
Author: Edward Stangler <[email protected]>
AuthorDate: Wed Dec 30 22:01:08 2020 -0600
Speed up XML parsing of larger datasets by 30-50% by using faster DOM APIs,
shorter string lookups, eliminating unnecessary string copies, and other
changes.
---
frameworks/projects/XML/src/main/royale/XML.as | 66 ++++++++++++++++++--------
1 file changed, 45 insertions(+), 21 deletions(-)
diff --git a/frameworks/projects/XML/src/main/royale/XML.as
b/frameworks/projects/XML/src/main/royale/XML.as
index 27c7103..0b2d810 100644
--- a/frameworks/projects/XML/src/main/royale/XML.as
+++ b/frameworks/projects/XML/src/main/royale/XML.as
@@ -34,20 +34,24 @@ package
* The XML QName can be a significant percentage of an XML
object size.
* By retaining a lookup of QNames and reusing QName objects,
we can save quite a bit of memory.
*/
- static private var _nameMap:Object = {};
+ static private var _nameMap:Object = Object.create(null);
+ static private var _attrNameMap:Object = Object.create(null);
static private function
getQName(localName:String,prefix:*,uri:String,isAttribute:Boolean):QName{
localName = localName || "";
var prefixKey:String = prefix == null ?
'{$'+prefix+'$}' : prefix ; // handle nullish values differently to the potent
'null' or 'undefined' string values
uri = uri || ''; //internally there is no concept of
'any' namespace which is what a null uri is in a QName.
- var key:String = localName + ":" + prefixKey + ":" +
uri + ":" + isAttribute;
- var qname:QName = _nameMap[key];
+ var key:String = (!prefix && !uri ? localName :
localName + ":" + prefixKey + ":" + uri);
+ var qname:QName = (isAttribute ? _attrNameMap[key] :
_nameMap[key]);
if(!qname){
qname = new QName(uri, localName);
if(prefix != null)
qname.setPrefix(prefix);
if (isAttribute) qname.setIsAttribute(true);
- _nameMap[key] = qname;
+ if (isAttribute)
+ _attrNameMap[key] = qname;
+ else
+ _nameMap[key] = qname;
}
return qname;
}
@@ -213,7 +217,8 @@ package
*/
static public function clearQNameCache():void
{
- _nameMap = {};
+ _nameMap = Object.create(null);
+ _attrNameMap = Object.create(null);
}
/**
@@ -333,12 +338,34 @@ package
return xml;
}
- static private function
iterateElement(node:Element,xml:XML):void
+ static private function
polyFillNodeGetAttributeNames(node:Element):Array
{
+ var ret:Array = new Array();
var i:int;
- // add attributes
var attrs:* = node.attributes;
var len:int = node.attributes.length;
+ for(i=0;i<len;i++)
+ {
+ ret.push(attrs[i].name);
+ }
+ return ret;
+ }
+
+ private static var hasNodeGetAttributeNames:Boolean = false;
+ private static var isInitStatic:Boolean = false;
+
+ static private function
iterateElement(node:Element,xml:XML):void
+ {
+ if (!isInitStatic)
+ {
+ hasNodeGetAttributeNames =
(node["getAttributeNames"] ? true : false);
+ isInitStatic = true;
+ }
+
+ var i:int;
+ // add attributes
+ var attrNames:Array = (hasNodeGetAttributeNames ?
node["getAttributeNames"]() : polyFillNodeGetAttributeNames(node));
+ var len:int = attrNames.length;
//set the name
var localName:String = node.nodeName;
var prefix:String = node.prefix;
@@ -351,7 +378,7 @@ package
var ns:Namespace;
for(i=0;i<len;i++)
{
- var att:Attr = attrs[i];
+ var att:Attr =
node.getAttributeNode(attrNames[i]);
if ((att.name == 'xmlns' || att.prefix ==
'xmlns') && att.namespaceURI == 'http://www.w3.org/2000/xmlns/') {
//from e4x spec: NOTE Although
namespaces are declared using attribute syntax in XML, they are not represented
in the [[Attributes]] property.
if (att.prefix) {
@@ -365,11 +392,8 @@ package
}
// loop through childNodes which will be one of:
// text, cdata, processing instrution or comment and
add them as children of the element
- var childNodes:NodeList = node.childNodes;
- len = childNodes.length;
- for(i=0;i<len;i++)
+ for(var nativeNode:Node=node.firstChild; nativeNode;
nativeNode=nativeNode.nextSibling)
{
- var nativeNode:Node = childNodes[i];
const nodeType:Number = nativeNode.nodeType;
if ((nodeType == 7 &&
XML.ignoreProcessingInstructions) ||
(nodeType == 8 &&
XML.ignoreComments)) {
@@ -389,7 +413,7 @@ package
static private function fromNode(node:Node):XML
{
var xml:XML;
- var data:* = node.nodeValue;
+ var data:String;
switch(node.nodeType)
{
case 1:
@@ -405,22 +429,26 @@ package
case 3:
//TEXT_NODE
if (XML.ignoreWhitespace) {
- data = data.trim();
+ data = node.nodeValue.trim();
if (!data) return null;
}
+ else {
+ data = node.nodeValue;
+ }
xml = new XML();
xml.setValue(data);
break;
case 4:
//CDATA_SECTION_NODE
xml = new XML();
- data = "<![CDATA[" + data + "]]>";
+ data = "<![CDATA[" + node.nodeValue +
"]]>";
xml.setValue(data);
break;
//case 5:break;//ENTITY_REFERENCE_NODE
//case 6:break;//ENTITY_NODE
case 7:
//PROCESSING_INSTRUCTION_NODE
+ data = node.nodeValue;
xml = new XML();
xml._nodeKind = PROCESSING_INSTRUCTION;
//e4x: The [[Name]] for each XML object
representing a processing-instruction will have its uri property set to the
empty string.
@@ -436,7 +464,7 @@ package
break;
case 8:
//COMMENT_NODE
-
+ data = node.nodeValue;
xml = new XML();
xml._nodeKind = COMMENT;
//e4X: the name must be null (comment
node rules)
@@ -581,7 +609,7 @@ package
_value = '';
}
}
- initializeClass();
+
if(!_class_initialized)
{
Object.defineProperty(XML.prototype,"0",
@@ -595,10 +623,6 @@ package
_class_initialized = true;
}
}
- private static function initializeClass():void
- {
-
- }
private static var _class_initialized:Boolean = false;