Skip to content

Commit d859753

Browse files
authored
Merge pull request #220 from metafacture/207-optimizePerformanceBottlenecks
Optimize performance bottlenecks in `Value.Hash` and `RecordTransformer`.
2 parents 46fb034 + 85db657 commit d859753

File tree

3 files changed

+198
-59
lines changed

3 files changed

+198
-59
lines changed

metafix/src/main/java/org/metafacture/metafix/Fix.xtext

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ Expression:
1616
;
1717

1818
Unless:
19-
'unless' name = QualifiedName '(' ( params += (QualifiedName|STRING) ( ',' params += (QualifiedName|STRING) )* )? ')'
19+
'unless' name = QualifiedName '(' ( params += (QualifiedName|STRING) ( ',' params += (QualifiedName|STRING) )* ','? )? ( options = Options )? ')'
2020
elements += Expression*
2121
'end'
2222
;
2323

2424
If:
25-
'if' name = QualifiedName '(' ( params += (QualifiedName|STRING) ( ',' params += (QualifiedName|STRING) )* )? ')'
25+
'if' name = QualifiedName '(' ( params += (QualifiedName|STRING) ( ',' params += (QualifiedName|STRING) )* ','? )? ( options = Options )? ')'
2626
elements += Expression*
2727
elseIf = ElsIf?
2828
else = Else?
2929
'end'
3030
;
3131

3232
ElsIf:
33-
'elsif' name = QualifiedName '(' ( params += (QualifiedName|STRING) ( ',' params += (QualifiedName|STRING) )* )? ')'
33+
'elsif' name = QualifiedName '(' ( params += (QualifiedName|STRING) ( ',' params += (QualifiedName|STRING) )* ','? )? ( options = Options )? ')'
3434
elements += Expression*
3535
;
3636

metafix/src/main/java/org/metafacture/metafix/RecordTransformer.java

Lines changed: 118 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.metafacture.metafix.fix.Fix;
2929
import org.metafacture.metafix.fix.If;
3030
import org.metafacture.metafix.fix.MethodCall;
31-
import org.metafacture.metafix.fix.Options;
3231
import org.metafacture.metafix.fix.Unless;
3332

3433
import org.eclipse.emf.ecore.EObject;
@@ -38,14 +37,14 @@
3837
import org.slf4j.Logger;
3938
import org.slf4j.LoggerFactory;
4039

40+
import java.util.ArrayList;
4141
import java.util.LinkedHashMap;
4242
import java.util.LinkedList;
4343
import java.util.List;
4444
import java.util.Map;
4545
import java.util.function.Consumer;
4646
import java.util.function.Function;
4747
import java.util.function.Supplier;
48-
import java.util.stream.Collectors;
4948

5049
/**
5150
* Transform a record using a {@link Fix}.
@@ -72,17 +71,20 @@ private RecordTransformer(final Metafix metafix, final List<Expression> expressi
7271
vars = metafix.getVars();
7372

7473
expressions.forEach(e -> {
74+
final Params params = new Params(e.getParams(), vars);
75+
final Options options = new Options(e.getOptions(), vars);
76+
7577
if (e instanceof Do) {
76-
processDo((Do) e);
78+
processDo((Do) e, params, options);
7779
}
7880
else if (e instanceof If) {
79-
processIf((If) e);
81+
processIf((If) e, params, options);
8082
}
8183
else if (e instanceof Unless) {
82-
processUnless((Unless) e);
84+
processUnless((Unless) e, params, options);
8385
}
8486
else if (e instanceof MethodCall) {
85-
processFunction((MethodCall) e);
87+
processFunction((MethodCall) e, params, options);
8688
}
8789
else {
8890
throw new FixProcessException(executionExceptionMessage(e));
@@ -100,16 +102,16 @@ public void transform(final Record record) {
100102
});
101103
}
102104

103-
private void processDo(final Do expression) {
105+
private void processDo(final Do expression, final Params params, final Options options) {
104106
processFix(() -> executionExceptionMessage(expression), () -> {
105107
final FixContext context = getInstance(expression.getName(), FixContext.class, FixBind::valueOf);
106108
final RecordTransformer recordTransformer = new RecordTransformer(metafix, expression.getElements());
107109

108-
return record -> context.execute(metafix, record, params(expression.getParams()), options(expression.getOptions()), recordTransformer);
110+
return record -> context.execute(metafix, record, params.resolve(), options.resolve(), recordTransformer);
109111
});
110112
}
111113

112-
private void processIf(final If ifExpression) {
114+
private void processIf(final If ifExpression, final Params ifParams, final Options ifOptions) {
113115
final ElsIf elseIfExpression = ifExpression.getElseIf();
114116
final Else elseExpression = ifExpression.getElse();
115117

@@ -118,21 +120,37 @@ private void processIf(final If ifExpression) {
118120

119121
processFix(() -> executionExceptionMessage(ifExpression, ifExpression.eResource()), () -> {
120122
final FixPredicate ifPredicate = getInstance(ifExpression.getName(), FixPredicate.class, FixConditional::valueOf);
121-
final FixPredicate elseIfPredicate = elseIfExpression != null ? getInstance(elseIfExpression.getName(), FixPredicate.class, FixConditional::valueOf) : null;
122-
123123
final RecordTransformer ifTransformer = new RecordTransformer(metafix, ifExpression.getElements());
124-
final RecordTransformer elseIfTransformer = elseIfExpression != null ? new RecordTransformer(metafix, elseIfExpression.getElements()) : null;
124+
125+
final FixPredicate elseIfPredicate;
126+
final Params elseIfParams;
127+
final Options elseIfOptions;
128+
final RecordTransformer elseIfTransformer;
129+
130+
if (elseIfExpression != null) {
131+
elseIfPredicate = getInstance(elseIfExpression.getName(), FixPredicate.class, FixConditional::valueOf);
132+
elseIfParams = new Params(elseIfExpression.getParams(), vars);
133+
elseIfOptions = new Options(elseIfExpression.getOptions(), vars);
134+
elseIfTransformer = new RecordTransformer(metafix, elseIfExpression.getElements());
135+
}
136+
else {
137+
elseIfPredicate = null;
138+
elseIfParams = null;
139+
elseIfOptions = null;
140+
elseIfTransformer = null;
141+
}
142+
125143
final RecordTransformer elseTransformer = elseExpression != null ? new RecordTransformer(metafix, elseExpression.getElements()) : null;
126144

127145
return record -> {
128-
if (ifPredicate.test(metafix, record, params(ifExpression.getParams()), options(null))) { // TODO: options
146+
if (ifPredicate.test(metafix, record, ifParams.resolve(), ifOptions.resolve())) {
129147
ifTransformer.transform(record);
130148
}
131149
else {
132150
if (elseIfExpression != null) {
133151
currentMessageSupplier = elseIfMessageSupplier;
134152

135-
if (elseIfPredicate.test(metafix, record, params(elseIfExpression.getParams()), options(null))) { // TODO: options
153+
if (elseIfPredicate.test(metafix, record, elseIfParams.resolve(), elseIfOptions.resolve())) {
136154
elseIfTransformer.transform(record);
137155
return;
138156
}
@@ -147,23 +165,23 @@ private void processIf(final If ifExpression) {
147165
});
148166
}
149167

150-
private void processUnless(final Unless expression) {
168+
private void processUnless(final Unless expression, final Params params, final Options options) {
151169
processFix(() -> executionExceptionMessage(expression, expression.eResource()), () -> {
152170
final FixPredicate predicate = getInstance(expression.getName(), FixPredicate.class, FixConditional::valueOf);
153171
final RecordTransformer recordTransformer = new RecordTransformer(metafix, expression.getElements());
154172

155173
return record -> {
156-
if (!predicate.test(metafix, record, params(expression.getParams()), options(null))) { // TODO: options
174+
if (!predicate.test(metafix, record, params.resolve(), options.resolve())) {
157175
recordTransformer.transform(record);
158176
}
159177
};
160178
});
161179
}
162180

163-
private void processFunction(final MethodCall expression) {
181+
private void processFunction(final MethodCall expression, final Params params, final Options options) {
164182
processFix(() -> executionExceptionMessage(expression), () -> {
165183
final FixFunction function = getInstance(expression.getName(), FixFunction.class, FixMethod::valueOf);
166-
return record -> function.apply(metafix, record, params(expression.getParams()), options(expression.getOptions()));
184+
return record -> function.apply(metafix, record, params.resolve(), options.resolve());
167185
});
168186
}
169187

@@ -219,27 +237,97 @@ private String executionExceptionMessage(final EObject object, final Resource re
219237
resource.getURI(), node.getStartLine(), NodeModelUtils.getTokenText(node));
220238
}
221239

222-
private String resolveVars(final String value) {
223-
return value == null ? null : StringUtil.format(value, Metafix.VAR_START, Metafix.VAR_END, false, vars);
240+
private abstract static class AbstractResolvable<T> {
241+
242+
protected boolean isResolvable(final String value) {
243+
return value != null && value.contains(Metafix.VAR_START);
244+
}
245+
246+
protected String resolveVars(final String value, final Map<String, String> vars) {
247+
return value == null ? null : StringUtil.format(value, Metafix.VAR_START, Metafix.VAR_END, false, vars);
248+
}
249+
250+
protected abstract T resolve();
251+
224252
}
225253

226-
private List<String> params(final List<String> params) {
227-
return params.stream().map(this::resolveVars).collect(Collectors.toList());
254+
private static class Params extends AbstractResolvable<List<String>> {
255+
256+
private final List<String> list;
257+
private final Map<String, String> vars;
258+
private final boolean resolve;
259+
260+
private Params(final List<String> list, final Map<String, String> vars) {
261+
this.list = list;
262+
this.vars = vars;
263+
264+
resolve = list.stream().anyMatch(this::isResolvable);
265+
}
266+
267+
@Override
268+
protected List<String> resolve() {
269+
if (resolve) {
270+
final List<String> resolvedList = new ArrayList<>(list.size());
271+
272+
for (final String entry : list) {
273+
resolvedList.add(resolveVars(entry, vars));
274+
}
275+
276+
return resolvedList;
277+
}
278+
else {
279+
return list;
280+
}
281+
}
282+
228283
}
229284

230-
private Map<String, String> options(final Options options) {
231-
final Map<String, String> map = new LinkedHashMap<>();
285+
private static class Options extends AbstractResolvable<Map<String, String>> {
286+
287+
private final Map<String, String> map = new LinkedHashMap<>();
288+
private final Map<String, String> vars;
289+
private final boolean resolve;
232290

233-
if (options != null) {
234-
final List<String> keys = options.getKeys();
235-
final List<String> values = options.getValues();
291+
private Options(final org.metafacture.metafix.fix.Options options, final Map<String, String> vars) {
292+
this.vars = vars;
236293

237-
for (int i = 0; i < keys.size(); i += 1) {
238-
map.put(resolveVars(keys.get(i)), resolveVars(values.get(i)));
294+
boolean resolveTemp = false;
295+
296+
if (options != null) {
297+
final List<String> keys = options.getKeys();
298+
final List<String> values = options.getValues();
299+
300+
for (int i = 0; i < keys.size(); ++i) {
301+
final String key = keys.get(i);
302+
final String value = values.get(i);
303+
304+
map.put(key, value);
305+
306+
if (!resolveTemp && (isResolvable(key) || isResolvable(value))) {
307+
resolveTemp = true;
308+
}
309+
}
310+
}
311+
312+
resolve = resolveTemp;
313+
}
314+
315+
@Override
316+
protected Map<String, String> resolve() {
317+
if (resolve) {
318+
final Map<String, String> resolvedMap = new LinkedHashMap<>(map.size());
319+
320+
for (final Map.Entry<String, String> entry : map.entrySet()) {
321+
resolvedMap.put(resolveVars(entry.getKey(), vars), resolveVars(entry.getValue(), vars));
322+
}
323+
324+
return resolvedMap;
325+
}
326+
else {
327+
return map;
239328
}
240329
}
241330

242-
return map;
243331
}
244332

245333
}

0 commit comments

Comments
 (0)