Skip to content

Commit e6177ed

Browse files
committed
0.21.0 - Performance improvements (~15-20%) and more in-depth performance related logging.
1 parent 7482a2a commit e6177ed

24 files changed

+267
-267
lines changed

CHANGELOG.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@ This project does its best to adhere to [Semantic Versioning](http://semver.org/
44

55

66
--------
7-
### [0.20.0](N/A) - 2020-11-22
7+
### [0.21.0](https://github.com/TeamworkGuy2/JParseCode/commit/7482a2a148a5f42e230c33897d3f17d907c5348f) - 2020-11-22
8+
__Parsing performance optimizations (~15-20%)__
9+
#### Changed
10+
* Update dependencies `jtext-tokenizer@0.7.0` and `jtext-parser@0.18.0`
11+
* `ParserActionLogger` and `ParseTimes` optimizations and changes to work with `jtext-tokenizer` new `TokenizationLogger`
12+
* `JavaFileTokenizer`, `CsFileTokenizer`, `CommentTokenizer`, `IdentifierTokenizer`, and `NumberTokenizer` `reusable/reusableCharParsers` flag implementation to control which `CharParserMatchableFactory` implementation is used
13+
* `CodeTokenizer.tokenizeDocument()` `fragmentConstructor` parameter optimization to skip creating fragment source string twice, major performance improvement ~5-10%
14+
* New aggregate performance logging output for text tokenization related counters
15+
16+
17+
--------
18+
### [0.20.0](https://github.com/TeamworkGuy2/JParseCode/commit/7482a2a148a5f42e230c33897d3f17d907c5348f) - 2020-11-22
819
__Method generic type parameters parsing support__ (i.e. 'public T Create<T>()' in C#).
920
#### Added
1021
* Method generic type parameters added - `MethodSig` and sub-classes have a new `typeParameters` field. Note: if these 'types' contain lower/upper type bounds these are included in the `typeName` property in Java and are not yet included in C# parsing

bin/jparse_code-with-tests.jar

-779 Bytes
Binary file not shown.

bin/jparse_code.jar

-979 Bytes
Binary file not shown.

package-lib.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version" : "0.20.0",
2+
"version" : "0.21.0",
33
"name" : "jparse-code",
44
"description" : "An in-progress suite of parsing/transpilation tools for C#, Java, and TypeScript code. Generates simple JSON ASTs.",
55
"homepage" : "https://github.com/TeamworkGuy2/JParseCode",

src/twg2/parser/codeParser/analytics/ParseTimes.java

+28-36
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.io.IOException;
44
import java.util.Map;
55

6-
import twg2.dataUtil.dataUtils.EnumError;
76
import twg2.io.files.FileUtil;
87
import twg2.io.json.stringify.JsonStringify;
98
import twg2.parser.output.JsonWritableSig;
@@ -15,17 +14,6 @@
1514
* @since 2016-09-07
1615
*/
1716
public class ParseTimes implements JsonWritableSig {
18-
19-
20-
public static enum TrackerAction {
21-
SETUP,
22-
READ,
23-
TOKENIZE,
24-
EXTRACT_AST;
25-
}
26-
27-
28-
2917
long setupNs;
3018
long readNs;
3119
long tokenizeNs;
@@ -57,23 +45,23 @@ public long getTotalNs() {
5745
}
5846

5947

60-
public void setActionTime(TrackerAction action, long timeNanos) {
61-
switch(action) {
62-
case SETUP:
63-
this.setupNs = timeNanos;
64-
break;
65-
case READ:
66-
this.readNs = timeNanos;
67-
break;
68-
case TOKENIZE:
69-
this.tokenizeNs = timeNanos;
70-
break;
71-
case EXTRACT_AST:
72-
this.extractAstNs = timeNanos;
73-
break;
74-
default:
75-
throw EnumError.unknownValue(action, TrackerAction.class);
76-
}
48+
public void setTimeSetup(long setupNanos) {
49+
this.setupNs = setupNanos;
50+
}
51+
52+
53+
public void setTimeRead(long readNanos) {
54+
this.readNs = readNanos;
55+
}
56+
57+
58+
public void setTimeTokenize(long tokenizeNanos) {
59+
this.tokenizeNs = tokenizeNanos;
60+
}
61+
62+
63+
public void setTimeExtractAst(long extractAstNanos) {
64+
this.extractAstNs = extractAstNanos;
7765
}
7866

7967

@@ -104,7 +92,7 @@ public String toString() {
10492

10593

10694
public String toString(String srcName, boolean includeClassName) {
107-
return (includeClassName ? "parserPerformance: { " : "") +
95+
return (includeClassName ? "parseTimes: { " : "") +
10896
(srcName != null ? ("file: " + srcName + ", ") : "") +
10997
"setup: " + roundNsToMs(this.setupNs) + ", " +
11098
"read: " + roundNsToMs(this.readNs) + ", " +
@@ -115,7 +103,7 @@ public String toString(String srcName, boolean includeClassName) {
115103
}
116104

117105

118-
public static final void toJsons(Map<String, ParseTimes> fileParseTimes, boolean includeSurroundingBrackets, Appendable dst, WriteSettings st) throws IOException {
106+
public static void toJsons(Map<String, ParseTimes> fileParseTimes, boolean includeSurroundingBrackets, Appendable dst, WriteSettings st) throws IOException {
119107
if(includeSurroundingBrackets) { dst.append("[\n"); }
120108
JsonStringify.inst.joinConsume(fileParseTimes.entrySet(), ",\n", dst, (entry) -> {
121109
var stat = entry.getValue();
@@ -126,14 +114,13 @@ public static final void toJsons(Map<String, ParseTimes> fileParseTimes, boolean
126114
}
127115

128116

129-
public static final String toStrings(Map<String, ParseTimes> fileParseTimes) {
117+
public static String toStrings(Map<String, ParseTimes> fileParseTimes) {
130118
long total = 0;
131119
var sb = new StringBuilder();
132120

133121
for(var entry : fileParseTimes.entrySet()) {
134122
var stat = entry.getValue();
135-
long subtotal = stat.setupNs + stat.readNs + stat.tokenizeNs + stat.extractAstNs;
136-
total += subtotal;
123+
total += stat.getTotalNs();
137124

138125
String fileName = FileUtil.getFileNameWithoutExtension(entry.getKey());
139126
fileName = '"' + fileName.substring(0, Math.min(30, fileName.length())) + '"';
@@ -148,8 +135,13 @@ public static final String toStrings(Map<String, ParseTimes> fileParseTimes) {
148135
}
149136

150137

151-
public static String roundNsToMs(long ns) {
152-
return String.format("%.2f", ns/1000000D);
138+
public static String roundNsToMs(long nanos) {
139+
return String.format("%.2f", nanos / 1000000D);
140+
}
141+
142+
143+
public static String roundNsToMs(long nanos, int decimalPlaces) {
144+
return String.format("%." + decimalPlaces + "f", nanos / 1000000D);
153145
}
154146

155147
}

src/twg2/parser/codeParser/analytics/ParserActionLogger.java

+66-99
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,74 @@
11
package twg2.parser.codeParser.analytics;
22

33
import java.io.IOException;
4-
import java.util.EnumMap;
4+
import java.util.ArrayList;
5+
import java.util.Collection;
6+
import java.util.List;
57
import java.util.Map;
68

79
import twg2.io.files.FileUtil;
810
import twg2.io.json.stringify.JsonStringify;
11+
import twg2.parser.condition.text.CharParser;
912
import twg2.parser.output.JsonWritableSig;
1013
import twg2.parser.output.WriteSettings;
1114
import twg2.text.stringEscape.StringEscapeJson;
1215
import twg2.text.stringUtils.StringPad;
13-
import twg2.text.tokenizer.analytics.ParserAction;
14-
import twg2.text.tokenizer.analytics.TypedLogger;
16+
import twg2.text.tokenizer.CharParserFactory;
17+
import twg2.text.tokenizer.CharParserMatchableFactory;
18+
import twg2.text.tokenizer.analytics.TokenizationLogger;
1519

1620
/**
1721
* @author TeamworkGuy2
1822
* @since 2016-09-11
1923
*/
20-
public class ParserActionLogger implements TypedLogger<ParserAction, WriteSettings>, JsonWritableSig {
21-
22-
static class CountAndDurationLog {
23-
String msg;
24-
long count;
25-
double durationMilliseconds;
26-
27-
28-
@Override
29-
public String toString() {
30-
return (this.msg != null ? "msg: " + this.msg + ", " : "") +
31-
(this.count != 0 ? "count: " + this.count + ", " : "") +
32-
(this.durationMilliseconds != 0 ? "durationMillis: " + this.durationMilliseconds : "");
33-
}
34-
35-
36-
public void toJson(Appendable dst, WriteSettings st) throws IOException {
37-
var json = JsonStringify.inst;
38-
39-
json.append("{ ", dst);
40-
41-
if(this.msg != null) {
42-
json.comma(dst).toProp("message", this.msg, dst);
43-
}
44-
45-
if(this.count != 0) {
46-
json.comma(dst).toProp("count", this.count, dst);
47-
}
48-
49-
if(this.durationMilliseconds != 0) {
50-
json.comma(dst).toProp("durationMillis", this.durationMilliseconds, dst);
51-
}
52-
53-
json.append(" }", dst);
54-
}
55-
56-
}
57-
58-
59-
Map<ParserAction, CountAndDurationLog> actions;
24+
public class ParserActionLogger implements TokenizationLogger, JsonWritableSig {
25+
public int countCompoundCharParserMatch;
26+
public int countCompoundCharParserAcceptNext;
27+
public int countCreateParser;
28+
public int countTextFragmentsConsumed;
29+
public int totalParserReuseCount;
30+
public List<CharParserMatchableFactory.Reusable<CharParser>> reusableParserFactories;
6031

6132

6233
public ParserActionLogger() {
63-
this.actions = new EnumMap<>(ParserAction.class);
64-
}
65-
66-
67-
public CountAndDurationLog getLog(ParserAction action) {
68-
return this.actions.get(action);
6934
}
7035

7136

72-
public String getLogMsg(ParserAction action) {
73-
var res = this.actions.get(action);
74-
return res != null ? res.msg : null;
75-
}
76-
77-
78-
public long getLogCount(ParserAction action) {
79-
var res = this.actions.get(action);
80-
return res != null ? res.count : 0;
37+
@Override
38+
public void logCountCompoundCharParserMatch(int count) {
39+
countCompoundCharParserMatch += count;
8140
}
8241

8342

84-
public double getLogDuration(ParserAction action) {
85-
var res = this.actions.get(action);
86-
return res != null ? res.durationMilliseconds : 0;
43+
@Override
44+
public void logCountCompoundCharParserAcceptNext(int count) {
45+
countCompoundCharParserAcceptNext += count;
8746
}
8847

8948

9049
@Override
91-
public void logMsg(ParserAction action, String msg) {
92-
getTypedAction(action).msg = msg;
50+
public void logCountCreateParser(int count) {
51+
countCreateParser += count;
9352
}
9453

9554

9655
@Override
97-
public void logCount(ParserAction action, long count) {
98-
getTypedAction(action).count += count;
56+
public void logCountTextFragmentsConsumed(int count) {
57+
countTextFragmentsConsumed += count;
9958
}
10059

10160

102-
@Override
103-
public void logDuration(ParserAction action, double durationMilliseconds) {
104-
getTypedAction(action).durationMilliseconds += durationMilliseconds;
61+
public void logCharParserFactoryReuse(Collection<? extends CharParserFactory> charParserFactories) {
62+
this.reusableParserFactories = new ArrayList<>();
63+
64+
for(var parserFactory : charParserFactories) {
65+
if(parserFactory instanceof CharParserMatchableFactory.Reusable) {
66+
@SuppressWarnings("unchecked")
67+
var parserFactoryReusable = (CharParserMatchableFactory.Reusable<CharParser>)parserFactory;
68+
reusableParserFactories.add(parserFactoryReusable);
69+
totalParserReuseCount += parserFactoryReusable.getReuseCount();
70+
}
71+
}
10572
}
10673

10774

@@ -111,7 +78,6 @@ public void toJson(Appendable dst, WriteSettings st) throws IOException {
11178
}
11279

11380

114-
@Override
11581
public void toJson(String srcName, boolean includeSurroundingBrackets, Appendable dst, WriteSettings st) throws IOException {
11682
if(includeSurroundingBrackets) { dst.append("{\n"); }
11783
if(srcName != null) {
@@ -120,16 +86,20 @@ public void toJson(String srcName, boolean includeSurroundingBrackets, Appendabl
12086
dst.append("\"");
12187
}
12288

123-
boolean first = true;
124-
for(ParserAction action : ParserAction.values()) {
125-
var data = this.actions.get(action);
126-
if(data != null) {
127-
if(!first || srcName != null) { dst.append(",\n"); }
128-
String name = action.name();
129-
dst.append("\t\"").append(name).append("\": ");
130-
data.toJson(dst, st);
131-
first = false;
132-
}
89+
if(countCompoundCharParserMatch > 0) {
90+
dst.append("\t\"compoundCharParserMatch\": ").append(Integer.toString(countCompoundCharParserMatch));
91+
}
92+
if(countCompoundCharParserAcceptNext > 0) {
93+
dst.append(",\n");
94+
dst.append("\t\"compoundCharParserAcceptNext\": ").append(Integer.toString(countCompoundCharParserAcceptNext));
95+
}
96+
if(countCreateParser > 0) {
97+
dst.append(",\n");
98+
dst.append("\t\"createParser\": ").append(Integer.toString(countCreateParser));
99+
}
100+
if(countTextFragmentsConsumed > 0) {
101+
dst.append(",\n");
102+
dst.append("\t\"textFragmentsConsumed\": ").append(Integer.toString(countTextFragmentsConsumed));
133103
}
134104

135105
if(includeSurroundingBrackets) { dst.append("\n}"); }
@@ -142,7 +112,6 @@ public String toString() {
142112
}
143113

144114

145-
@Override
146115
public String toString(String srcName, boolean includeClassName) {
147116
var dst = new StringBuilder();
148117
if(includeClassName) {
@@ -152,40 +121,38 @@ public String toString(String srcName, boolean includeClassName) {
152121
dst.append("file: " + srcName);
153122
}
154123

155-
boolean first = true;
156-
for(ParserAction action : ParserAction.values()) {
157-
var data = this.actions.get(action);
158-
if(data != null) {
159-
if(!first || srcName != null) { dst.append(", "); }
160-
String name = action.name();
161-
dst.append("\"").append(name).append("\": ").append(data.toString());
162-
first = false;
163-
}
124+
if(countCompoundCharParserMatch > 0) {
125+
dst.append("compoundCharParserMatch: ").append(Integer.toString(countCompoundCharParserMatch));
126+
}
127+
if(countCompoundCharParserAcceptNext > 0) {
128+
dst.append(", ");
129+
dst.append("compoundCharParserAcceptNext: ").append(Integer.toString(countCompoundCharParserAcceptNext));
130+
}
131+
if(countCreateParser > 0) {
132+
dst.append(", ");
133+
dst.append("createParser: ").append(Integer.toString(countCreateParser));
164134
}
135+
if(countTextFragmentsConsumed > 0) {
136+
dst.append(", ");
137+
dst.append("textFragmentsConsumed: ").append(Integer.toString(countTextFragmentsConsumed));
138+
}
139+
165140
if(includeClassName) {
166141
dst.append("\n}");
167142
}
168143
return dst.toString();
169144
}
170145

171146

172-
private CountAndDurationLog getTypedAction(ParserAction action) {
173-
var data = actions.get(action);
174-
if(data == null) {
175-
data = new CountAndDurationLog();
176-
actions.put(action, data);
177-
}
178-
return data;
179-
}
180-
181-
182147
public static void toJsons(Map<String, ParserActionLogger> fileParserDetails, boolean includeSurroundingBrackets, Appendable dst, WriteSettings st) throws IOException {
183148
if(includeSurroundingBrackets) { dst.append("[\n"); }
149+
184150
JsonStringify.inst.joinConsume(fileParserDetails.entrySet(), ",\n", dst, (entry) -> {
185151
var stat = entry.getValue();
186152
String fileName = FileUtil.getFileNameWithoutExtension(entry.getKey());
187153
stat.toJson(fileName, includeSurroundingBrackets, dst, st);
188154
});
155+
189156
if(includeSurroundingBrackets) { dst.append("\n]"); }
190157
}
191158

0 commit comments

Comments
 (0)