I am encountering a performance issue trying to fill in a grid with some data from a webservice.
Thanks to the Timeline analyzer from Chrome, I have found the function which is causing my performance issue. It's due to a loop to get all the data from an xml and converting it into a JSON.
I've tried different loop (each, for, while) expecting improvement but didn't find better than each.
Here is an example of the xml with one child (but in my case there can be 10,000 child nodes):
<DockDistrSearchOutput>
<groupRecord>
<uniqueIdentifier><![CDATA[KP789281]]></uniqueIdentifier>
<supplierCode><![CDATA[10003]]></supplierCode>
<supplierDescription><![CDATA[GROSFILLEX]]></supplierDescription>
<supplierCommercialContractCode><![CDATA[CTCOM01]]></supplierCommercialContractCode>
<supplierCommercialContractDescription><![CDATA[STANDARD EN EURO]]></supplierCommercialContractDescription>
<supplierAddressChainCode><![CDATA[1]]></supplierAddressChainCode>
<supplierAddressChainDescription><![CDATA[FIL1]]></supplierAddressChainDescription>
<articleCode><![CDATA[13A42001]]></articleCode>
<articleDescription><![CDATA[Banane]]></articleDescription>
<logisticVariantCode><![CDATA[2]]></logisticVariantCode>
<logisticVariantDescription><![CDATA[VL0 BANANE C G100]]></logisticVariantDescription>
<weightFactor><![CDATA[0]]></weightFactor>
<purchasePricePerKilo><![CDATA[13]]></purchasePricePerKilo>
<amount><![CDATA[0]]></amount>
<startDate><![CDATA[2016-07-29]]></startDate>
<endDate><![CDATA[2016-07-31]]></endDate>
<crossDockDiscount />
<crossDockMargin />
<extraMargin><![CDATA[3]]></extraMargin>
<listPrice />
<costPriceRD />
<oldSupplierCode><![CDATA[10003]]></oldSupplierCode>
<oldSupplierCommercialContractCode><![CDATA[CTCOM01]]></oldSupplierCommercialContractCode>
<oldSupplierAddressChainCode><![CDATA[1]]></oldSupplierAddressChainCode>
<oldArticleCode><![CDATA[13A42001]]></oldArticleCode>
<oldLogisticVariantCode><![CDATA[2]]></oldLogisticVariantCode>
<oldStartDate><![CDATA[2016-07-29]]></oldStartDate>
<oldEndDate><![CDATA[2016-07-31]]></oldEndDate>
</groupRecord>
</DockDistrSearchOutput>
And here is the loop used to get the data (15900ms for my test case) :
function getDataFromXml(xml){
var data = [];
$(xml).children().each( function (index) {
uniqueNumber++;
var recStatus = ORIGINAL;
if(this.getAttribute("recordState")!=null){
recStatus = this.getAttribute("recordState");
}
this.setAttribute("recordState", recStatus);
this.setAttribute("lineNumber", uniqueNumber);
var record = [];
if(this.getAttribute("checkedLine") == "true"){
record["checkedLine"] = true;
}else
record["checkedLine"] = false;
// Build the array by reading XML Tagname/value
record["id"] = "ID"+uniqueNumber;
$(this).children().each(function () {
record[this.tagName] = this.text;
});
record["recordState"] = recStatus;
record["rowXML"] = this;
data.push(record);
record = null;
recStatus = null;
});
return data;
}
Here are other try to get the data faster:
function getDataFromXml(xml){
var data = [];
$(xml).children().each( function (index) {
uniqueNumber++;
var recStatus = ORIGINAL;
if(this.getAttribute("recordState")!=null){
recStatus = this.getAttribute("recordState");
}
this.setAttribute("recordState", recStatus);
this.setAttribute("lineNumber", uniqueNumber);
var record = [];
/* First try
var a = $(this).children();
var l = a.length;
while(l--){
record[a[l].tagName] = a[l].text;
}*/
//Second try
var tmp = "{", cur = null;
for(var i =0, ln=this.childElementCount; i<ln;++i)
{
cur = this.children[i];
tmp += '"'+cur.tagName+'":"'+cur.text.replace('"', '')+'",';
}
tmp +='}';
tmp = tmp.replace(',}', '}');
record=JSON.parse(tmp);
if(this.getAttribute("checkedLine") == "true"){
record["checkedLine"] = true;
}else
record["checkedLine"] = false;
// Build the array by reading XML Tagname/value
record["id"] = "ID"+uniqueNumber;
record["recordState"] = recStatus;
record["rowXML"] = this;
data.push(record);
tmp = null;
cur = null;
record = null;
recStatus = null;
});
return data;
}
A try with only JavaScript (9600ms in my test case):
function getDataFromXml(xml){
var data = [];
var a = xml.getElementsByTagName("groupRecord");
var l = a.length;
while(l--){
uniqueNumber++;
var recStatus = ORIGINAL;
var groupRec = a[l];
if(groupRec.getAttribute("recordState")!=null){
recStatus = groupRec.getAttribute("recordState");
}
groupRec.setAttribute("recordState", recStatus);
groupRec.setAttribute("lineNumber", uniqueNumber);
var record = [];
var b = groupRec.childNodes;
var j = b.length;
while(j--){
record[b[j].tagName] = b[j].text;
}
if(groupRec.getAttribute("checkedLine") == "true"){
record["checkedLine"] = true;
}else
record["checkedLine"] = false;
// Build the array by reading XML Tagname/value
record["id"] = "ID"+uniqueNumber;
record["recordState"] = recStatus;
record["rowXML"] = groupRec;
data.push(record);
tmp = null;
cur = null;
record = null;
recStatus = null;
groupRec = null;
}
return data;
}
If someone has any advice to increase the performance of my loop? Thanks in advance!
Edit: Thanks to Jaromanda X I have improved the performance by using only JavaScript.