[generator] Use ordinal string comparison. (#1022)

Test results when running the generator for XM/full:

Profile output size before: 9,4 GB
Profile output size after:  5,6 GB

Duration before: 21,5 s
Duration after:  19,0 s
Difference:     - 2,5 s = -11,6 %

Total memory usage barely changed (5kb less within a total of 1,0 GB),
but the number of method calls fell drastically:

Method calls before: 868.053.383
Method calls after:  492.325.187
Difference:        - 375.728.196 = -43,3%

The top 10 method calls also changed significantly.

Method call summary before

```
Total(ms) Self(ms)      Calls Method name
  128879    28400    3509251 Mono.Globalization.Unicode.SimpleCollator:CompareInternal (string,int,int,string,int,int,bool&,bool&,bool,bool,Mono.Globalization.Unicode.SimpleCollator/Context&)
   16074    16074   79118946 Mono.Globalization.Unicode.CodePointIndexer:ToIndex (int)
   15952    10492   26747901 Mono.Globalization.Unicode.MSCompatUnicodeTable:Category (int)
   26425    10473   26747901 Mono.Globalization.Unicode.SimpleCollator:Category (int)
   14743     8679   14952304 Mono.Globalization.Unicode.MSCompatUnicodeTable:IsIgnorable (int,byte)
   31345     8113   10413595 System.RuntimeType:GetBaseType ()
   12266     7303   12523021 Mono.Globalization.Unicode.SimpleCollator:GetContraction (string,int,int)
   20555     5812   14952304 Mono.Globalization.Unicode.SimpleCollator:IsIgnorable (int,System.Globalization.CompareOptions)
   93341     5529    2674913 System.MonoCustomAttrs:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool)
    8229     5337   13551378 System.RuntimeType:GetAttributeFlagsImpl ()
```

Method call summary after

```
Total(ms) Self(ms)      Calls Method name
   31646     8168   10412459 System.RuntimeType:GetBaseType ()
   94899     5672    2674880 System.MonoCustomAttrs:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool)
    8343     5395   13550176 System.RuntimeType:GetAttributeFlagsImpl ()
    5646     5243    2914268 (wrapper managed-to-native) System.MonoCustomAttrs:GetCustomAttributesInternal (System.Reflection.ICustomAttributeProvider,System.Type,bool)
    5147     5147    9727785 (wrapper managed-to-native) object:__icall_wrapper_ves_icall_array_new_specific (intptr,int)
   11140     4432   10948127 System.Type:get_Attributes ()
   19601     4362   10716826 System.Type:get_IsInterface ()
   15238     4344   10716826 System.RuntimeTypeHandle:IsInterface (System.RuntimeType)
    4133     4133          1 (wrapper managed-to-native) System.Threading.WaitHandle:WaitOne_internal (intptr,int)
    5922     3851    9541170 (wrapper stelemref) object:virt_stelemref_class (intptr,object)
```
This commit is contained in:
Rolf Bjarne Kvinge 2016-10-28 00:34:05 +02:00 коммит произвёл Sebastien Pouliot
Родитель d0209f4b27
Коммит 3cf1b75749
1 изменённых файлов: 40 добавлений и 40 удалений

Просмотреть файл

@ -2177,7 +2177,7 @@ public partial class Generator : IMemberGatherer {
if (HasAttribute (pi, typeof (NullAllowedAttribute)))
return false;
if (mi.IsSpecialName && mi.Name.StartsWith ("set_")){
if (mi.IsSpecialName && mi.Name.StartsWith ("set_", StringComparison.Ordinal)){
if (HasAttribute (mi, typeof (NullAllowedAttribute))){
return false;
}
@ -2337,7 +2337,7 @@ public partial class Generator : IMemberGatherer {
var marshalDirective = GetAttribute<MarshalDirectiveAttribute> (mi);
if (marshalDirective != null && marshalDirective.Library != null) {
print (m, "\t\t[DllImport (\"{0}\", EntryPoint=\"{1}\")]", marshalDirective.Library, method_name);
} else if (method_name.StartsWith ("xamarin_")) {
} else if (method_name.StartsWith ("xamarin_", StringComparison.Ordinal)) {
print (m, "\t\t[DllImport (\"__Internal\", EntryPoint=\"{0}\")]", method_name);
} else {
print (m, "\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"{0}\")]", entry_point);
@ -3055,7 +3055,7 @@ public partial class Generator : IMemberGatherer {
print ("namespace {0} {{", ns.CoreObjCRuntime); indent++;
print ("[CompilerGenerated]");
print ("static partial class Libraries {"); indent++;
foreach (var library_info in libraries.OrderBy (v => v.Key)) {
foreach (var library_info in libraries.OrderBy (v => v.Key, StringComparer.Ordinal)) {
var library_name = library_info.Key;
var library_path = library_info.Value;
print ("static public class {0} {{", library_name.Replace (".", string.Empty)); indent++;
@ -3201,7 +3201,7 @@ public partial class Generator : IMemberGatherer {
} else if (pi.PropertyType == typeof (string)){
getter = "GetStringValue ({0})";
setter = "SetStringValue ({0}, value)";
} else if (pi.PropertyType.Name.StartsWith ("NSDictionary")){
} else if (pi.PropertyType.Name.StartsWith ("NSDictionary", StringComparison.Ordinal)){
if (pi.PropertyType.IsGenericType) {
var genericParameters = pi.PropertyType.GetGenericArguments ();
// we want to keep {0} for later yet add the params for the template.
@ -3428,7 +3428,7 @@ public partial class Generator : IMemberGatherer {
{
string prefix = new string ('\t', level);
Console.WriteLine ("{2} {0} - {1}", gt.Type.Name, gt.ImplementsAppearance ? "APPEARANCE" : "", prefix);
foreach (var c in (from s in gt.Children orderby s.Type.FullName select s))
foreach (var c in (from s in gt.Children .OrderBy ( s => s.Type.FullName, StringComparer.Ordinal) select s))
DumpChildren (level+1, c);
}
@ -3741,9 +3741,9 @@ public partial class Generator : IMemberGatherer {
}
// Unified internal methods automatically get a _ appended
if (minfo.is_extension_method && minfo.method.IsSpecialName) {
if (name.StartsWith ("get_"))
if (name.StartsWith ("get_", StringComparison.Ordinal))
name = "Get" + name.Substring (4);
else if (name.StartsWith ("set_"))
else if (name.StartsWith ("set_", StringComparison.Ordinal))
name = "Set" + name.Substring (4);
}
sb.Append (name);
@ -3821,7 +3821,7 @@ public partial class Generator : IMemberGatherer {
print (w, "//\n// Auto-generated from generator.cs, do not edit\n//");
print (w, "// We keep references to objects, so warning 414 is expected\n");
print (w, "#pragma warning disable 414\n");
print (w, ns.ImplicitNamespaces.OrderByDescending (n => n.StartsWith ("System")).ThenBy (n => n.Length).Select (n => "using " + n + ";"));
print (w, ns.ImplicitNamespaces.OrderByDescending (n => n.StartsWith ("System", StringComparison.Ordinal)).ThenBy (n => n.Length).Select (n => "using " + n + ";"));
print (w, "");
}
@ -4972,7 +4972,7 @@ public partial class Generator : IMemberGatherer {
// If we're doing a setter for a weak property that is protocolized event back
// we need to put in a check to verify you aren't stomping the "internal underscore"
// generated delegate. We check CheckForEventAndDelegateMismatches global to disable the checks
if (pi.Name.StartsWith ("Weak")) {
if (pi.Name.StartsWith ("Weak", StringComparison.Ordinal)) {
string delName = pi.Name.Substring(4);
if (SafeIsProtocolizedEventBacked (delName, type))
print ("\t{0}.EnsureDelegateAssignIsNotOverwritingInternalDelegate ({1}, value, {2});", ApplicationClassName, string.IsNullOrEmpty (var_name) ? "null" : var_name, GetDelegateTypePropertyName (delName));
@ -5386,18 +5386,18 @@ public partial class Generator : IMemberGatherer {
group fullname by ns into g
select new {Namespace = g.Key, Fullname=g};
foreach (var group in groupedTypes.OrderBy (v => v.Namespace)) {
foreach (var group in groupedTypes.OrderBy (v => v.Namespace, StringComparer.Ordinal)) {
if (group.Namespace != null) {
print ("namespace {0} {{", group.Namespace);
indent++;
}
foreach (var deltype in group.Fullname.OrderBy (v => v)) {
int p = deltype.LastIndexOf (".");
foreach (var deltype in group.Fullname.OrderBy (v => v, StringComparer.Ordinal)) {
int p = deltype.LastIndexOf (".", StringComparison.Ordinal);
var shortName = deltype.Substring (p+1);
var mi = delegateTypes [deltype];
if (shortName.StartsWith ("Func<"))
if (shortName.StartsWith ("Func<", StringComparison.Ordinal))
continue;
var del = mi.DeclaringType;
@ -5518,7 +5518,7 @@ public partial class Generator : IMemberGatherer {
{
var allProtocolMethods = new List<MethodInfo> ();
var allProtocolProperties = new List<PropertyInfo> ();
var ifaces = (IEnumerable<Type>) type.GetInterfaces ().Concat (new Type [] { ReflectionExtensions.GetBaseType (type) }).OrderBy (v => v.FullName);
var ifaces = (IEnumerable<Type>) type.GetInterfaces ().Concat (new Type [] { ReflectionExtensions.GetBaseType (type) }).OrderBy (v => v.FullName, StringComparer.Ordinal);
if (type.Namespace != null) {
print ("namespace {0} {{", type.Namespace);
@ -5967,7 +5967,7 @@ public partial class Generator : IMemberGatherer {
implements_list.Add (iface);
}
implements_list.Sort ();
implements_list.Sort (StringComparer.Ordinal);
if (is_protocol)
implements_list.Insert (0, "I" + type.Name);
@ -6025,7 +6025,7 @@ public partial class Generator : IMemberGatherer {
indent++;
if (!is_model && !is_partial) {
foreach (var ea in selectors [type].OrderBy (s => s)) {
foreach (var ea in selectors [type].OrderBy (s => s, StringComparer.Ordinal)) {
var selectorField = SelectorField (ea, true);
if (!InlineSelectors) {
selectorField = selectorField.Substring (0, selectorField.Length - 6 /* Handle */);
@ -6174,12 +6174,12 @@ public partial class Generator : IMemberGatherer {
var bound_methods = new List<string> (); // List of methods bound on the class itself (not via protocols)
var generated_methods = new List<MemberInformation> (); // All method that have been generated
foreach (var mi in GetTypeContractMethods (type).OrderByDescending (m => m.Name == "Constructor").ThenBy (m => m.Name)) {
foreach (var mi in GetTypeContractMethods (type).OrderByDescending (m => m.Name == "Constructor").ThenBy (m => m.Name, StringComparer.Ordinal)) {
if (mi.IsSpecialName || (mi.Name == "Constructor" && type != mi.DeclaringType))
continue;
#if RETAIN_AUDITING
if (mi.Name.StartsWith ("Set"))
if (mi.Name.StartsWith ("Set", StringComparison.Ordinal))
foreach (ParameterInfo pi in mi.GetParameters ())
if (IsWrappedType (pi.ParameterType) || pi.ParameterType.IsArray) {
Console.WriteLine ("AUDIT: {0}", mi);
@ -6248,7 +6248,7 @@ public partial class Generator : IMemberGatherer {
var bound_properties = new List<string> (); // List of properties bound on the class itself (not via protocols)
var generated_properties = new List<string> (); // All properties that have been generated
foreach (var pi in GetTypeContractProperties (type).OrderBy (p => p.Name)) {
foreach (var pi in GetTypeContractProperties (type).OrderBy (p => p.Name, StringComparer.Ordinal)) {
#if !XAMCORE_2_0
if (HasAttribute (pi, typeof (AlphaAttribute)) && Alpha == false)
@ -6304,7 +6304,7 @@ public partial class Generator : IMemberGatherer {
}
if (field_exports.Count != 0){
foreach (var field_pi in field_exports.OrderBy (f => f.Name)) {
foreach (var field_pi in field_exports.OrderBy (f => f.Name, StringComparer.Ordinal)) {
var fieldAttr = (FieldAttribute) field_pi.GetCustomAttributes (typeof (FieldAttribute), true) [0];
string library_name;
string library_path = null;
@ -6336,7 +6336,7 @@ public partial class Generator : IMemberGatherer {
} else {
library_name = type.Namespace;
// note: not every binding namespace will start with ns.Prefix (e.g. MonoTouch.)
if (!String.IsNullOrEmpty (ns.Prefix) && library_name.StartsWith (ns.Prefix)) {
if (!String.IsNullOrEmpty (ns.Prefix) && library_name.StartsWith (ns.Prefix, StringComparison.Ordinal)) {
library_name = library_name.Substring (ns.Prefix.Length + 1);
library_name = library_name.Replace (".", string.Empty); // Remove dots from namespaces
}
@ -6481,7 +6481,7 @@ public partial class Generator : IMemberGatherer {
int delidx = 0;
foreach (var dtype in bta.Events) {
string delName = bta.Delegates [delidx++];
delName = delName.StartsWith ("Weak") ? delName.Substring(4) : delName;
delName = delName.StartsWith ("Weak", StringComparison.Ordinal) ? delName.Substring(4) : delName;
// Here's the problem:
// If you have two or more types in an inheritence structure in the binding that expose events
@ -6596,7 +6596,7 @@ public partial class Generator : IMemberGatherer {
string previous_miname = null;
int miname_count = 0;
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name)) {
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name, StringComparer.Ordinal)) {
if (ShouldSkipEventGeneration (mi))
continue;
@ -6742,7 +6742,7 @@ public partial class Generator : IMemberGatherer {
print ("return false;");
--indent;
print ("IntPtr selHandle = sel == null ? IntPtr.Zero : sel.Handle;");
foreach (var mi in noDefaultValue.OrderBy (m => m.Name)) {
foreach (var mi in noDefaultValue.OrderBy (m => m.Name, StringComparer.Ordinal)) {
if (InlineSelectors) {
var eattrs = mi.GetCustomAttributes (typeof (ExportAttribute), false);
var export = (ExportAttribute)eattrs[0];
@ -6778,8 +6778,8 @@ public partial class Generator : IMemberGatherer {
int minameCount = 0;
repeatedDelegateApiNames.Clear ();
// Now add the instance vars and event handlers
foreach (var dtype in bta.Events.OrderBy (d => d.Name)) {
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name)) {
foreach (var dtype in bta.Events.OrderBy (d => d.Name, StringComparer.Ordinal)) {
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name, StringComparer.Ordinal)) {
if (ShouldSkipEventGeneration (mi))
continue;
@ -6834,7 +6834,7 @@ public partial class Generator : IMemberGatherer {
if (instance_fields_to_clear_on_dispose.Count > 0) {
print ("if (Handle == IntPtr.Zero) {");
indent++;
foreach (var field in instance_fields_to_clear_on_dispose.OrderBy (f => f))
foreach (var field in instance_fields_to_clear_on_dispose.OrderBy (f => f, StringComparer.Ordinal))
print ("{0} = null;", field);
indent--;
print ("}");
@ -6867,7 +6867,7 @@ public partial class Generator : IMemberGatherer {
if (appearance_selectors != null){
var currently_ignored_fields = new List<string> ();
foreach (MemberInfo mi in appearance_selectors.OrderBy (m => m.Name)) {
foreach (MemberInfo mi in appearance_selectors.OrderBy (m => m.Name, StringComparer.Ordinal)) {
if (mi is MethodInfo)
GenerateMethod (type, mi as MethodInfo,
is_model: false,
@ -6933,7 +6933,7 @@ public partial class Generator : IMemberGatherer {
print ("//");
print ("public static partial class Notifications {\n");
foreach (var property in notifications.OrderBy (p => p.Name)) {
foreach (var property in notifications.OrderBy (p => p.Name, StringComparer.Ordinal)) {
string notification_name = GetNotificationName (property);
string notification_center = GetNotificationCenter (property);
@ -6959,7 +6959,7 @@ public partial class Generator : IMemberGatherer {
// Copy delegates from the API files into the output if they were declared there
//
var rootAssembly = types [0].Assembly;
foreach (var deltype in trampolines.Keys.OrderBy (d => d.Name)) {
foreach (var deltype in trampolines.Keys.OrderBy (d => d.Name, StringComparer.Ordinal)) {
if (deltype.Assembly != rootAssembly)
continue;
@ -6974,7 +6974,7 @@ public partial class Generator : IMemberGatherer {
print ("//");
}
// Now add the EventArgs classes
foreach (var eaclass in eventArgTypes.Keys.OrderBy (e => e)) {
foreach (var eaclass in eventArgTypes.Keys.OrderBy (e => e, StringComparer.Ordinal)) {
if (skipGeneration.ContainsKey (eaclass)){
continue;
}
@ -6986,14 +6986,14 @@ public partial class Generator : IMemberGatherer {
print ("public {0} ({1})", eaclass, RenderParameterDecl (pars.Skip (1), true));
print ("{");
indent++;
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name)) {
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name, StringComparer.Ordinal)) {
print ("this.{0} = {1};", GetPublicParameterName (p), p.Name);
}
indent--;
print ("}");
// Now print the properties
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name)) {
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name, StringComparer.Ordinal)) {
var bareType = p.ParameterType.IsByRef ? p.ParameterType.GetElementType () : p.ParameterType;
print ("public {0} {1} {{ get; set; }}", RenderType (bareType), GetPublicParameterName (p));
@ -7008,7 +7008,7 @@ public partial class Generator : IMemberGatherer {
print ("//");
}
foreach (var async_type in async_result_types.OrderBy (t => t.Item1)) {
foreach (var async_type in async_result_types.OrderBy (t => t.Item1, StringComparer.Ordinal)) {
if (async_result_types_emitted.Contains (async_type.Item1))
continue;
async_result_types_emitted.Add (async_type.Item1);
@ -7146,7 +7146,7 @@ public partial class Generator : IMemberGatherer {
bool ShouldSkipEventGeneration (MethodInfo mi)
{
// Skip property getter/setters
if (mi.IsSpecialName && (mi.Name.StartsWith ("get_") || mi.Name.StartsWith ("set_")))
if (mi.IsSpecialName && (mi.Name.StartsWith ("get_", StringComparison.Ordinal) || mi.Name.StartsWith ("set_", StringComparison.Ordinal)))
return true;
if (mi.IsUnavailable ())
@ -7167,8 +7167,8 @@ public partial class Generator : IMemberGatherer {
// Safely strips away any Weak from the beginning of either delegate and returns if they match
static bool CompareTwoDelegateNames (string lhsDel, string rhsDel)
{
lhsDel = lhsDel.StartsWith ("Weak") ? lhsDel.Substring (4): lhsDel;
rhsDel = rhsDel.StartsWith ("Weak") ? rhsDel.Substring (4): rhsDel;
lhsDel = lhsDel.StartsWith ("Weak", StringComparison.Ordinal) ? lhsDel.Substring (4): lhsDel;
rhsDel = rhsDel.StartsWith ("Weak", StringComparison.Ordinal) ? rhsDel.Substring (4): rhsDel;
return lhsDel == rhsDel;
}
@ -7216,7 +7216,7 @@ public partial class Generator : IMemberGatherer {
static string Capitalize (string str)
{
if (str.StartsWith ("@"))
if (str.StartsWith ("@", StringComparison.Ordinal))
return char.ToUpper (str[1]) + str.Substring (2);
return char.ToUpper (str[0]) + str.Substring (1);
@ -7235,7 +7235,7 @@ public partial class Generator : IMemberGatherer {
{
// TODO: fetch the NotificationAttribute, see if there is an override there.
var name = pi.Name;
if (name.EndsWith ("Notification"))
if (name.EndsWith ("Notification", StringComparison.Ordinal))
return name.Substring (0, name.Length-"Notification".Length);
return name;
}
@ -7346,7 +7346,7 @@ public partial class Generator : IMemberGatherer {
throw new BindingException (1004, true, "The delegate method {0}.{1} is missing the [EventArgs] attribute (has {2} parameters)", mi.DeclaringType.FullName, mi.Name, mi.GetParameters ().Length);
var ea = (EventArgsAttribute) a;
if (ea.ArgName.EndsWith ("EventArgs"))
if (ea.ArgName.EndsWith ("EventArgs", StringComparison.Ordinal))
throw new BindingException (1005, true, "EventArgs in {0}.{1} attribute should not include the text `EventArgs' at the end", mi.DeclaringType.FullName, mi.Name);
if (ea.SkipGeneration){