[Bug+Fix] Xml creating and printing errors and optimizations

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug+Fix] Xml creating and printing errors and optimizations

Reinout Heeck-2
We started with implementing Web Services in VisualWorks. In this
context we found some Issues in XML processing.
We saw, that half of the time a WebService call takes is spent in
printing the XML.Document onto the HttpPackage.

The implementation of SAXCannonicalWriter on each use newly creates 2
Dictionaries textMapping and attributeMapping in #minimalCharacterMap
instead of caching them. This takes a lot of time. In XML.Node we have
the same behavior in #printCannonical:on:. The character mapping table
dictionary is always created as a temporary variable.

Furthermore we noted, that other implementations of #printCannonicalOn:
use String concatenations in methods that have access to a WriteStream.

The initialize method of XML.Element uses a UserMessage "tag :=
(#undefined << #xml >> 'undefined') asString."  as initial value for tag.
If you really use internationalization, you get a serious performance
bottleneck in xml processing and this makes in my opinion no sense since
this is a fixed constant, translating it would break the protocol.

I have attached a parcel with the patches we made. These patches reduce
the processing time of an WebServices call up to 50%.



<?xml version="1.0"?>

<st-source>
<!--
Name: Sps-Xml-Speed-Patches
DbIdentifier: Soops74
DbTrace: 56694
PackageName: Sps-Xml-Speed-Patches
Parcel: #('Sps-Xml-Speed-Patches')
PrintStringCache: (4,Mac)
Date: 1:15:14 pm July 5, 2006
 -->
<time-stamp>From VisualWorks®, 7.4 of December 5, 2005 on July 5, 2006 at 1:15:14 pm</time-stamp>


<do-it>(Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned.  Choose terminate or close.']</do-it>

<shared-variable>
<name>MinmalCharacterMap</name>
<environment>XML.Node</environment>
<private>false</private>
<constant>false</constant>
<category>caches</category>
<attributes>
<package>Sps-Xml-Speed-Patches</package>
</attributes>
</shared-variable>

<shared-variable>
<name>MinmalAttributeMap</name>
<environment>XML.SAXCanonicalWriter</environment>
<private>false</private>
<constant>false</constant>
<category>caches</category>
<attributes>
<package>Sps-Xml-Speed-Patches</package>
</attributes>
</shared-variable>

<shared-variable>
<name>MinimalTextMap</name>
<environment>XML.SAXCanonicalWriter</environment>
<private>false</private>
<constant>false</constant>
<category>caches</category>
<attributes>
<package>Sps-Xml-Speed-Patches</package>
</attributes>
</shared-variable>

<methods>
<class-id>XML.Attribute</class-id> <category>printing</category>

<body package="Sps-Xml-Speed-Patches" selector="printCanonicalOn:">printCanonicalOn: aStream
        self tag xmlTagOn: aStream.
        aStream nextPutAll: '="'.
        self printCanonical: value on: aStream.
        aStream nextPut: $"</body>
</methods>

<methods>
<class-id>XML.SAXCanonicalWriter</class-id> <category>initialize</category>

<body package="Sps-Xml-Speed-Patches" selector="minimalCharacterMapping">minimalCharacterMapping
        textMap := self minimalTextMap.
        attrMap := self minmalAttributeMap</body>

<body package="Sps-Xml-Speed-Patches" selector="minimalTextMap">minimalTextMap
        MinimalTextMap isNil
                ifTrue:
                        [MinimalTextMap := (Dictionary new: 17)
                                                at: $&lt; put: '&amp;lt;';
                                                at: $&gt; put: '&amp;gt;';
                                                at: $" put: '&amp;quot;';
                                                at: $&amp; put: '&amp;amp;';
                                                at: (Character value: 9) put: '&amp;#9;';
                                                at: (Character value: 10) put: '&amp;#10;';
                                                at: (Character value: 13) put: '&amp;#13;';
                                                yourself].
        ^MinimalTextMap</body>

<body package="Sps-Xml-Speed-Patches" selector="minmalAttributeMap">minmalAttributeMap
        MinmalAttributeMap isNil
                ifTrue:
                        [MinmalAttributeMap := (Dictionary new: 17)
                                                at: $&lt; put: '&amp;lt;';
                                                at: $&gt; put: '&amp;gt;';
                                                at: $&amp; put: '&amp;amp;';
                                                at: $" put: '&amp;quot;';
                                                at: (Character value: 9) put: '&amp;#9;';
                                                at: (Character value: 10) put: '&amp;#10;';
                                                at: (Character value: 13) put: '&amp;#13;';
                                                yourself].
        ^MinmalAttributeMap</body>
</methods>

<methods>
<class-id>XML.Element</class-id> <category>initialize</category>

<body package="Sps-Xml-Speed-Patches" selector="initialize">initialize
        super initialize.
        tag := 'undefined'.
        attributes := #()</body>
</methods>

<methods>
<class-id>XML.Element</class-id> <category>printing</category>

<body package="Sps-Xml-Speed-Patches" selector="printCanonicalOn:">printCanonicalOn: aStream
        | az |
        aStream nextPut: $&lt;.
        tag xmlTagOn: aStream.
        attributes == nil
                ifFalse:
                        [az := attributes size &gt; 1
                                                ifTrue: [attributes asSortedCollection: [:x :y | x key &lt; y key]]
                                                ifFalse: [attributes].
                        az do:
                                        [:at |
                                        aStream space.
                                        at printCanonicalOn: aStream]].
        self printNamespacesOn: aStream.
        elements == nil
                ifTrue: [aStream nextPutAll: '/&gt;']
                ifFalse:
                        [aStream nextPut: $&gt;.
                        elements do: [:e | e printCanonicalOn: aStream].
                        aStream nextPutAll: '&lt;/'.
                        tag xmlTagOn: aStream.
                        aStream nextPut: $&gt;]</body>
</methods>

<methods>
<class-id>XML.Node</class-id> <category>printing</category>

<body package="Sps-Xml-Speed-Patches" selector="minimalCharacterMap">minimalCharacterMap
        MinmalCharacterMap isNil
                ifTrue:
                        [MinmalCharacterMap := Dictionary new: 17.
                        MinmalCharacterMap
                                at: Character cr put: '&amp;#13;';
                                at: Character lf put: '&amp;#10;';
                                at: Character tab put: '&amp;#9;';
                                at: $&amp; put: '&amp;amp;';
                                at: $&lt; put: '&amp;lt;';
                                at: $&gt; put: '&amp;gt;';
                                at: $" put: '&amp;quot;'].
        ^MinmalCharacterMap</body>

<body package="Sps-Xml-Speed-Patches" selector="printCanonical:on:">printCanonical: text on: aStream
        "Print myself on the stream in the form described by James
        Clark's canonical XML."

        | d |
        d := self minimalCharacterMap.
        text do:
                        [:c |
                        | s |
                        (s := d at: c ifAbsent: [nil]) isNil
                                ifTrue: [aStream nextPut: c]
                                ifFalse: [aStream nextPutAll: s]]</body>
</methods>

<methods>
<class-id>Core.CharacterArray</class-id> <category>printing</category>

<body package="Sps-Xml-Speed-Patches" selector="xmlTagOn:">xmlTagOn: aStream
        aStream nextPutAll: self</body>
</methods>

<methods>
<class-id>XML.NodeTag</class-id> <category>printing</category>

<body package="Sps-Xml-Speed-Patches" selector="xmlTagOn:">xmlTagOn: aStream
        qualifier isEmpty
                ifTrue: [aStream nextPutAll: type]
                ifFalse:
                        [aStream
                                nextPutAll: qualifier;
                                nextPut: $:;
                                nextPutAll: type]</body>
</methods>

<do-it>"Imported Classes:"</do-it>

<do-it>self error: 'Attempting to file-in parcel imports.  Choose terminate or close'</do-it>

<class>
<name>CharacterArray</name>
<environment>Core</environment>
<super>Core.ArrayedCollection</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>Collections-Text</category>
<attributes>
<package>Collections-Text</package>
</attributes>
</class>

<class>
<name>Node</name>
<environment>XML</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>parent flags userData </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Nodes</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>Element</name>
<environment>XML</environment>
<super>XML.Node</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>tag attributes namespaces elements definition </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Nodes</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>Attribute</name>
<environment>XML</environment>
<super>XML.Node</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name value </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Nodes</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>NodeTag</name>
<environment>XML</environment>
<super>Core.Magnitude</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>namespace type qualifier </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Parsing</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>SAXCanonicalWriter</name>
<environment>XML</environment>
<super>XML.SAXWriter</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>baseURI </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-SAX</category>
<attributes>
<package>XML</package>
</attributes>
</class>

</st-source>

Sps-Xml-Speed-Patches.pcl (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Bug+Fix] Xml creating and printing errors and optimizations

Reinout Heeck-2
Especially for people, that still use Outlook as email client, I packed
the parcel as a zip archive.



Sps-Xml-Speed-Patches.zip (4K) Download Attachment