{"id":2916,"date":"2016-03-19T05:54:41","date_gmt":"2016-03-19T05:54:41","guid":{"rendered":"http:\/\/www.ericwhite.com\/home2\/bm8qcmjy\/public_html\/blog\/?page_id=2916"},"modified":"2016-03-20T13:52:09","modified_gmt":"2016-03-20T13:52:09","slug":"linq-to-xml-for-javascript-gaining-performance-through-atomization","status":"publish","type":"page","link":"https:\/\/www.ericwhite.com\/blog\/linq-to-xml-for-javascript-gaining-performance-through-atomization\/","title":{"rendered":"LINQ to XML for JavaScript &#8211; Gaining Performance through Atomization"},"content":{"rendered":"<p><span class=\"Back\"><a class=\"Back\" href=\"https:\/\/www.ericwhite.com\/blog\/open-xml-and-javascript\/\">Return to the<br \/>Open XML and JavaScript<br \/>Developer Center<\/a><\/span><\/p>\n<p>One of the interesting characteristics of LINQ to XML as implemented in the .NET framework is that it uses atomized <b>XNamespace<\/b> and <b>XName<\/b> objects, and this means that LINQ to XML has very good performance for many common scenarios.\u00a0 The <b>Ltxml.js<\/b> library also uses<br \/>\nan approach of atomizing <b>XNamespace<\/b> and <b>XName<\/b> objects, and for the exact same reason.\u00a0 In this post, I\u2019m going to explain exactly what I mean by this, and how this works in the JavaScript implementation (which is similar in design, but different in mechanics from the .NET LINQ to XML library).<\/p>\n<p style=\"margin-left: .5in;\"><i>As an aside, I am starting an <a href=\"https:\/\/www.ericwhite.com\/blog\/open-xml-and-javascript\/\">Open XML \/ JavaScript Resource Page<\/a> here on OpenXMLDeveloper.org.\u00a0 I will be listing all JavaScript-related blog posts and screen-casts on this page.\u00a0 I think that developers will soon find that using JavaScript to implement Open XML functionality has a large number of benefits.\u00a0 I expect that the number of blog posts and screen-casts will rapidly multiply on this page.<\/i><\/p>\n<h1>What is XNamespace and XName Atomization?<\/h1>\n<p>First I am going to explain what atomization is, and why we like it.<\/p>\n<p>The key point about atomization is that if two variables are initialized with the name namespace and local name, then they are in fact they are initialized with the exact same object.\u00a0 The way this happens is that when you initialize an <b>XName<\/b> object with a given namespace and name, first Ltxml looks in a name cache and determines if that namespace and name exist in the cache.\u00a0 If they do, then Ltxml returns the object in the cache.\u00a0 If that namespace and name do not exist in the cache, then Ltxml initializes an object, puts it into the cache, and then returns that object.<\/p>\n<p>The reason that we do this is that if then we compare two <b>XName<\/b> objects together to see if they have the same namespace and local name, all we need to do is to see if they are the same object.\u00a0 In JavaScript, we can use the === comparison operator.<\/p>\n<p style=\"margin: 0; padding: 0; line-height: normal;\"><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">var<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> ns1 = <\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">new<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> XNamespace(<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: #a31515; background: white;\">&#8220;http:\/\/www.ericwhite.com&#8221;<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\">);<\/span><\/p>\n<p style=\"margin: 0; padding: 0; line-height: normal;\"><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">var<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> n1 = <\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">new<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> XName(ns1 + <\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: #a31515; background: white;\">&#8220;root&#8221;<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\">);<\/span><\/p>\n<p style=\"margin: 0; padding: 0; line-height: normal;\"><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">var<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> n2 = <\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">new<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> XName(ns1 + <\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: #a31515; background: white;\">&#8220;root&#8221;<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\">);<\/span><\/p>\n<p style=\"margin: 0; padding: 0; line-height: normal;\"><span style=\"font-size: 9.5pt; font-family: Consolas; color: blue; background: white;\">var<\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: black; background: white;\"> b = n1 === n2;\u00a0 <\/span><span style=\"font-size: 9.5pt; font-family: Consolas; color: green; background: white;\">\/\/ b is set to true, and this === operator executes extremely quickly<\/span><\/p>\n<p>Where this really comes in handy is in the axis methods, such as the <b>elements<\/b> method or the <b>descendants<\/b> method.\u00a0 If we look in the <b>Ltxml.XContainer.prototype.elements<\/b> method in <b>ltxml.js<\/b>, we see the comparison between the passed-in <b>XName<\/b> object and the <b>XName<\/b> object of each node in the list of children nodes.\u00a0 Key point is that this<br \/>\ncomparison is fast, so the <b>elements<\/b> axis method performs well.<\/p>\n<h1>About the Mechanics<\/h1>\n<p>In the .NET implementation of LINQ to XML, you find that the constructors for the <b>XNamespace<\/b> and <b>XName<\/b> classes are protected, and you can\u2019t call them directly.\u00a0 This is necessary because there is no way to use the constructor to return an atomized object.\u00a0 The constructor will always create a new object.\u00a0 So instead, LINQ to XML in .NET uses an implicit conversion from <b>string<\/b> to <b>XNamespace<\/b>, so that you can initialize an <b>XNamespace<\/b> object by assigning a <b>string<\/b> to it.\u00a0 The atomization happens in that implicit conversion code.\u00a0 If the namespace already exists in the cache, then the implicit conversion returns the object in the cache.<\/p>\n<p>However, JavaScript does not have implicit conversions.\u00a0 But JavaScript does have provisions in a constructor function to specify exactly which object is returned by the constructor function.\u00a0 If you look at the <strong>Ltxml.XName<\/strong> function, you can see that it first looks for the namespace\/name combination in the <strong>Ltxml.nameCache<\/strong> property, and if it finds it, then the constructor returns the object in the cache.\u00a0 Otherwise the constructor creates a new object, adds it to the cache, and then returns it.<\/p>\n<p>The <strong>nameCache <\/strong>is an ordinary JavaScript objects where we use the object as a hash table.\u00a0 The property names of its properties are the expanded names, which means that the namespace is enclosed in curly braces, and the name follows the namespace.\u00a0 Those property names look like this:<\/p>\n<p style=\"margin-bottom: .0001pt;\"><span style=\"font-size: 9.5pt; line-height: 107%; font-family: Consolas; color: black; background: white;\">{http:\/\/www.ericwhite.com}root<\/span><\/p>\n<p style=\"margin-bottom: .0001pt;\"><span style=\"font-size: 9.5pt; line-height: 107%; font-family: Consolas; color: black; background: white;\">{http:\/\/www.ericwhite.com}child<\/span><\/p>\n<p style=\"margin-bottom: .0001pt;\"><span style=\"font-size: 9.5pt; line-height: 107%; font-family: Consolas; color: black; background: white;\">{http:\/\/www.ericwhite.com}anotherElement<\/span><\/p>\n<p>The values of those properties are the atomized name objects.<\/p>\n<p>Since you have the source code for <strong>Ltxml.js<\/strong>, you can go look at the code, and see how this works.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Return to theOpen XML and JavaScriptDeveloper Center One of the interesting characteristics of LINQ to XML as implemented in the .NET framework is that it uses atomized XNamespace and XName objects, and this means that LINQ to XML has very good performance for many common scenarios.\u00a0 The Ltxml.js library also uses an approach of atomizing [&hellip;]<\/p>\n","protected":false},"author":10567,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"_s2mail":"","footnotes":""},"class_list":["post-2916","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages\/2916","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/users\/10567"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/comments?post=2916"}],"version-history":[{"count":3,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages\/2916\/revisions"}],"predecessor-version":[{"id":2933,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages\/2916\/revisions\/2933"}],"wp:attachment":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/media?parent=2916"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}