JSON Performance Problem


#1

Hi.

After moving to JSON from XML I’ve noticed that things became quite slow.
I run a small performance test that confirmed my suspicion, it shows that JSON it much slower than XMLDOCUMENT:

**** Counter for “JSON” started at: 27 Jun 2011 3:33:39pm
Performance count for “JSON” - average over 50 run(s) = 528 microsecs, total = 0.02644 seconds
Performance count for “JSON” - average over 50 run(s) = 526 microsecs, total = 0.02630 seconds
Performance count for “JSON” - average over 50 run(s) = 519 microsecs, total = 0.02597 seconds
Performance count for “JSON” - average over 50 run(s) = 502 microsecs, total = 0.02515 seconds
Performance count for “JSON” - average over 50 run(s) = 497 microsecs, total = 0.02485 seconds
Performance count for “JSON” - average over 50 run(s) = 511 microsecs, total = 0.02556 seconds
Performance count for “JSON” - average over 50 run(s) = 517 microsecs, total = 0.02586 seconds
Performance count for “JSON” - average over 50 run(s) = 508 microsecs, total = 0.02545 seconds
Performance count for “JSON” - average over 50 run(s) = 500 microsecs, total = 0.02502 seconds
Performance count for “JSON” - average over 50 run(s) = 512 microsecs, total = 0.02563 seconds

**** Counter for “XML” started at: 27 Jun 2011 3:52:57pm
Performance count for “XML” - average over 50 run(s) = 258 microsecs, total = 0.01295 seconds
Performance count for “XML” - average over 50 run(s) = 264 microsecs, total = 0.01324 seconds
Performance count for “XML” - average over 50 run(s) = 263 microsecs, total = 0.01315 seconds
Performance count for “XML” - average over 50 run(s) = 268 microsecs, total = 0.01345 seconds
Performance count for “XML” - average over 50 run(s) = 256 microsecs, total = 0.01282 seconds
Performance count for “XML” - average over 50 run(s) = 259 microsecs, total = 0.01299 seconds
Performance count for “XML” - average over 50 run(s) = 258 microsecs, total = 0.01293 seconds
Performance count for “XML” - average over 50 run(s) = 267 microsecs, total = 0.01336 seconds
Performance count for “XML” - average over 50 run(s) = 258 microsecs, total = 0.01292 seconds
Performance count for “XML” - average over 50 run(s) = 286 microsecs, total = 0.01435 seconds

This is my small test:



void ServerProxy::testPerformance()
{
	File jsonFile("D:/Temp/data.json");
	File xmlFile("D:/Temp/data.xml");
	String jsonString = jsonFile.loadFileAsString();
	String xmlString = xmlFile.loadFileAsString();

	PerformanceCounter pcJSON("JSON",50, File("D:/Temp/json.log"));

	for (int i = 0; i < 500 ; i ++)
	{
		pcJSON.start();
		testJSONPerformance(jsonString);
		pcJSON.stop();
	}

	PerformanceCounter pcXML("XML",50, File("D:/Temp/xml.log"));

	for (int i = 0; i < 500 ; i ++)
	{
		pcXML.start();
		testXMLPerformance(xmlString);
		pcXML.stop();
	}

}

void ServerProxy::testJSONPerformance( String jsonString )
{
	var jsonVar = JSON::parse(jsonString);
	var widgetVar = jsonVar[Identifier("widget")];
	bool isDebug = widgetVar[Identifier("debug")];
	var textVar =  widgetVar[Identifier("text")];
	int vOffset = textVar[Identifier("vOffset")];
}

void ServerProxy::testXMLPerformance( String xmlString )
{
	XmlDocument myDocument (xmlString);
	XmlElement* mainElement = myDocument.getDocumentElement();
	int isDebug = mainElement->getChildElementAllSubText("debug","1").getIntValue();
        XmlElement* textXMLNode = mainElement->getChildByName("text");
	int vOffset = textXMLNode->getChildElementAllSubText("vOffset","1").getIntValue();
	delete mainElement;
}

data.json:

{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    },
    "text": {
        "data": "Click Here",
        "size": 36,
        "style": "bold",
        "name": "text1",
        "hOffset": 250,
        "vOffset": 100,
        "alignment": "center",
        "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
}}

data.xml:

<widget>
  <debug>on</debug>
  <window title="Sample Konfabulator Widget">
    <name>main_window</name>
    <width>500</width>
    <height>500</height>
  </window>
  <image src="Images/Sun.png" name="sun1">
    <hOffset>250</hOffset>
    <vOffset>250</vOffset>
    <alignment>center</alignment>
  </image>
  <text data="Click Here" size="36" style="bold">
    <name>text1</name>
    <hOffset>250</hOffset>
    <vOffset>100</vOffset>
    <alignment>center</alignment>
    <onMouseUp>
      sun1.opacity = (sun1.opacity / 100) * 90;
    </onMouseUp>
  </text>
</widget>

#2

Well I wrote the XML parser many years ago and have fine-tuned it ever since. I wrote the JSON parser a couple of weeks ago and haven’t made any attempt to optimise it! Feel free to do some profiling and let me know the hot-spots if its performance is important to you.


#3

I tried to find a benchmark of C++ JSON parsers and lean the best algorithm but it seems that there’s no such benchmark at the moment.
This thread at StackOverflow ( http://stackoverflow.com/questions/245973/whats-the-best-c-json-parser ) suggests some parsers like JsonCpp.


#4

There’s nothing wrong with my parser design.

Bear in mind here that the XML parser is seriously fast and all the objects it creates are specially designed to be extremely quick to create and return. The var object is a general-purpose class, and gets copied by value, so passing them around can add some overhead. Be careful when you do your test that you don’t make a copy of the return value, or that in itself will probably half your execution time!