diff --git a/src/SIL.Machine.Morphology.HermitCrab/AnalysisAffixTemplateRule.cs b/src/SIL.Machine.Morphology.HermitCrab/AnalysisAffixTemplateRule.cs index 6331e2995..fd687e201 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/AnalysisAffixTemplateRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/AnalysisAffixTemplateRule.cs @@ -12,7 +12,7 @@ namespace SIL.Machine.Morphology.HermitCrab { - internal class AnalysisAffixTemplateRule : IRule + internal class AnalysisAffixTemplateRule : InstrumentedRule { private readonly Morpher _morpher; private readonly AffixTemplate _template; @@ -20,6 +20,7 @@ internal class AnalysisAffixTemplateRule : IRule public AnalysisAffixTemplateRule(Morpher morpher, AffixTemplate template) { + Name = template.Name; _morpher = morpher; _template = template; _rules = new List>( @@ -29,9 +30,10 @@ public AnalysisAffixTemplateRule(Morpher morpher, AffixTemplate template) FreezableEqualityComparer.Default )) ); + AddSubRules(_rules); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_template)) return Enumerable.Empty(); @@ -55,6 +57,8 @@ public IEnumerable Apply(Word input) foreach (Word outWord in output) outWord.SyntacticFeatureStruct.Add(fs); + + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs b/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs index b4673ca55..fd6b5e31f 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/AnalysisLanguageRule.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using SIL.Machine.Annotations; using SIL.Machine.Rules; @@ -6,7 +7,7 @@ namespace SIL.Machine.Morphology.HermitCrab { - internal class AnalysisLanguageRule : IRule + internal class AnalysisLanguageRule : InstrumentedRule { private readonly Morpher _morpher; private readonly List _strata; @@ -14,13 +15,16 @@ internal class AnalysisLanguageRule : IRule public AnalysisLanguageRule(Morpher morpher, Language language) { + Name = "Analysis"; _morpher = morpher; _strata = language.Strata.Reverse().ToList(); _rules = _strata.Select(stratum => stratum.CompileAnalysisRule(morpher)).ToList(); + AddSubRules(_rules); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { + long startTime = Stopwatch.GetTimestamp(); var inputSet = new HashSet(FreezableEqualityComparer.Default) { input }; var tempSet = new HashSet(FreezableEqualityComparer.Default); var results = new HashSet(FreezableEqualityComparer.Default); @@ -45,6 +49,8 @@ public IEnumerable Apply(Word input) inputSet = outputSet; } + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(results.Count()); return results; } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs b/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs index 36d9557ad..477c12fab 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/AnalysisStratumRule.cs @@ -8,7 +8,7 @@ namespace SIL.Machine.Morphology.HermitCrab { - internal class AnalysisStratumRule : IRule + internal class AnalysisStratumRule : InstrumentedRule { private readonly IRule _mrulesRule; private readonly IRule _prulesRule; @@ -18,6 +18,7 @@ internal class AnalysisStratumRule : IRule public AnalysisStratumRule(Morpher morpher, Stratum stratum) { + Name = stratum.Name; _stratum = stratum; _morpher = morpher; _prulesRule = new LinearRuleCascade( @@ -61,6 +62,9 @@ public AnalysisStratumRule(Morpher morpher, Stratum stratum) #endif break; } + AddSubRule(_prulesRule); + AddSubRule(_templatesRule); + AddSubRule(_mrulesRule); } private IRule CompileAffixTemplate(AffixTemplate template, Morpher morpher) @@ -99,8 +103,9 @@ private IRule CompilePhonologicalRule(IPhonologicalRule prule, } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { + long startTime = Stopwatch.GetTimestamp(); if (_morpher.TraceManager.IsTracing) _morpher.TraceManager.BeginUnapplyStratum(_stratum, input); @@ -144,6 +149,9 @@ public IEnumerable Apply(Word input) if (_morpher.MaxUnapplications > 0 && output.Count >= _morpher.MaxUnapplications) break; } + + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/Morpher.cs b/src/SIL.Machine.Morphology.HermitCrab/Morpher.cs index e4fd1879d..da6eaa0db 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/Morpher.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/Morpher.cs @@ -27,6 +27,7 @@ public class Morpher : IMorphologicalAnalyzer, IMorphologicalGenerator private readonly ITraceManager _traceManager; private readonly ReadOnlyObservableCollection _morphemes; private readonly IList _lexicalPatterns = new List(); + private bool _enableCorpusStatistics = false; public Morpher(ITraceManager traceManager, Language lang) { @@ -53,8 +54,9 @@ public Morpher(ITraceManager traceManager, Language lang) } _analysisRule = lang.CompileAnalysisRule(this); _synthesisRule = lang.CompileSynthesisRule(this); + ((InstrumentedRule)_synthesisRule).Name = "Synthesis"; MaxStemCount = 2; - MaxUnapplications = 0; + MaxUnapplications = 1000; MergeEquivalentAnalyses = true; LexEntrySelector = entry => true; RuleSelector = rule => true; @@ -84,6 +86,16 @@ public ITraceManager TraceManager /// public bool MergeEquivalentAnalyses { get; set; } + public bool EnableCorpusStatistics + { + get { return _enableCorpusStatistics; } + set + { + _enableCorpusStatistics = value; + ClearRuleStats(); + } + } + public Func LexEntrySelector { get; set; } public Func RuleSelector { get; set; } @@ -119,6 +131,10 @@ public IEnumerable ParseWord(string word, out object trace, bool guessRoot if (_traceManager.IsTracing) _traceManager.AnalyzeWord(_lang, input); trace = input.CurrentTrace; + if (!EnableCorpusStatistics) + { + ClearRuleStats(); + } // Unapply rules var analyses = new ConcurrentQueue(_analysisRule.Apply(input)); @@ -163,6 +179,34 @@ public IEnumerable ParseWord(string word, out object trace, bool guessRoot return syntheses; } + /// + /// Get the top-level rule statistics. + /// + public IEnumerable> GetRuleStats() + { + var list = new List>(); + if (_analysisRule is InstrumentedRule) + { + list.Add(_analysisRule as InstrumentedRule); + } + if (_synthesisRule is InstrumentedRule) + { + list.Add(_synthesisRule as InstrumentedRule); + } + return list; + } + + /// + /// Clear all rule statistics. + /// + public void ClearRuleStats() + { + foreach (InstrumentedRule rule in GetRuleStats()) + { + rule.ClearStats(); + } + } + /// /// Generates surface forms from the specified word synthesis information. /// diff --git a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisAffixProcessRule.cs b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisAffixProcessRule.cs index 4e89fef97..89a60410f 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisAffixProcessRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisAffixProcessRule.cs @@ -6,7 +6,7 @@ namespace SIL.Machine.Morphology.HermitCrab.MorphologicalRules { - public class AnalysisAffixProcessRule : IRule + public class AnalysisAffixProcessRule : InstrumentedRule { private readonly Morpher _morpher; private readonly AffixProcessRule _rule; @@ -14,6 +14,7 @@ public class AnalysisAffixProcessRule : IRule public AnalysisAffixProcessRule(Morpher morpher, AffixProcessRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -36,7 +37,7 @@ public AnalysisAffixProcessRule(Morpher morpher, AffixProcessRule rule) } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -70,6 +71,8 @@ public IEnumerable Apply(Word input) if (_morpher.TraceManager.IsTracing && !unapplied) _morpher.TraceManager.MorphologicalRuleNotUnapplied(_rule, i, input); } + + AddRuleStats(output.Count); return output; } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisCompoundingRule.cs b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisCompoundingRule.cs index 6dc2a0c28..59a54d5ff 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisCompoundingRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisCompoundingRule.cs @@ -6,7 +6,7 @@ namespace SIL.Machine.Morphology.HermitCrab.MorphologicalRules { - public class AnalysisCompoundingRule : IRule + public class AnalysisCompoundingRule : InstrumentedRule { private readonly Morpher _morpher; private readonly CompoundingRule _rule; @@ -14,6 +14,7 @@ public class AnalysisCompoundingRule : IRule public AnalysisCompoundingRule(Morpher morpher, CompoundingRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -36,7 +37,7 @@ public AnalysisCompoundingRule(Morpher morpher, CompoundingRule rule) } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -143,6 +144,7 @@ RootAllomorph allo in _morpher.SearchRootAllomorphs(_rule.Stratum, outWord.Curre _morpher.TraceManager.MorphologicalRuleNotUnapplied(_rule, i, input); } + AddRuleStats(output.Count); return output; } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisRealizationalAffixProcessRule.cs b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisRealizationalAffixProcessRule.cs index 749aa7b4d..153dbe802 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisRealizationalAffixProcessRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/AnalysisRealizationalAffixProcessRule.cs @@ -7,7 +7,7 @@ namespace SIL.Machine.Morphology.HermitCrab.MorphologicalRules { - public class AnalysisRealizationalAffixProcessRule : IRule + public class AnalysisRealizationalAffixProcessRule : InstrumentedRule { private readonly Morpher _morpher; private readonly RealizationalAffixProcessRule _rule; @@ -15,6 +15,7 @@ public class AnalysisRealizationalAffixProcessRule : IRule public AnalysisRealizationalAffixProcessRule(Morpher morpher, RealizationalAffixProcessRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -37,7 +38,7 @@ public AnalysisRealizationalAffixProcessRule(Morpher morpher, RealizationalAffix } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -65,6 +66,8 @@ public IEnumerable Apply(Word input) if (_morpher.TraceManager.IsTracing && !unapplied) _morpher.TraceManager.MorphologicalRuleNotUnapplied(_rule, i, input); } + + AddRuleStats(output.Count); return output; } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisAffixProcessRule.cs b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisAffixProcessRule.cs index f7dc9c0dc..accf39a18 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisAffixProcessRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisAffixProcessRule.cs @@ -8,7 +8,7 @@ namespace SIL.Machine.Morphology.HermitCrab.MorphologicalRules { - public class SynthesisAffixProcessRule : IRule + public class SynthesisAffixProcessRule : InstrumentedRule { private readonly Morpher _morpher; private readonly AffixProcessRule _rule; @@ -16,6 +16,7 @@ public class SynthesisAffixProcessRule : IRule public SynthesisAffixProcessRule(Morpher morpher, AffixProcessRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; _rules = new List>(); @@ -38,7 +39,7 @@ public SynthesisAffixProcessRule(Morpher morpher, AffixProcessRule rule) } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!input.IsMorphologicalRuleApplicable(_rule)) return Enumerable.Empty(); @@ -232,6 +233,7 @@ public IEnumerable Apply(Word input) } } + AddRuleStats(output.Count); return output; } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisCompoundingRule.cs b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisCompoundingRule.cs index a8f16e650..8db9bb081 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisCompoundingRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisCompoundingRule.cs @@ -9,7 +9,7 @@ namespace SIL.Machine.Morphology.HermitCrab.MorphologicalRules { - public class SynthesisCompoundingRule : IRule + public class SynthesisCompoundingRule : InstrumentedRule { private readonly Morpher _morpher; private readonly CompoundingRule _rule; @@ -17,6 +17,7 @@ public class SynthesisCompoundingRule : IRule public SynthesisCompoundingRule(Morpher morpher, CompoundingRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; _subruleMatchers = new List, Matcher>>(); @@ -42,7 +43,7 @@ private Matcher BuildMatcher(IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!input.IsMorphologicalRuleApplicable(_rule)) return Enumerable.Empty(); @@ -223,6 +224,7 @@ public IEnumerable Apply(Word input) } } + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisRealizationalAffixProcessRule.cs b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisRealizationalAffixProcessRule.cs index 1ea640909..433b650d8 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisRealizationalAffixProcessRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/MorphologicalRules/SynthesisRealizationalAffixProcessRule.cs @@ -9,7 +9,7 @@ namespace SIL.Machine.Morphology.HermitCrab.MorphologicalRules { - public class SynthesisRealizationalAffixProcessRule : IRule + public class SynthesisRealizationalAffixProcessRule : InstrumentedRule { private readonly Morpher _morpher; private readonly RealizationalAffixProcessRule _rule; @@ -17,6 +17,7 @@ public class SynthesisRealizationalAffixProcessRule : IRule public SynthesisRealizationalAffixProcessRule(Morpher morpher, RealizationalAffixProcessRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; _rules = new List>(); @@ -38,7 +39,7 @@ public SynthesisRealizationalAffixProcessRule(Morpher morpher, RealizationalAffi } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -162,6 +163,7 @@ public IEnumerable Apply(Word input) } } + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisMetathesisRule.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisMetathesisRule.cs index 8b21c1853..e75770587 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisMetathesisRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisMetathesisRule.cs @@ -8,7 +8,7 @@ namespace SIL.Machine.Morphology.HermitCrab.PhonologicalRules { - public class AnalysisMetathesisRule : IRule + public class AnalysisMetathesisRule : InstrumentedRule { private readonly Morpher _morpher; private readonly MetathesisRule _rule; @@ -16,6 +16,7 @@ public class AnalysisMetathesisRule : IRule public AnalysisMetathesisRule(Morpher morpher, MetathesisRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -35,7 +36,7 @@ public AnalysisMetathesisRule(Morpher morpher, MetathesisRule rule) _patternRule = new IterativePhonologicalPatternRule(ruleSpec, settings); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -48,7 +49,11 @@ public IEnumerable Apply(Word input) { if (_morpher.TraceManager.IsTracing) _morpher.TraceManager.PhonologicalRuleUnapplied(_rule, -1, origInput, input); - return input.ToEnumerable(); + { + IEnumerable output = input.ToEnumerable(); + AddRuleStats(output.Count()); + return output; + } } if (_morpher.TraceManager.IsTracing) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisRewriteRule.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisRewriteRule.cs index 95eacbf73..5ebfa0e97 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisRewriteRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/AnalysisRewriteRule.cs @@ -10,7 +10,7 @@ namespace SIL.Machine.Morphology.HermitCrab.PhonologicalRules { - public class AnalysisRewriteRule : IRule + public class AnalysisRewriteRule : InstrumentedRule { private enum ReapplyType { @@ -25,6 +25,7 @@ private enum ReapplyType public AnalysisRewriteRule(Morpher morpher, RewriteRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -125,7 +126,7 @@ Constraint curConstraint in env.GetNodesDepthFirst() return true; } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -188,7 +189,11 @@ public IEnumerable Apply(Word input) } if (applied) - return input.ToEnumerable(); + { + IEnumerable output = input.ToEnumerable(); + AddRuleStats(output.Count()); + return output; + } return Enumerable.Empty(); } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisMetathesisRule.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisMetathesisRule.cs index 2ea546df2..3687530b0 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisMetathesisRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisMetathesisRule.cs @@ -7,7 +7,7 @@ namespace SIL.Machine.Morphology.HermitCrab.PhonologicalRules { - public class SynthesisMetathesisRule : IRule + public class SynthesisMetathesisRule : InstrumentedRule { private readonly Morpher _morpher; private readonly MetathesisRule _rule; @@ -15,6 +15,7 @@ public class SynthesisMetathesisRule : IRule public SynthesisMetathesisRule(Morpher morpher, MetathesisRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -32,7 +33,7 @@ public SynthesisMetathesisRule(Morpher morpher, MetathesisRule rule) _patternRule = new IterativePhonologicalPatternRule(ruleSpec, settings); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -45,7 +46,9 @@ public IEnumerable Apply(Word input) { if (_morpher.TraceManager.IsTracing) _morpher.TraceManager.PhonologicalRuleApplied(_rule, -1, origInput, input); - return input.ToEnumerable(); + IEnumerable output = input.ToEnumerable(); + AddRuleStats(output.Count()); + return output; } if (_morpher.TraceManager.IsTracing) diff --git a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisRewriteRule.cs b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisRewriteRule.cs index 1dc7e3ca5..77c93e08f 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisRewriteRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/PhonologicalRules/SynthesisRewriteRule.cs @@ -8,7 +8,7 @@ namespace SIL.Machine.Morphology.HermitCrab.PhonologicalRules { - public class SynthesisRewriteRule : IRule + public class SynthesisRewriteRule : InstrumentedRule { private readonly Morpher _morpher; private readonly RewriteRule _rule; @@ -16,6 +16,7 @@ public class SynthesisRewriteRule : IRule public SynthesisRewriteRule(Morpher morpher, RewriteRule rule) { + Name = rule.Name; _morpher = morpher; _rule = rule; @@ -48,7 +49,7 @@ public SynthesisRewriteRule(Morpher morpher, RewriteRule rule) } } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_rule)) return Enumerable.Empty(); @@ -84,7 +85,11 @@ public IEnumerable Apply(Word input) input.CurrentRuleResults = null; } if (applied) - return input.ToEnumerable(); + { + IEnumerable output = input.ToEnumerable(); + AddRuleStats(output.Count()); + return output; + } return Enumerable.Empty(); } } diff --git a/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplateRule.cs b/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplateRule.cs index e8cf7ee17..e249915f5 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplateRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplateRule.cs @@ -6,7 +6,7 @@ namespace SIL.Machine.Morphology.HermitCrab { - internal class SynthesisAffixTemplateRule : IRule + internal class SynthesisAffixTemplateRule : InstrumentedRule { private readonly Morpher _morpher; private readonly AffixTemplate _template; @@ -14,6 +14,7 @@ internal class SynthesisAffixTemplateRule : IRule public SynthesisAffixTemplateRule(Morpher morpher, AffixTemplate template) { + Name = template.Name; _morpher = morpher; _template = template; _rules = new List>( @@ -23,14 +24,16 @@ public SynthesisAffixTemplateRule(Morpher morpher, AffixTemplate template) FreezableEqualityComparer.Default )) ); + AddSubRules(_rules); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (_morpher.TraceManager.IsTracing) _morpher.TraceManager.BeginApplyTemplate(_template, input); var output = new HashSet(FreezableEqualityComparer.Default); ApplySlots(input, 0, output); + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplatesRule.cs b/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplatesRule.cs index 1d878cd75..4af537652 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplatesRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/SynthesisAffixTemplatesRule.cs @@ -7,7 +7,7 @@ namespace SIL.Machine.Morphology.HermitCrab { - internal class SynthesisAffixTemplatesRule : IRule + internal class SynthesisAffixTemplatesRule : InstrumentedRule { private readonly Morpher _morpher; private readonly Stratum _stratum; @@ -16,13 +16,15 @@ internal class SynthesisAffixTemplatesRule : IRule public SynthesisAffixTemplatesRule(Morpher morpher, Stratum stratum) { + Name = stratum.Name; _morpher = morpher; _stratum = stratum; _templates = stratum.AffixTemplates.ToList(); _templateRules = _templates.Select(temp => temp.CompileSynthesisRule(morpher)).ToList(); + AddSubRules(_templateRules); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!input.RealizationalFeatureStruct.IsUnifiable(input.SyntacticFeatureStruct)) return Enumerable.Empty(); @@ -74,6 +76,7 @@ public IEnumerable Apply(Word input) } } + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine.Morphology.HermitCrab/SynthesisStratumRule.cs b/src/SIL.Machine.Morphology.HermitCrab/SynthesisStratumRule.cs index a15a6de5b..10bad3452 100644 --- a/src/SIL.Machine.Morphology.HermitCrab/SynthesisStratumRule.cs +++ b/src/SIL.Machine.Morphology.HermitCrab/SynthesisStratumRule.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using SIL.Extensions; using SIL.Machine.Annotations; @@ -7,7 +8,7 @@ namespace SIL.Machine.Morphology.HermitCrab { - internal class SynthesisStratumRule : IRule + internal class SynthesisStratumRule : InstrumentedRule { private readonly IRule _mrulesRule; private readonly IRule _prulesRule; @@ -17,6 +18,7 @@ internal class SynthesisStratumRule : IRule public SynthesisStratumRule(Morpher morpher, Stratum stratum) { + Name = stratum.Name; _templatesRule = new SynthesisAffixTemplatesRule(morpher, stratum); _mrulesRule = null; IEnumerable> mrules = stratum.MorphologicalRules.Select(mrule => @@ -44,9 +46,12 @@ public SynthesisStratumRule(Morpher morpher, Stratum stratum) ); _stratum = stratum; _morpher = morpher; + AddSubRule(_mrulesRule); + AddSubRule(_prulesRule); + AddSubRule(_templatesRule); } - public IEnumerable Apply(Word input) + public override IEnumerable Apply(Word input) { if (!_morpher.RuleSelector(_stratum) || input.RootAllomorph.Morpheme.Stratum.Depth > _stratum.Depth) return input.ToEnumerable(); @@ -54,6 +59,7 @@ public IEnumerable Apply(Word input) if (_morpher.TraceManager.IsTracing) _morpher.TraceManager.BeginApplyStratum(_stratum, input); + long startTime = Stopwatch.GetTimestamp(); var output = new HashSet(FreezableEqualityComparer.Default); foreach (Word mruleOutWord in ApplyMorphologicalRules(input).Concat(ApplyTemplates(input))) { @@ -88,6 +94,9 @@ public IEnumerable Apply(Word input) } if (_morpher.TraceManager.IsTracing && output.Count == 0) _morpher.TraceManager.EndApplyStratum(_stratum, input); + + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine/Rules/CombinationRuleCascade.cs b/src/SIL.Machine/Rules/CombinationRuleCascade.cs index 25fdfb8c6..e933ac18c 100644 --- a/src/SIL.Machine/Rules/CombinationRuleCascade.cs +++ b/src/SIL.Machine/Rules/CombinationRuleCascade.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using SIL.Machine.Annotations; namespace SIL.Machine.Rules @@ -24,8 +25,11 @@ IEqualityComparer comparer public override IEnumerable Apply(TData input) { + long startTime = Stopwatch.GetTimestamp(); var output = new HashSet(Comparer); ApplyRules(input, !MultipleApplication ? new HashSet() : null, output); + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine/Rules/InstrumentedRule.cs b/src/SIL.Machine/Rules/InstrumentedRule.cs new file mode 100644 index 000000000..3c7424c85 --- /dev/null +++ b/src/SIL.Machine/Rules/InstrumentedRule.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.Linq; +using SIL.Machine.Annotations; + +namespace SIL.Machine.Rules +{ + /// + /// This class instruments IRules. + /// Statistics are stored in InputCount, OutputCount, and ElapsedTime. + /// The rules update the statistics when Apply is called. + /// Name and SubRules are filled in when the rule is created. + /// + /// + /// + public abstract class InstrumentedRule : IRule + where TData : IAnnotatedData + { + public string Name { get; set; } + public int InputCount; + public int OutputCount; + public long ElapsedTime; + public IList> SubRules = new List>(); + + public InstrumentedRule() { } + + /// + /// Add sub-rules to the rule statisics. + /// + /// + protected void AddSubRules(IEnumerable> rules) + { + foreach (IRule rule in rules) + { + AddSubRule(rule); + } + } + + protected void AddSubRule(IRule rule) + { + SubRules.Add(rule as InstrumentedRule); + } + + /// + /// Add input count and output count to the rule statistics. + /// + protected void AddRuleStats(int outputCount) + { + if (outputCount > 0) + { + InputCount++; + OutputCount += outputCount; + } + } + + /// + /// Add elapsed time to the rule statistics. + /// + protected void AddElapsedTime(long elapsedTime) + { + ElapsedTime += elapsedTime; + } + + /// + /// Sort SubRules unless the order matters. + /// + public void SortSubRules() + { + if (Name == "Analysis" || Name == "Synthesis" || Name == "RuleCascade") + { + return; + } + SubRules = SubRules.OrderByDescending(rule => rule.OutputCount).ToList(); + } + + /// + /// Clear all rule statistics. + /// + public void ClearStats() + { + InputCount = 0; + OutputCount = 0; + ElapsedTime = 0; + foreach (InstrumentedRule rule in SubRules) + { + rule.ClearStats(); + } + } + + public abstract IEnumerable Apply(TData input); + } +} diff --git a/src/SIL.Machine/Rules/LinearRuleCascade.cs b/src/SIL.Machine/Rules/LinearRuleCascade.cs index b4e985a33..9394dbfc2 100644 --- a/src/SIL.Machine/Rules/LinearRuleCascade.cs +++ b/src/SIL.Machine/Rules/LinearRuleCascade.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using SIL.Machine.Annotations; namespace SIL.Machine.Rules @@ -24,8 +25,11 @@ IEqualityComparer comparer public override IEnumerable Apply(TData input) { + long startTime = Stopwatch.GetTimestamp(); var output = new HashSet(Comparer); ApplyRules(input, 0, output); + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine/Rules/ParallelRuleBatch.cs b/src/SIL.Machine/Rules/ParallelRuleBatch.cs index afe053c79..7c90a0abe 100644 --- a/src/SIL.Machine/Rules/ParallelRuleBatch.cs +++ b/src/SIL.Machine/Rules/ParallelRuleBatch.cs @@ -28,7 +28,9 @@ public override IEnumerable Apply(TData input) } ); - return output.Distinct(Comparer); + IEnumerable distinctOutput = output.Distinct(Comparer); + AddRuleStats(distinctOutput.Count()); + return distinctOutput; } } } diff --git a/src/SIL.Machine/Rules/PermutationRuleCascade.cs b/src/SIL.Machine/Rules/PermutationRuleCascade.cs index b16671f44..9fc3ce36a 100644 --- a/src/SIL.Machine/Rules/PermutationRuleCascade.cs +++ b/src/SIL.Machine/Rules/PermutationRuleCascade.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using SIL.Machine.Annotations; namespace SIL.Machine.Rules @@ -24,8 +25,11 @@ IEqualityComparer comparer public override IEnumerable Apply(TData input) { + long startTime = Stopwatch.GetTimestamp(); var output = new HashSet(Comparer); ApplyRules(input, 0, output); + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(output.Count); return output; } diff --git a/src/SIL.Machine/Rules/PipelineRuleCascade.cs b/src/SIL.Machine/Rules/PipelineRuleCascade.cs index 524300883..c8ef172d8 100644 --- a/src/SIL.Machine/Rules/PipelineRuleCascade.cs +++ b/src/SIL.Machine/Rules/PipelineRuleCascade.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using SIL.Machine.Annotations; namespace SIL.Machine.Rules @@ -14,6 +15,7 @@ public PipelineRuleCascade(IEnumerable> rules, IEqualityCo public override IEnumerable Apply(TData input) { + long startTime = Stopwatch.GetTimestamp(); var inputSet = new HashSet(Comparer) { input }; HashSet outputSet = null; var tempSet = new HashSet(Comparer); @@ -29,6 +31,8 @@ public override IEnumerable Apply(TData input) inputSet = outputSet; } + AddElapsedTime(Stopwatch.GetTimestamp() - startTime); + AddRuleStats(outputSet.Count); return outputSet; } } diff --git a/src/SIL.Machine/Rules/RuleBatch.cs b/src/SIL.Machine/Rules/RuleBatch.cs index 61249068b..24a9c29bd 100644 --- a/src/SIL.Machine/Rules/RuleBatch.cs +++ b/src/SIL.Machine/Rules/RuleBatch.cs @@ -4,7 +4,7 @@ namespace SIL.Machine.Rules { - public class RuleBatch : IRule + public class RuleBatch : InstrumentedRule where TData : IAnnotatedData { private readonly List> _rules; @@ -22,9 +22,11 @@ public RuleBatch(IEnumerable> rules, bool disjunctive) public RuleBatch(IEnumerable> rules, bool disjunctive, IEqualityComparer comparer) { + Name = "RuleBatch"; _rules = new List>(rules); _disjunctive = disjunctive; _comparer = comparer; + AddSubRules(_rules); } public IReadOnlyList> Rules @@ -42,7 +44,7 @@ public bool IsDisjunctive get { return _disjunctive; } } - public virtual IEnumerable Apply(TData input) + public override IEnumerable Apply(TData input) { var output = new HashSet(_comparer); foreach (IRule rule in _rules) @@ -52,6 +54,7 @@ public virtual IEnumerable Apply(TData input) return output; } + AddRuleStats(output.Count); return output; } } diff --git a/src/SIL.Machine/Rules/RuleCascade.cs b/src/SIL.Machine/Rules/RuleCascade.cs index a139e8ced..df44aacbf 100644 --- a/src/SIL.Machine/Rules/RuleCascade.cs +++ b/src/SIL.Machine/Rules/RuleCascade.cs @@ -5,7 +5,7 @@ namespace SIL.Machine.Rules { - public abstract class RuleCascade : IRule + public abstract class RuleCascade : InstrumentedRule where TData : IAnnotatedData { private readonly ReadOnlyList> _rules; @@ -27,9 +27,11 @@ protected RuleCascade( IEqualityComparer comparer ) { + Name = "RuleCascade"; _rules = new ReadOnlyList>(rules.ToList()); _multiApp = multiApp; _comparer = comparer; + AddSubRules(_rules); } public IEqualityComparer Comparer @@ -47,7 +49,7 @@ public IReadOnlyList> Rules get { return _rules; } } - public abstract IEnumerable Apply(TData input); + public abstract override IEnumerable Apply(TData input); protected virtual IEnumerable ApplyRule(IRule rule, int index, TData input) {