Using XML in Performance Sensitive Apps?
A Parser's Baggage queries: "For the last couple of years I've been working with XML based protocols and one thing that keeps coming up is the amount of CPU power needed to handle 10, 20, 30 or 40 concurrent requests. I've ran benchmarks on both Java and C#, and my results show that on a 2ghz CPU, the upper boundary for concurrent clients is around 20, regardless of the platform. How have other developers dealt with these issues and what kinds of argument do you use to make the performance concerns know to the execs. I'm in favor of using XML for it's flexibility, but for performance sensitive applications, the weight is simply too big. This is especially true when some executive expects and demands that it handle 1000 requests/second on a 1 or 2 cpu server. Things like stream/pull parsers help for SOAP, but when you're reading and using the entire message, pull parsing doesn't buy you any advantages."
<?xml version="1.0" encoding="UTF-8"?>z RKiQIXOSMfOskEqGRJJIpshcyjxLokLGIoRkCplDvP/zVhe/Dv /n+77d5/5+nude92zn7LPWXmt91mevvc+++1Vl5I7AhBB0+/v6 G5rpaNAwCBRiY3SRTkwMQid8wtza1NDO3M3UBAIDLk9C0Ajglz xEB4LEwuEQJAoN0SPcBsFh0Dg48F+yEAwUhUMC/6UCIVyfhuDQ CBRwLS4OoTO1NiH0DCH5x8XO9DwdICEchoPQQX//wNCQn78h1n Q0v1qQGDjuzzYUHIMFtSGxoGexSAQS3IZFgNpQ8A3akKg/2mCA NDBwG/rPZ2EwJO5PmWEwFBz0LByHAN0Hx6FB9yFR0D/1ANrgf+ oLA4wFB7ehQc9i4CjQOzBwDEgPLHAjqA2HBr0XB4eC25BIDKgN jQHpi8NB/3wHHJD6T1ngUAT2T92At4L8BQ4Y+M/3wmFQLBTUhg DZHA5DgcYeDsNCQc8Cwvw5pnA4HA16LzDMoHfAMWD5EFDwOxBw 5J8+DkcAwQBqw8DA/eEwoP6QgHagNiQK9CwSAwM/i0OAxhkFQ4 P6QyFAfg9HoeEgPVBAwP3ZhobiQGOP3sBGaBQK9F7ArUD3YcBY AgfcGfRewByg/jAYkD/DMThQ7MOxMAzoPiwS/CwWUATUhgU/i4 OCsAmACBho/HAosB44DAgTAbcC+R8CGP0/bY6AgrETAcWAxh4B xYFiEAGDQ8FtSMSfY4qAoTF/jh8ChoOCZIHDQPEBeAHuz3hDwM GxjwAGHyQzoAioPwQC/qePIxAoUPwiEBgsaEyRUBCOI5CA94La kDjQGCAxCNA7gNtAbSgYCCeBvAvyA4LIoPeiAID+sw0NA+UKBB oBwjoEGngY1IYFjxUGCAdQGxwNkg+zwRhgMAiQjTA4UCwAaA8F 9YfdwK+waCxIDywO7Pc4GCg3InAI8Pjh0FDws1hQHkRCoSAsRg Ie/acsSCgKlOORgEuC78OBxgoJgyP/lA8JhMef44KEYU">
<session session="2003-06-27T17:03:39GMT+08:00" session-serialNumber="06302003b01" encode-version="1.8"><structure id="bzip2"><info cdate="2003-07-12T14:57:07+08:00" expiry-date="" id="OBD12" mdate="2003-07-12T14:57:07+08:00" name="" notes="" organization="Sd7+/OtxQ==" version="1.0"/><content code="H4sIAAAAAAAAAMy9CThW2xc/rpQpYxKJvIakEu88IJk
Hint: The shorter the header, the faster.
P.S. This is a joke, for humor-impaired
1. I use DOM objects, in this case the MSXML free threaded model, to handle xml strings and read out the string only at the last point.
2. I would also suggest using wstring/string in the STL library as you can reserve string buffers in advance in case you have to handle the XML as strings, that's if your using c++, don't know much about c#/java sorry.
using this method I have manage to push it to ~200 concurrent requests.
mlati
It's hard to parse. That takes cycles. You can probably tweak the parsing to make it faster, but that might not get you from 20 concurrent to 2000 concurrent.
You've got two choices. More processors, which are pretty cheap right now; or a simpler and more specialized language to replace XML.
If tits were wings it'd be flying around.
It might be of some use if you actually told us what libraries you used, what methods, etc, not just "I tried to parse some XML files". Is that result of 20 concurrent requests using a SAX parser or DOM? Are you using the standard java DOM implementation (slow and bulky), or one of the slicker ones like JDOM, dom4j, etc (there's a bunch you should have a look at). Another thing you could do t o improve performance is to identify the points where you don't really need a DOM (eg you're just reading the values once and discarding) and use a SAX parser instead to fill in a custom class or a hashtable or such.
Daniel
Carpe Diem
well there's your problem.
With mod_perl, XML::LibXML, XML::LibXSLT, I EASILY get 100/per second. and my code is shitty.
what do you do with the XML, do you generate HTML from it with XSLT or what?
another thing to try: intelligently cache your results in shared memory. you can easily double performance or more.
I love XML, and I use it anywhere I can get away with it, but I know from my old job, that switching to a binary protocol that is streamlined for the task at hand can give you performance gains over XML protocols that are just plain ridiculous.
I think we the results we measured were something like 1000 times as many connections on a custom binary protocol over an XML based one.
That was in C++ mind you. YMMV.
Give me liberty or give me kill -s 9
The homescreen app in the MS Smartphone has it's config specified by XML.
For speed, and to avoid parser-usage memory leaks that may exist or be introduced by improper usage of other homescreen plugin developers a seperate app loads all the homescreen plugins feeding them their xml config. This app then streams the plugins out in a binary format (each plugin must support streaming) and then quits, solvin gany memory leaks.
Then the homescreen app streams them back in and out again as needed without the xml speed hit or danger of leaks from xml parser.
blog.sam.liddicott.com
First off, any chance you could post those benchmarks? 20 requests/second seems low, I'm wondering what the rest of the setup was.
For the first part: we had performance problems on an app where the customer had insisted on xml everywhere. However, in one particularly critical part of the system we were getting hammered by the garbage collection overhead of SAX (its efficient for text in elements, but not for attribute values or element names).
Anyway - we knew what was coming into the system as we were also the producers of this xml at an earlier stage. So we wrote a custom SAX parser that only supported ASCII, no DTDs, internal subsets etc; and wrote it to return element/attribute names from a pool (IIRC we used a ternary tree to store this stuff, so we didn't need to create a string to do the lookup).
It was like night and day. XML parsing dropped from generating 80% of the garbage to about 5% and it just didn't appear on my list of performance issues from then on.
Java strings do a lot of copying, the point is to get yourself as close as possible to a zero-copy xml parser as you can.
You might want to look at switching toolkits entirely as well - GLUEs benchmarks sound a lot better than yours.
Have you profiled your application?
/db connection/db speed). Look at your own code with a profiler to see the bottleneck.
:-)
Do you test on a dedicated test system?
If your only getting 20 concurrent users regardless of platform (could be, it really depends on the setup and complexity of the problem), maybe the technology isn't the problem but it could be network etc.
benchmarking is fine, but if you do it on the whole system you don't know what the problem really is.
Find out precisely what the problem is (network/xml parser/your app logic
If you do end up blaming the parser, change it! (and i don't mean using a different parsing method as most use a sax parser to generate the tree anyway) there are parsers that are 50% faster than those used as standard (xerces isn't the fastest java parser around!). Also look at the most efficient way of using the tree (java dom is, as already said, slow in usage) or maybe you can go from sax directly to your object model without using a tree but building your own sax parser.
If you can't get a performance gain (which I really doubt), be honest to your client. "If you want to do it that way it's going to cost you" or "it can't be done on one machine" how did they get the idea they could handle 1000's of requests a second anyway? Work on your expectationmanagment (basicly work on making their expectations more realistic). If you promise mountains make sure you can deliver them first. If you can't deliver them make them not want mountains but molehills
I don't understand what the problem is here. You're saying that you like XML, but it's slow. Fine, don't use it. It's not like it's the only tool in existence, is it?
Dave
I write a blog now, you should be afraid.
The solution would be to load the DOM in the backend and have front-end applications access it.
You could try using AOLserver as a multi-threaded web server and tDOM as your DOM processor.
-- Don't Tase me, bro!
Many have asked about what libraries you are using to get at the XML. Loading up a whole DOM document is indeed quite inefficient.
.Net platform, I would suggest using the XmlTextReader class. This class and its bretheren are the parsers underlying Microsoft's DOM implementation, and anything else that needs access to XML. The class is noted for its strong performance advantage over loading a DOM or using XPathNavigator - and it is indeed a very lightweight class. It is certainly not as comfortable to use as the DOM, but neither is it incredibly painful, especially if your documents are relatively simple.
On the
Give XmlTextReader a shot.
This is an example of the wrong way to use XML.
XML is great because it's extensible and a markup language. It's great for storage, configuration files, and certain forms of data transmission (which is just a sub-set of storage).
What XML is not good for is performance-critical transmission protocols. It's too verbose and too complex, and both are bad for protocols. That is the mistake made by the author of the article. Go with a structured protocol and skip the XML.
"Times have not become more violent. They have just become more televised."
-Marilyn Manson
I'd have to agree with people's assertion that performance intensive apps should use a custom protocol and preferably binary based or some kind of delayed stream parser that only accesses the XML node when the app calls for it. I believe Sun has an API in the works for XML stream parsing JSR 317. It's too bad the jsr is still in public review phase. I've written custom parser in the past using SAX and it can definitely improve performance if you convert it to an object model. The question is trade off between being generalized and performance.
In the case of a webservice that uses schema, it's going to be hard to get around the performance issue. An obvious solution in situations where XML is required is to send as little as possible and only get the nodes you need. In that respect XPP2 and XmlTextReader help, until you need the entire document and you use the whole document.
First, what does your program do? Why are you so sure XML takes so much time to process? And, is really XML the best format for your application?
/> is definitely not a good use of XML. For some kinds of data perfectly good formats already exist.
You could get speed improvements by making things simpler. If XML data takes so much to process on your server then I guess you have two possible problems: Either the amount of data is very big, or you're doing something wrong. You don't really have to use every feature of XML in your program.
Make sure you also understand what XML is for. Sending bitmaps by transferring gigabytes of <pixel r="10" g="100" b="0"
Also, do you really need XML? If it's something time or bandwidth critical, rolling your own could be easier. Especially if you don't need a lot of interoperation with other programs. Binary protocols are quite easy to make extensible, too. For example, you can send everything in a kind of container. Say, a structure with a char or int for a command ID, and a long for a command length. Then put any data inside. That's just 5-8 bytes per header, and should let you add stuff easily.
In my experience that seems about right. I'm using AxKit with caching shutoff and my own Language module and those are about the results I get. For me its not a big deal since speed isn't that important.
What little I have looked at the speed issue points to 2 things. First caching probably helps alot. Second it may pay to customize the output code. From the few performance tests I've done libxml's output code was the main slow down. Keeping in mind the performance testing was done on C++ code not perl code. It may be possible to write something that walks the DOM and spews the result in a much faster fashion.
Sounds like you make extensive use of DOM-based parsing. Ever look at the memory footprint required to parse a large XML document using a DOM parser? I've seen 1MB XML files that require >100MB of memory to parse to a DOM. Event-based parsing helps a lot here.
Now, if you need to manipulate the DOM (and thus require DOM-based parsing), I would suggest caching. One thing some of the commercial XML-based databases do is to parse XML files when they are added to the DB, storing the resulting DOM rather than the original XML document. Then, they make heavy use of lazy loading and in-memory caching of the DOM so that the entire DOM doesn't need to be stored in memory (if all you are concerned about is a changine a small part of the DOM), and so that frequent accesses to the same nodes can be speeded up.
Finally, you can use one of the non-standard DOM-like parsers, such as JDOM. These things don't require the memory footprint nor the parsing time that traditional DOM parsers require. Good stuff.
Of course, I would suggest you use a combination of all three. JDOM + stored, post-parsed DOM + in-memory DOM node caching can result in a solution that is as fast as using proprietary binary representations while still retaining all of the flexibility and compatibility of XML.
--Be human.
--toomuchPerl
Even if the parsing could be done in zero execution time, XML is still consuming excessive network bandwidth.
XML is very flexible, and an excellent solution when flexibility is truly required in what the next data element is.
Howeveer, doubling (or worse) the network bandwidth used in downloading a table in order to allow each record to have a different set of fields is just plain stupid.
A realistic compromise is to use XML to describe different "row formats" that will be used. And then to deliver each row in a compact tagged binary format.
Save the full flexibility for transfers that need it, a text document is a great example. There are too many options for what might apply to the next paragraph for a fixed format to be useful.
If you are using C/C++ check out gSOAP. It goes real fast, runs on many platforms, and I've used it to talk to Java, PHP, C# etc without a problem. It does about 3000 transactions per second on my little desktop PC. Obviously 100 parallel clients aren't going to get that speed, but it sounds like it will be much faster than what you're using!
http://www.cs.fsu.edu/~engelen/soap.html
So you are the guys who write .processor code so I have to keep adding ram all the time. .processor languages like xml are really the invention of an evil computer marketing genuis. Who ever the SOB is, it is getting silly.
OH THE SHAME I fell off the wagon and use sigs again!
I have to agree with many of the comments. The parser you choose is the most important decision. DOM is typically a memory hog and takes time. In my experience the MSXML 4.0 parser is very fast, written in C, etc. DOM is easier to user, but obviously can have some downsides. XML is great for portability and faster development, but performance concerns can arise.
Find out where the bottleneck lies. If you are running an XSLT processor on the server, that will limit your request/sec. I've found that stream XML from the server to a client (such as IE6, gasp) and having the client render to HTML is wicked fast. The XSLT parser in IE renders asynchronously allowing the results to be displayed before the entire doc is loaded. Of course this is MS specific stuff I've experienced, etc.
SAX is faster for grabbing XML events. While writing a web spider, I was parsing HTML using an HTML parser. I switched from that to regex and saw crawl speed increase significantly. It depends if you need to whole XML doc or not.
You may want to try loading the XML DOM once and serialize the binary. You could then ship the binary around town. Macromedia has some tools like this that can send binary objects to a flash client, etc. Limit the parsing.
Another tip... if you have control over the XML schema, you may want to research how to structure XML for performance. I've heard that attribute heavy XML docs are more efficient than docs with embedded data, etc. Also look into some XML tricks like IDs, etc.
Good luck in your pursuit. Choose your parser carefully. If testing turns out negative, you may just want to use some binary data. XML is a wonderful technology designed to aid in system integration, and ease of use... but it comes at a price.
From what I've heard, you can get much higher overall data transfer rates using CORBA than XML. It uses a binary protocol, but with a customisable API. Depending on your application, this may be a viable solution - plenty of open-source ORBs are available, with omniorb quite well known as being one of the fastest.
We need to know more about what you are doing to really be able to understand.
For example: Are you serializing XML to/from objects in Java or C#? Are you writing custom serializers? Or are you using the built in introspective type serializers for Objects?
Are you using Document centric SOAP, in which case your doing more parsing and logical operation that serialization/deserialization?
Do you really know that SOAP is your bottleneck? Have you profiled it?
I'm using SOAP in production with J2EE right now with no problems. We use both Document centric (DOM Element[]) and serialization/deserialization.
It's fast, without problems. We are using load-balancing/clustering as well, and SOAP does not seem to be the scale-bottleneck for us. The write's/tx's to the database are a bigger problem. Smart usage of caching solves the problem for us.
--Stupidity is Self Curing!
Most of the work in an off the shelf XML parser is verifying that the XML is "good" or matches some schema specification. If its coming from one of your programs and going to one of your programs and you've done reasonable debugging, its good. You just parse it and use it. Not enough has been done to optimize the "trusted" app communications scenario even though in reality, that's probably 95%+ of the actual usage of XML. Very few sites are actually publishing XML that is really getting used by programs and pages other than the ones they've written.
Parsing it is very easy and quick if you're in full control of the encoding. You can optimize your parser greatly by choosing not to handle the general case, but to instead handle only what your specific encoder generates.
Use the protocol, pick up the buzz word for your app, but leave the pain of the generalities meant to handle some free data exchange world that is 15 years in the future out. When the semantic net comes about and applications can actually use any XML without needing to be written to use that XML schema, then you can worry about the general case.
> This is the problem when high level coders try to
> design low level systems, they...assume that the
> high level procedures/objects that they work with
> are some sort of magic that "just happens"
You mean like this RFC:
http://www.ietf.org/rfc/rfc3252.txt
which basically turns IPV4 packets in XML? Just imagine sending XML on these networks!;-)
This is somewhat simplified, but code like: // handle surname // handle firstname // handle surname // handle firstname
if (strcmp(tag, "surname") == 0)
;
else if (strcmp(tag, "firstname") == 0)
;
is obviously a whole lot slower than code like:
if (tagByte == TAG_SURNAME)
;
else if (tagByte == TAG_FIRSTNAME)
;
The problem with XML is that it is a general-purpose textual encoding, and as with most textual encodings it requires more bytes than a dedicated binary encoding does. The result is that it requires many more cycles to process.
If speed it of prime importance then don't use XML.
ASN.1 with it's various encodings (BER/DER/PER), as used by PKI standards to encode things like keys and X.509 certificates (to name a very small fraction of what it is used for) can be very compact. It takes quite a bit more effort to understand, but it does result in efficient encodings of data. This is one of the reasons why ASN.1 has been an international standard for many years and is used for protocols in mobile phone networks.
If you can do with basic parsing, the nanoxml and picoxml libraries will put everything else to shame.
-I like my women like I like my tea: green-
You do realize that, to some degree, what he described is precisely how TCP/IP's wire protocol was meant to work, right?
But of course, we all know how awful an idea TCP/IP was.
We use Biztalk for a lot of enterprise-level XML parsing, and we get up to 200+ documents parsed per second. Of course, there's a lot of hardware being used - 3 2-processor processing boxes handling the workload, for example. But for a system pushing and pulling messages in and out of a SQL Server database it works pretty well. And these are pretty decently sized documents, doing mapping and using all kinds of functoids and whatnot.
"On the Internet, nobody knows you're a dog!" - a dog
Get a 64 bit processor with lots of memory and cache EVERYTHING. I'm using an app that caches the entire database(currently about 10 mg).It's lightning fast for hundreds of users. Suppose thousands could be handled.
my other sig sucks less
Can you be more specific about why your SOAP messages are so large? What do they contain? What platform is giving you such poor performance? BTW it makes great sense to have the ability to use XML to communicate across heterogenous application boundaries, but why not use a framework that abstracts the wire format? For example, you could leverage binary-format remoting on .NET or a similar technology on Java (RMI?) that has the capability to communicate via XML, but can also use its own efficient wire format for the app domain boundary.
I agree that you should have the capability to communicate in XML for interoperability, but do not always limit your middleware to the lowest common denominator.
You might also want to re-examine your system design to minimize the amount of data passing over the SOAP application boundary. But I can't really tell what you're trying to achieve, in terms of application, processing or bandwidth.
r4lv3k
If you do end up blaming the parser, change it! (and i don't mean using a different parsing method as most use a sax parser to generate the tree anyway) there are parsers that are 50% faster than those used as standard (xerces isn't the fastest java parser around!).
I got enormous performance gains by switching from xerces-j to dom4j in one application. I also found its API much more straightforward.
On the other hand, I have run into a few bugs in dom4j -- but it was simple enough to fix them and submit patches.
If you have 20 conections and each one is doing 20mB/s I don't think parser issues are your problem. Similarly it sounds likely that your problem is with the XML implementation (poor memory allocators) rather than xml per say. Or is it that xml is bloating your file format? I haven't had any problems with xml performance on clients running on 33 mhz 68 processors.
On person mentioned using a C struct that you can whack directly into memory, and several others suggested using caching the DOM somehow. Of course these combine perfectly together. Get the sender to put a unique id or md5 in the header. If you don't have a file with that name in the cache dir then parse and dump the parsed structure to disc. If the file exists then pull file into memory and send the rest of the incoming byte stream to /dev/null. Of course caching won't help you if all your incoming XML files are unique.
Phillip.
Property for sale in Nice, France
Take a look at TIRPC and the XDR RFCS. Nothing beats a streamlined binary. Patrick
There are quite a few XML hardware transformation engines on the market now. Has anyone spent any time looking at them? Many claim to process XSLT at wirespeed...
But that's an evil optimization unless you've already designed your DTD to limit memory allocations. You wouldn't put detailled client information in every order item record when using a database, would you?
I once attended an international conference where the speaker "proved" XML/XSLT had poor performance... with an example doing a simple lookup in an XML file. The XML data was shamely unstructured and the lookup algorithm was O(n2)!
Design your DTD with the care you naturally take to databases, design your code to avoid multiple passes over the XML and everything should be OK. Never forget things usually go pretty well with databases only thanks to SQL optimizers: most tables and requests are badly designed.
- Avoid redundant data: factorize them by using a relational-like XML structure, use entities for constants
- Get rid of any data you could retrieve another way: just put ids in the XML and store detailled persistent data in a hashtable.
- Don't misuse XML: avoid over-nested structure, prefer attribute to sub-element for singletons, use the ID/IDREF mechanism.
With these common sense rules, you can achieve several hundreds of requests per second per cpu. Go to XML Pattenrs for further reading.