Memory performance improvements

This commit is contained in:
serso
2016-01-25 10:34:12 +01:00
parent 9d4365cc79
commit f05d050b6c
14 changed files with 170 additions and 131 deletions

View File

@@ -1,6 +1,16 @@
package jscl.math;
import jscl.JsclMathEngine;
import org.solovyev.common.Converter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.function.Constant;
import jscl.math.function.Fraction;
import jscl.math.function.Inverse;
@@ -8,14 +18,12 @@ import jscl.math.numeric.Real;
import jscl.math.polynomial.Polynomial;
import jscl.math.polynomial.UnivariatePolynomial;
import jscl.mathml.MathML;
import jscl.text.*;
import jscl.text.ExpressionParser;
import jscl.text.ParseException;
import jscl.text.Parser;
import jscl.text.ParserUtils;
import jscl.text.msg.Messages;
import jscl.util.ArrayUtils;
import org.solovyev.common.Converter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public class Expression extends Generic {
@@ -113,15 +121,13 @@ public class Expression extends Generic {
}
public static Expression valueOf(@Nonnull String expression) throws ParseException {
final MutableInt position = new MutableInt(0);
final Parser.Parameters p = Parser.Parameters.newInstance(expression, position, JsclMathEngine.getInstance());
final Parser.Parameters p = Parser.Parameters.get(expression);
final Generic generic = ExpressionParser.parser.parse(p, null);
ParserUtils.skipWhitespaces(p);
int index = position.intValue();
int index = p.position.intValue();
if (index < expression.length()) {
throw new ParseException(index, expression, Messages.msg_1, index + 1);
}

View File

@@ -1,10 +1,10 @@
package jscl.text;
import jscl.math.Generic;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.Generic;
public class CompoundIdentifier implements Parser<String> {
public static final Parser<String> parser = new CompoundIdentifier();
@@ -16,12 +16,13 @@ public class CompoundIdentifier implements Parser<String> {
public String parse(@Nonnull Parameters p, @Nullable Generic previousSumElement) throws ParseException {
int pos0 = p.position.intValue();
StringBuilder result = new StringBuilder();
final StringBuilder result;
ParserUtils.skipWhitespaces(p);
try {
String s = Identifier.parser.parse(p, previousSumElement);
result.append(s);
final String identifier = Identifier.parser.parse(p, previousSumElement);
result = new StringBuilder();
result.append(identifier);
} catch (ParseException e) {
p.position.setValue(pos0);
throw e;

View File

@@ -1,11 +1,14 @@
package jscl.text;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.NumeralBase;
import jscl.math.Generic;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static jscl.text.ParserUtils.makeParseException;
import static jscl.text.ParserUtils.skipWhitespaces;
public class Digits implements Parser<String> {
@@ -20,15 +23,15 @@ public class Digits implements Parser<String> {
public String parse(@Nonnull Parameters p, @Nullable Generic previousSumElement) throws ParseException {
int pos0 = p.position.intValue();
final StringBuilder result = new StringBuilder();
ParserUtils.skipWhitespaces(p);
skipWhitespaces(p);
final StringBuilder result;
if (p.position.intValue() < p.expression.length() && nb.getAcceptableCharacters().contains(p.expression.charAt(p.position.intValue()))) {
result = new StringBuilder(2);
result.append(p.expression.charAt(p.position.intValue()));
p.position.increment();
} else {
ParserUtils.throwParseException(p, pos0, Messages.msg_9);
throw makeParseException(p, pos0, Messages.msg_9);
}
while (p.position.intValue() < p.expression.length() && nb.getAcceptableCharacters().contains(p.expression.charAt(p.position.intValue()))) {

View File

@@ -1,18 +1,19 @@
package jscl.text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.NumeralBase;
import jscl.math.Generic;
import jscl.math.NumericWrapper;
import jscl.math.numeric.Real;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class DoubleParser implements Parser<NumericWrapper> {
public static final Parser<NumericWrapper> parser = new DoubleParser();
@@ -69,7 +70,6 @@ class FloatingPointLiteral implements Parser<Double> {
final NumeralBase nb = NumeralBaseParser.parser.parse(p, previousSumElement);
final StringBuilder result = new StringBuilder();
boolean digits = false;
boolean point = false;
@@ -77,6 +77,7 @@ class FloatingPointLiteral implements Parser<Double> {
final Digits digitsParser = new Digits(nb);
final StringBuilder result = new StringBuilder();
try {
result.append(digitsParser.parse(p, previousSumElement));
digits = true;
@@ -167,16 +168,15 @@ class ExponentPart implements Parser<String> {
public String parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
int pos0 = p.position.intValue();
final StringBuilder result = new StringBuilder();
ParserUtils.skipWhitespaces(p);
final StringBuilder result;
if (p.position.intValue() < p.expression.length() && (p.expression.charAt(p.position.intValue()) == 'e' || p.expression.charAt(p.position.intValue()) == 'E')) {
char c = p.expression.charAt(p.position.intValue());
result = new StringBuilder();
result.append(p.expression.charAt(p.position.intValue()));
p.position.increment();
result.append(c);
} else {
ParserUtils.throwParseException(p, pos0, Messages.msg_10, 'e', 'E');
throw ParserUtils.makeParseException(p, pos0, Messages.msg_10, 'e', 'E');
}
try {
@@ -201,10 +201,10 @@ class SignedInteger implements Parser<String> {
public String parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
final int pos0 = p.position.intValue();
final StringBuilder result = new StringBuilder();
ParserUtils.skipWhitespaces(p);
final StringBuilder result = new StringBuilder();
final int pos1 = p.position.intValue();
if (pos1 < p.expression.length() && (p.expression.charAt(pos1) == '+' || MinusParser.isMinus(p.expression.charAt(pos1)))) {
final char c = p.expression.charAt(pos1);

View File

@@ -1,14 +1,17 @@
package jscl.text;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ExceptionsPool {
private static final int MAX_COUNT = 20;
@Nonnull
private final List<ParseException> list = new ArrayList<>();
@@ -30,6 +33,9 @@ public class ExceptionsPool {
}
public void release(@Nonnull ParseException e) {
if (list.size() >= MAX_COUNT) {
return;
}
list.add(e);
}
}

View File

@@ -1,12 +1,13 @@
package jscl.text;
import jscl.math.Generic;
import jscl.text.msg.Messages;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
import jscl.math.Generic;
import jscl.text.msg.Messages;
public class Identifier implements Parser<String> {
@@ -30,15 +31,16 @@ public class Identifier implements Parser<String> {
public String parse(@Nonnull Parameters p, @Nullable Generic previousSumElement) throws ParseException {
int pos0 = p.position.intValue();
final StringBuilder result = new StringBuilder();
ParserUtils.skipWhitespaces(p);
final StringBuilder result;
if (p.position.intValue() < p.expression.length() && isValidFirstCharacter(p.expression.charAt(p.position.intValue()))) {
result = new StringBuilder();
result.append(p.expression.charAt(p.position.intValue()));
p.position.increment();
} else {
ParserUtils.throwParseException(p, pos0, Messages.msg_5);
throw ParserUtils.makeParseException(p, pos0, Messages.msg_5);
}
while (p.position.intValue() < p.expression.length() && isValidNotFirstCharacter(p.expression, p.position)) {

View File

@@ -1,13 +1,14 @@
package jscl.text;
import java.util.Collections;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.NumeralBase;
import jscl.math.Generic;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
public class IntegerParser implements Parser<Integer> {
public static final Parser<Integer> parser = new IntegerParser();
@@ -18,32 +19,14 @@ public class IntegerParser implements Parser<Integer> {
public Integer parse(@Nonnull Parameters p, @Nullable Generic previousSumElement) throws ParseException {
int pos0 = p.position.intValue();
/*int n;
ParserUtils.skipWhitespaces(expression, position);
if (position.intValue() < expression.length() && Character.isDigit(expression.charAt(position.intValue()))) {
char c = expression.charAt(position.intValue());
position.increment();
n = c - '0';
} else {
position.setValue(pos0);
throw new ParseException();
}
while (position.intValue() < expression.length() && Character.isDigit(expression.charAt(position.intValue()))) {
char c = expression.charAt(position.intValue());
position.increment();
n = 10 * n + (c - '0');
}*/
final NumeralBase nb = NumeralBaseParser.parser.parse(p, previousSumElement);
final StringBuilder result = new StringBuilder();
ParserUtils.skipWhitespaces(p);
final StringBuilder result;
if (p.position.intValue() < p.expression.length() && nb.getAcceptableCharacters().contains(p.expression.charAt(p.position.intValue()))) {
char c = p.expression.charAt(p.position.intValue());
p.position.increment();
result = new StringBuilder();
result.append(c);
} else {
p.position.setValue(pos0);

View File

@@ -1,14 +1,15 @@
package jscl.text;
import java.util.Collections;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.NumeralBase;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
public class JsclIntegerParser implements Parser<JsclInteger> {
public static final Parser<JsclInteger> parser = new JsclIntegerParser();
@@ -21,16 +22,14 @@ public class JsclIntegerParser implements Parser<JsclInteger> {
final NumeralBase nb = NumeralBaseParser.parser.parse(p, previousSumElement);
final StringBuilder result = new StringBuilder();
final String number;
try {
result.append(new Digits(nb).parse(p, previousSumElement));
number = new Digits(nb).parse(p, previousSumElement);
} catch (ParseException e) {
p.position.setValue(pos0);
throw e;
}
final String number = result.toString();
try {
return nb.toJsclInteger(number);
} catch (NumberFormatException e) {

View File

@@ -1,12 +1,14 @@
package jscl.text;
import jscl.MathContext;
import jscl.math.Generic;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import jscl.JsclMathEngine;
import jscl.MathContext;
import jscl.math.Generic;
/**
* Main parser interface.
@@ -28,10 +30,18 @@ public interface Parser<T> {
class Parameters {
@Nonnull
public final String expression;
private static final ThreadLocal<Parameters> instance = new ThreadLocal<Parameters>() {
@Override
protected Parameters initialValue() {
return new Parameters("", JsclMathEngine.getInstance());
}
};
@Nonnull
public final MutableInt position;
public String expression;
@Nonnull
public final MutableInt position = new MutableInt(0);
@Nonnull
public final List<ParseException> exceptions = new ArrayList<ParseException>();
@@ -44,18 +54,24 @@ public interface Parser<T> {
/**
* @param expression expression to be parsed
* @param position current position of expression. Side effect: if parsing is successful this parameter should be increased on the number of parsed letters (incl whitespaces etc)
* @param context math engine to be used in parsing
*/
Parameters(@Nonnull String expression, @Nonnull MutableInt position, @Nonnull MathContext context) {
Parameters(@Nonnull String expression, @Nonnull MathContext context) {
this.expression = expression;
this.position = position;
this.context = context;
}
@Nonnull
public static Parameters newInstance(@Nonnull String expression, @Nonnull MutableInt position, @Nonnull final MathContext mathEngine) {
return new Parameters(expression, position, mathEngine);
public static Parameters get(@Nonnull String expression) {
final Parameters parameters = instance.get();
parameters.expression = expression;
parameters.reset();
return parameters;
}
public void reset() {
position.setValue(0);
exceptions.clear();
}
public void addException(@Nonnull ParseException e) {

View File

@@ -1,11 +1,13 @@
package jscl.text;
import jscl.math.Generic;
import jscl.text.msg.Messages;
import java.lang.reflect.Array;
import java.util.Collections;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Array;
import jscl.math.Generic;
import jscl.text.msg.Messages;
/**
* User: serso
@@ -62,14 +64,43 @@ public class ParserUtils {
}
}
public static void throwParseException(@Nonnull Parser.Parameters p,
int pos0,
@Nonnull String messageId) throws ParseException {
throw makeParseException(p, pos0, messageId);
}
@Nonnull
public static ParseException makeParseException(@Nonnull Parser.Parameters p, int pos0, @Nonnull String messageId) {
final MutableInt position = p.position;
final ParseException parseException = p.exceptionsPool.obtain(position.intValue(), p.expression, messageId, Collections.emptyList());
position.setValue(pos0);
return parseException;
}
public static void throwParseException(@Nonnull Parser.Parameters p,
int pos0,
@Nonnull String messageId,
@Nonnull Object parameter) throws ParseException {
final MutableInt position = p.position;
final ParseException parseException = p.exceptionsPool.obtain(position.intValue(), p.expression, messageId, Collections.singletonList(parameter));
position.setValue(pos0);
throw parseException;
}
public static void throwParseException(@Nonnull Parser.Parameters p,
int pos0,
@Nonnull String messageId,
Object... parameters) throws ParseException {
throw makeParseException(p, pos0, messageId, parameters);
}
@Nonnull
public static ParseException makeParseException(@Nonnull Parser.Parameters p, int pos0, @Nonnull String messageId, Object... parameters) {
final MutableInt position = p.position;
final ParseException parseException = p.exceptionsPool.obtain(position.intValue(), p.expression, messageId, parameters);
position.setValue(pos0);
throw parseException;
return parseException;
}

View File

@@ -1,17 +1,17 @@
package jscl.text;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.Generic;
import jscl.math.function.PostfixFunctionsRegistry;
import jscl.math.operator.Operator;
import jscl.math.operator.TripleFactorial;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* User: serso
* Date: 10/31/11
@@ -26,13 +26,14 @@ public class PostfixFunctionsParser implements Parser<Generic> {
this.content = content;
}
private static Generic parsePostfix(@Nonnull List<PostfixFunctionParser> parsers,
private static Generic parsePostfix(@Nonnull List<String> names,
Generic content,
@Nullable final Generic previousSumElement,
@Nonnull final Parameters p) throws ParseException {
Generic result = content;
for (PostfixFunctionParser parser : parsers) {
for (String name : names) {
final PostfixFunctionParser parser = new PostfixFunctionParser(name);
final PostfixFunctionParser.Result postfixResult = parser.parse(p, previousSumElement);
if (postfixResult.isPostfixFunction()) {
final Operator postfixFunction;
@@ -51,7 +52,7 @@ public class PostfixFunctionsParser implements Parser<Generic> {
}
}
result = parsePostfix(parsers, postfixFunction.expressionValue(), previousSumElement, p);
result = parsePostfix(names, postfixFunction.expressionValue(), previousSumElement, p);
}
}
@@ -59,15 +60,6 @@ public class PostfixFunctionsParser implements Parser<Generic> {
}
public Generic parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
final List<String> postfixFunctionNames = PostfixFunctionsRegistry.getInstance().getNames();
final List<PostfixFunctionParser> parsers = new ArrayList<PostfixFunctionParser>(postfixFunctionNames.size());
parsers.add(new PostfixFunctionParser(TripleFactorial.NAME));
for (String postfixFunctionName : postfixFunctionNames) {
parsers.add(new PostfixFunctionParser(postfixFunctionName));
}
return parsePostfix(parsers, content, previousSumElement, p);
return parsePostfix(PostfixFunctionsRegistry.getInstance().getNames(), content, previousSumElement, p);
}
}