[Mono-docs-list] Monodoc Assembler Performance patch
Ben Maurer
bmaurer@users.sourceforge.net
19 Jun 2003 16:07:10 -0400
--=-GcfogFs7X2qnu6bT/tli
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hello all,
If my previous 12% speed improvement patch wasn't enough for you, you
are in good company ;-), it was not enough for me either. So I went in
and ripped out all the XPath and XmlDocument stuff from the guts of
ecma-provider and replaced it with cool, clean XmlTextReader.
As a result, I was able to half both the amount of time it takes to
assemble the class libraries and the amount of memory that the assembler
takes up.
May I commit?
-- Ben
--=-GcfogFs7X2qnu6bT/tli
Content-Disposition: attachment; filename=monodocperf.patch
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-patch; name=monodocperf.patch; charset=UTF-8
Index: ChangeLog
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/monodoc/browser/ChangeLog,v
retrieving revision 1.35
diff -u -r1.35 ChangeLog
--- ChangeLog 6 Jun 2003 04:22:30 -0000 1.35
+++ ChangeLog 19 Jun 2003 20:14:14 -0000
@@ -1,3 +1,7 @@
+2003-06-19 Ben Maurer <bmaurer@users.sourceforge.net>
+ * ecma-provider.cs, provider.cs: Added tons of performance
+ related stuff. Doubles speed, halfs memory allocation!
+
2003-06-02 Miguel de Icaza <miguel@ximian.com>
=20
* ecma-provider.cs (PopulateIndex): Add full type names.
Index: ecma-provider.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/monodoc/browser/ecma-provider.cs,v
retrieving revision 1.49
diff -u -r1.49 ecma-provider.cs
--- ecma-provider.cs 15 Jun 2003 18:53:27 -0000 1.49
+++ ecma-provider.cs 19 Jun 2003 20:14:14 -0000
@@ -4,9 +4,11 @@
// Authors:
// Miguel de Icaza (miguel@ximian.com)
// Joshua Tauberer (tauberer@for.net)
+// Ben Maurer (bmaurer@users.sourceforge.net)
//
// (C) 2002, 2003 Ximian, Inc.
// (C) 2003 Joshua Tauberer.
+// (C) 2003 Ben Maurer
//
// TODO:
// Should cluster together constructors
@@ -27,58 +29,8 @@
=20
using BF =3D System.Reflection.BindingFlags;
=20
-//
-// Helper routines to extract information from an Ecma XML document
-//
public class EcmaDoc {
- public static string GetFullClassName (XmlDocument doc)
- {
- return doc.SelectSingleNode ("/Type").Attributes ["FullName"].InnerText;
- }
-=09
- public static string GetClassName (XmlDocument doc)
- {
- return doc.SelectSingleNode ("/Type").Attributes ["Name"].InnerText;
- }
-
- public static string GetClassAssembly (XmlDocument doc)
- {
- return doc.SelectSingleNode ("/Type/AssemblyInfo/AssemblyName").InnerTex=
t;
- }
-
- public static string GetClassNamespace (XmlDocument doc)
- {
- string s =3D doc.SelectSingleNode ("/Type").Attributes ["FullName"].Inne=
rText;
-
- return s.Substring (0, s.LastIndexOf ("."));
- }
-=09
- public static string GetTypeKind (XmlDocument doc)
- {
- XmlNode node =3D doc.SelectSingleNode ("/Type/Base/BaseTypeName");
-
- if (node =3D=3D null){
- if (GetFullClassName (doc) =3D=3D "System.Object")
- return "Class";
- return "Interface";
- }
-
- switch (node.InnerText){
-
- case "System.Delegate":
- return "Delegate";
- case "System.ValueType":
- return "Structure";
- case "System.Enum":
- return "Enumeration";
- default:
- return "Class";
- }
- }
-
- //
- // Utility function: converts a fully .NET qualified type name into a C#-=
looking one
- //
+ =09
public static string ConvertCTSName (string type)
{
if (!type.StartsWith ("System."))
@@ -115,7 +67,6 @@
return type;
}
}
-
//
// The Ecma documentation provider:
//
@@ -160,125 +111,381 @@
}
}
=20
- struct TypeInfo : IComparable {
- public string type_assembly;
- public string type_name;
- public string type_full;
- public string type_kind;
- public XmlNode type_doc;
-
- public TypeInfo (string k, string a, string f, string s, XmlNode n)
- {
- type_assembly =3D a;
- type_name =3D s;
- type_doc =3D n;
- type_kind =3D k;
- type_full =3D f;
+=09
+ public class TypeInfo : IComparable {
+ public string name, assembly, kind, fullclassname, baseType;
+ public string summary;
+ =09
+ public ArrayList constructors, methods, properties, fields, events;
+ =09
+ TypeInfo (XmlTextReader r)=20
+ {
+ constructors =3D new ArrayList ();
+ methods =3D new ArrayList ();
+ properties =3D new ArrayList ();
+ fields =3D new ArrayList ();
+ events =3D new ArrayList ();
+ =09
+ r.MoveToContent ();
+ ReadAttributes (r);
+ r.ReadStartElement ("Type");
+ =09
+ ReadElements (r);
+ kind =3D GetTypeKind ();
}
-
+ =09
public int CompareTo (object b)
{
TypeInfo na =3D this;
TypeInfo nb =3D (TypeInfo) b;
+=09
+ return String.Compare (na.fullclassname, nb.fullclassname);
+ }
+ =09
+ public static TypeInfo Parse (string file)
+ {
+ XmlTextReader r =3D new XmlTextReader (file);
+ r.WhitespaceHandling =3D WhitespaceHandling.Significant;
+=09
+ return new TypeInfo (r);
+ }
+ =09
+ =09
+ string GetTypeKind ()
+ {
+=09
+ switch (baseType) {
+ case null:
+ if (fullclassname =3D=3D "System.Object")
+ return "Class";
+ else
+ return "Interface";
+ =09
+ case "System.Delegate":
+ return "Delegate";
+ case "System.ValueType":
+ return "Structure";
+ case "System.Enum":
+ return "Enumeration";
+ default:
+ return "Class";
+ =09
+ }
+ }
+ =09
+ void ReadAttributes (XmlTextReader r)
+ {
+ name =3D r.GetAttribute ("Name");
+ fullclassname =3D r.GetAttribute ("FullName");
+ }
+ =09
+ void ReadElements (XmlTextReader r)
+ {
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ =09
+ switch (r.LocalName) {
=20
- return String.Compare (na.type_full, nb.type_full);
+ =09
+ case "AssemblyInfo":
+ ReadAssemblyInfo (r);
+ break;
+ =09
+ case "Docs":
+ ReadDocs (r);
+ break;
+ case "Base":
+ ReadBase (r);
+ break;
+ =09
+ case "Members":
+ ReadMembers (r);
+ break;
+ /*
+ case "TypeSignature":
+ case "MemberOfLibrary":
+ case "ThreadingSafetyStatement":
+ case "ThreadSafetyStatement":
+ case "Interfaces":
+ case "TypeExcluded":
+ case "Attributes":
+ */
+ default:
+ r.Skip ();
+ r.MoveToContent ();
+ break;
+ =09
+ }
+ }
+ }
+ =09
+ void ReadAssemblyInfo (XmlTextReader r)
+ {
+ if (r.IsEmptyElement) {
+ r.Skip ();
+ return;
+ }
+ r.ReadStartElement ("AssemblyInfo");
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ =09
+ if (r.LocalName =3D=3D "AssemblyName") {
+ assembly =3D r.ReadString ();
+ r.ReadEndElement ();
+ } else {
+ r.Skip ();
+ r.MoveToContent ();
+ }
+ }
+ r.ReadEndElement ();
}
+ =09
+ =09
+ void ReadDocs (XmlTextReader r)
+ {
+ if (r.IsEmptyElement) {
+ r.Skip ();
+ return;
+ }
+ r.ReadStartElement ("Docs");
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ if (r.LocalName =3D=3D "summary")=20
+ summary =3D r.ReadOuterXml ();
+ else=20
+ r.Skip ();
+ r.MoveToContent ();
+ }
+ r.ReadEndElement ();
+ }
+ =09
+=09
+ void ReadBase (XmlTextReader r)
+ {
+ if (r.IsEmptyElement) {
+ r.Skip ();
+ return;
+ }
+ r.ReadStartElement ("Base");
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ if (r.LocalName =3D=3D "BaseTypeName") {
+ baseType =3D r.ReadString ();
+ r.ReadEndElement ();
+ } else {
+ r.Skip ();
+ r.MoveToContent ();
+ }
+ }
+ r.ReadEndElement ();
+ }
+ =09
+ void ReadMembers (XmlTextReader r)
+ {
+ if (r.IsEmptyElement) {
+ r.Skip ();
+ return;
+ }
+ r.ReadStartElement ("Members");
+ =09
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ string mName, type, sig, paramsStr;
+ =09
+ mName =3D r.GetAttribute ("MemberName");
+ r.MoveToElement ();
+ r.ReadStartElement ("Member");
+=09
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ switch (r.LocalName) {
+
+ case "MemberType":
+ type =3D r.ReadString ();
+ r.ReadEndElement ();
+ break; =09
+ case "Parameters":
+ if (r.IsEmptyElement) {
+ r.Skip ();
+ r.MoveToContent ();
+ } else {
+ r.ReadStartElement ("Parameters");
+ StringBuilder b =3D new StringBuilder ();
+ =09
+ b.Append ('(');
+ =09
+ bool first =3D true;
+=09
+ while (r.MoveToContent () =3D=3D XmlNodeType.Element) {
+ if (!first) b.Append (',');
+ first =3D false; =09
+ b.Append (EcmaDoc.ConvertCTSName (r.GetAttribute ("Type")));
+ r.Skip ();
+ }
+ =09
+ b.Append (')');
+ r.ReadEndElement ();
+ paramsStr =3D b.ToString ();
+ }
+ break;
+ /*
+ case "Attributes":
+ case "Docs":
+ case "Excluded":
+ case "ExcludedLibrary":
+ case "MemberSignature":
+ case "MemberValue":
+ case "ReturnValue":
+ */
+ default:
+ r.Skip ();
+ r.MoveToContent ();
+ break;
+ }
+ }
+ =09
+ r.ReadEndElement ();
+ switch (type) {
+ case "Event":
+ events.Add (mName);
+ break;
+ =09
+ case "Property":
+ properties.Add (mName);
+ break;
+ =09
+ case "Field":
+ fields.Add (mName);
+ break;
+ =09
+ case "Constructor":
+ constructors.Add (name + paramsStr);
+ break;
+ =09
+ case "Method":
+ methods.Add (mName + paramsStr);
+ break;
+ }
+ }
+ r.ReadEndElement ();
+ =09
+ events.Sort ();
+ properties.Sort ();
+ fields.Sort ();
+ constructors.Sort ();
+ methods.Sort ();
+=09
+ }
+
}
=09
+=09
+ struct TypeSummary : IComparable {
+ public string type_assembly;
+ public string type_name;
+ public string type_full;
+ public string type_kind;
+ public string type_doc;
+
+ public TypeSummary (string k, string a, string f, string s=
, string n)
+ {
+ type_assembly =3D a;
+ type_name =3D s;
+ type_doc =3D n;
+ type_kind =3D k;
+ type_full =3D f;
+ }
+
+ public int CompareTo (object b)
+ {
+ TypeSummary na =3D this;
+ TypeSummary nb =3D (TypeSummary) b;
+
+ return String.Compare (na.type_full, nb.type_full)=
;
+ }
+ }
//
// Packs a file with the summary data
//
public override void CloseTree (HelpSource hs, Tree tree)
{
foreach (DictionaryEntry de in class_summaries){
- XmlDocument doc =3D new XmlDocument ();
string ns =3D (string) de.Key;
- =09
ArrayList list =3D (ArrayList) de.Value;
- list.Sort();
-
- XmlElement elements =3D doc.CreateElement ("elements");
- doc.AppendChild (elements);
+ list.Sort ();
=09
- string file =3D "xml.summary." + ns;
Console.Error.WriteLine ("Have {0} elements in the {1}", list.Count, ns=
);
- foreach (TypeInfo p in list){
- XmlElement e =3D null;
- =09
+ =09
+ XmlTextWriter w =3D hs.PackXmlWriter ("xml.summary." + ns);
+ =09
+ w.WriteStartElement ("elements");
+
+ foreach (TypeSummary p in list){
switch (p.type_kind){
case "Class":
- e =3D doc.CreateElement ("class");=20
+ w.WriteStartElement ("class");=20
break;
=09
case "Enumeration":
- e =3D doc.CreateElement ("enum");
+ w.WriteStartElement ("enum");
break;
=09
case "Structure":
- e =3D doc.CreateElement ("struct");
+ w.WriteStartElement ("struct");
break;
=09
case "Delegate":
- e =3D doc.CreateElement ("delegate");
+ w.WriteStartElement ("delegate");
break;
=09
case "Interface":
- e =3D doc.CreateElement ("interface");
+ w.WriteStartElement ("interface");
break;
}
- =09
- e.SetAttribute ("name", p.type_name);
- e.SetAttribute ("fullname", p.type_full);
- e.SetAttribute ("assembly", p.type_assembly);
- XmlNode copy =3D doc.ImportNode (p.type_doc, true);
- e.AppendChild (copy);
- elements.AppendChild (e);
+ w.WriteAttributeString ("name", p.type_name);
+ w.WriteAttributeString ("fullname", p.type_full);
+ w.WriteAttributeString ("assembly", p.type_assembly);
+
+ w.WriteRaw (p.type_doc);
+ w.WriteEndElement ();
}
- hs.PackXml ("xml.summary." + ns, doc);
+ =09
+ w.WriteEndDocument();
+ w.Flush ();
}
}
=20
static Hashtable class_summaries =3D new Hashtable ();
=20
- XmlDocument doc;
+ XmlNode typeNode;
=09
void PopulateClass (string ns, Node ns_node, string file)
{
- doc =3D new XmlDocument ();
- doc.Load (file);
- =09
- string name =3D EcmaDoc.GetClassName (doc);
- string assembly =3D EcmaDoc.GetClassAssembly (doc);
- string kind =3D EcmaDoc.GetTypeKind (doc);
- string full =3D EcmaDoc.GetFullClassName (doc);
-
- Node class_node;
+ TypeInfo t =3D TypeInfo.Parse (file);
string file_code =3D ns_node.tree.HelpSource.PackFile (file);
-
- XmlNode class_summary =3D doc.SelectSingleNode ("/Type/Docs/summary");
+ string name =3D t.name;
+ string assembly =3D t.assembly;
+ string kind =3D t.kind;
+ string full =3D t.fullclassname;
+ string class_summary =3D t.summary;
+ =09
ArrayList l =3D (ArrayList) class_summaries [ns];
if (l =3D=3D null)
l =3D class_summaries [ns] =3D new ArrayList ();
- l.Add (new TypeInfo (kind, assembly, full, name, class_summary));
- =20
- class_node =3D ns_node.LookupNode (String.Format ("{0} {1}", name, kind)=
, "ecma:" + file_code + "#" + name + "/");
+ =09
+ l.Add (new TypeSummary (kind, assembly, full, name, class_summary));
=20
- if (kind =3D=3D "Enumeration")
- return;
=20
- if (kind =3D=3D "Delegate")
+ Node class_node =3D ns_node.LookupNode (String.Format ("{0} {1}", name, =
kind), "ecma:" + file_code + "#" + name + "/");
+
+ if (kind =3D=3D "Enumeration" || kind =3D=3D "Delegate")=20
return;
=09
//
// Always add the Members node
//
class_node.CreateNode ("Members", "*");
+ =09
=20
- PopulateMember (name, class_node, "Constructor", "Constructors");
- PopulateMember (name, class_node, "Method", "Methods");
- PopulateMember (name, class_node, "Property", "Properties");
- PopulateMember (name, class_node, "Field", "Fields");
- PopulateMember (name, class_node, "Event", "Events");
+ PopulateMember (t.constructors, class_node, "Constructor", "Constructors=
");
+ PopulateMember (t.methods, class_node, "Method", "Methods");
+ PopulateMember (t.properties, class_node, "Property", "Properties");
+ PopulateMember (t.fields, class_node, "Field", "Fields");
+ PopulateMember (t.events, class_node, "Event", "Events");
}
=20
class NodeIndex {
@@ -314,59 +521,19 @@
// Performs an XPath query on the document to extract the nodes for the v=
arious members
// we also use some extra text to pluralize the caption
//
- void PopulateMember (string typename, Node node, string text, string plur=
al_text)
+ void PopulateMember (ArrayList items, Node node, string text, string plur=
al_text)
{
- XmlNodeList list =3D doc.SelectNodes (String.Format ("/Type/Members/Memb=
er[MemberType=3D\"{0}\"]", text));
- int count =3D list.Count;
- =09
- if (count =3D=3D 0)
- return;
-
Node nodes_node;
string key =3D text.Substring (0, 1);
- if (count =3D=3D 1)
- nodes_node =3D node.CreateNode (text, key);
- else
- nodes_node =3D node.CreateNode (plural_text, key);
-
- NodeIndex [] node_array =3D new NodeIndex [count];
+ if (items.Count =3D=3D 1)
+ nodes_node =3D node.CreateNode (text, key);
+ else
+ nodes_node =3D node.CreateNode (plural_text, key);
+ =09
+ =09
int i =3D 0;
- foreach (XmlNode n in list)
- node_array [i] =3D new NodeIndex (n, i++);
- =09
- Array.Sort (node_array, NodeComparer);
-
- foreach (NodeIndex ni in node_array){
- string signature;
-
- switch (text){
- case "Event":
- case "Property":
- case "Field":
- signature =3D GetMemberName (ni.node);
- break;
-
- case "Constructor":
- signature =3D EcmaHelpSource.MakeSignature(ni.node, typename);
- break;
-
- case "Method":
- signature =3D EcmaHelpSource.MakeSignature(ni.node, null);
- break;
- =09
- default:
- XmlNode signode =3D ni.node.SelectSingleNode ("MemberSignature[@Langua=
ge=3D'C#']");
- =09
- if (signode =3D=3D null)
- signature =3D GetMemberName (ni.node);
- else
- signature =3D signode.Attributes ["Value"].InnerText;
- break;
- }
- =09
- //signature =3D CleanSignature (ni.node, signature);
-
- nodes_node.CreateNode (signature, ni.index.ToString ());
+ foreach (string s in items) {
+ nodes_node.CreateNode (s, (i++).ToString ());
}
}
=20
Index: provider.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/monodoc/browser/provider.cs,v
retrieving revision 1.28
diff -u -r1.28 provider.cs
--- provider.cs 1 Jun 2003 15:26:45 -0000 1.28
+++ provider.cs 19 Jun 2003 20:14:14 -0000
@@ -470,11 +470,12 @@
=20
return entry_name;
}
-=09
- public void PackXml (string fname, XmlDocument doc)
+ =09
+ public System.Xml.XmlTextWriter PackXmlWriter (string entry_name)
{
- doc.Save ("tmp");
- PackFile ("tmp", fname);
+ ZipEntry entry =3D new ZipEntry (entry_name);
+ zip_output.PutNextEntry (entry);
+ return new System.Xml.XmlTextWriter (zip_output, null);
}
=09
public virtual string GetText (string url, out Node n)
--=-GcfogFs7X2qnu6bT/tli--