Skip to content

Commit

Permalink
[Backport] 8333396: Use StringBuilder internally for java.text.Format…
Browse files Browse the repository at this point in the history
….* formatting

Summary: java.text.Format.* use StringBuffer internally, but StringBuffer's bad performance character become obvious after obsoleting biased locking. So use StringBuilder if possible in java.text.Formating.*.

Testing: All java.text.format jtreg.

Reviewers: D-D-H, Yude Lin

Issue: #83
  • Loading branch information
lingjun-cg authored Jul 23, 2024
1 parent 3798df7 commit 102db0f
Show file tree
Hide file tree
Showing 14 changed files with 682 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -54,7 +54,7 @@ class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
}

public void formatted(Format.Field attr, Object value, int start, int end,
StringBuffer buffer) {
Format.StringBuf buffer) {
if (start != end) {
if (start < size) {
// Adjust attributes of existing runs
Expand Down Expand Up @@ -93,7 +93,7 @@ public void formatted(Format.Field attr, Object value, int start, int end,
}

public void formatted(int fieldID, Format.Field attr, Object value,
int start, int end, StringBuffer buffer) {
int start, int end, Format.StringBuf buffer) {
formatted(attr, value, start, end, buffer);
}

Expand Down
14 changes: 13 additions & 1 deletion src/java.base/share/classes/java/text/ChoiceFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,13 @@ public Object[] getFormats() {
*/
public StringBuffer format(long number, StringBuffer toAppendTo,
FieldPosition status) {
return format((double)number, toAppendTo, status);
return format((double) number, StringBufFactory.of(toAppendTo), status).asStringBuffer();
}

@Override
StringBuf format(long number, StringBuf toAppendTo,
FieldPosition status) {
return format((double) number, toAppendTo, status);
}

/**
Expand All @@ -397,6 +403,12 @@ public StringBuffer format(long number, StringBuffer toAppendTo,
*/
public StringBuffer format(double number, StringBuffer toAppendTo,
FieldPosition status) {
return format(number, StringBufFactory.of(toAppendTo), status).asStringBuffer();
}

@Override
StringBuf format(double number, StringBuf toAppendTo,
FieldPosition status) {
// find the number
int i;
for (i = 0; i < choiceLimits.length; ++i) {
Expand Down
77 changes: 62 additions & 15 deletions src/java.base/share/classes/java/text/CompactNumberFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,35 @@ public final StringBuffer format(Object number,
&& ((BigInteger) number).bitLength() < 64)) {
return format(((Number) number).longValue(), toAppendTo,
fieldPosition);
} else if (number instanceof BigDecimal) {
return format((BigDecimal) number, StringBufFactory.of(toAppendTo), fieldPosition).asStringBuffer();
} else if (number instanceof BigInteger) {
return format((BigInteger) number, StringBufFactory.of(toAppendTo), fieldPosition).asStringBuffer();
} else if (number instanceof Number) {
return format(((Number) number).doubleValue(), toAppendTo, fieldPosition);
} else {
throw new IllegalArgumentException("Cannot format "
+ number.getClass().getName() + " as a number");
}
}

@Override
StringBuf format(Object number,
StringBuf toAppendTo,
FieldPosition fieldPosition) {

if (number == null) {
throw new IllegalArgumentException("Cannot format null as a number");
}

if (number instanceof Long || number instanceof Integer
|| number instanceof Short || number instanceof Byte
|| number instanceof AtomicInteger
|| number instanceof AtomicLong
|| (number instanceof BigInteger
&& ((BigInteger) number).bitLength() < 64)) {
return format(((Number) number).longValue(), toAppendTo,
fieldPosition);
} else if (number instanceof BigDecimal) {
return format((BigDecimal) number, toAppendTo, fieldPosition);
} else if (number instanceof BigInteger) {
Expand All @@ -529,7 +558,7 @@ public final StringBuffer format(Object number,
return format(((Number) number).doubleValue(), toAppendTo, fieldPosition);
} else {
throw new IllegalArgumentException("Cannot format "
+ number.getClass().getName() + " as a number");
+ number.getClass().getName() + " as a number");
}
}

Expand Down Expand Up @@ -560,12 +589,21 @@ public final StringBuffer format(Object number,
public StringBuffer format(double number, StringBuffer result,
FieldPosition fieldPosition) {

fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, StringBufFactory.of(result), fieldPosition.getFieldDelegate()).asStringBuffer();
}

@Override
StringBuf format(double number, StringBuf result,
FieldPosition fieldPosition) {

fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate());
}

private StringBuffer format(double number, StringBuffer result,
private StringBuf format(double number, StringBuf result,
FieldDelegate delegate) {

boolean nanOrInfinity = decimalFormat.handleNaN(number, result, delegate);
Expand Down Expand Up @@ -650,12 +688,21 @@ false, getMaximumIntegerDigits(), getMinimumIntegerDigits(),
public StringBuffer format(long number, StringBuffer result,
FieldPosition fieldPosition) {

fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, StringBufFactory.of(result), fieldPosition.getFieldDelegate()).asStringBuffer();
}

@Override
StringBuf format(long number, StringBuf result,
FieldPosition fieldPosition) {

fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate());
}

private StringBuffer format(long number, StringBuffer result, FieldDelegate delegate) {
private StringBuf format(long number, StringBuf result, FieldDelegate delegate) {
boolean isNegative = (number < 0);
if (isNegative) {
number = -number;
Expand Down Expand Up @@ -726,23 +773,23 @@ isNegative, false, getMaximumIntegerDigits(),
* of the prefix and the suffix fields can be
* obtained using {@link NumberFormat.Field#PREFIX}
* and {@link NumberFormat.Field#SUFFIX} respectively.
* @return the {@code StringBuffer} passed in as {@code result}
* @return the {@code StringBuf} passed in as {@code result}
* @throws ArithmeticException if rounding is needed with rounding
* mode being set to {@code RoundingMode.UNNECESSARY}
* @throws NullPointerException if any of the given parameter
* is {@code null}
* @see FieldPosition
*/
private StringBuffer format(BigDecimal number, StringBuffer result,
FieldPosition fieldPosition) {
private StringBuf format(BigDecimal number, StringBuf result,
FieldPosition fieldPosition) {

Objects.requireNonNull(number);
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate());
}

private StringBuffer format(BigDecimal number, StringBuffer result,
private StringBuf format(BigDecimal number, StringBuf result,
FieldDelegate delegate) {

boolean isNegative = number.signum() == -1;
Expand Down Expand Up @@ -812,23 +859,23 @@ false, getMaximumIntegerDigits(), getMinimumIntegerDigits(),
* prefix and the suffix fields can be obtained
* using {@link NumberFormat.Field#PREFIX} and
* {@link NumberFormat.Field#SUFFIX} respectively.
* @return the {@code StringBuffer} passed in as {@code result}
* @return the {@code StringBuf} passed in as {@code result}
* @throws ArithmeticException if rounding is needed with rounding
* mode being set to {@code RoundingMode.UNNECESSARY}
* @throws NullPointerException if any of the given parameter
* is {@code null}
* @see FieldPosition
*/
private StringBuffer format(BigInteger number, StringBuffer result,
FieldPosition fieldPosition) {
private StringBuf format(BigInteger number, StringBuf result,
FieldPosition fieldPosition) {

Objects.requireNonNull(number);
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate(), false);
}

private StringBuffer format(BigInteger number, StringBuffer result,
private StringBuf format(BigInteger number, StringBuf result,
FieldDelegate delegate, boolean formatLong) {

boolean isNegative = number.signum() == -1;
Expand Down Expand Up @@ -905,7 +952,7 @@ private String getAffix(boolean isExpanded, boolean isPrefix, boolean isNegative
* {@code NumberFormat.Field.SIGN} and
* {@code NumberFormat.Field.PREFIX} fields
*/
private void appendPrefix(StringBuffer result, String prefix,
private void appendPrefix(StringBuf result, String prefix,
FieldDelegate delegate) {
append(result, expandAffix(prefix), delegate,
getFieldPositions(prefix, NumberFormat.Field.PREFIX));
Expand All @@ -921,7 +968,7 @@ private void appendPrefix(StringBuffer result, String prefix,
* {@code NumberFormat.Field.SIGN} and
* {@code NumberFormat.Field.SUFFIX} fields
*/
private void appendSuffix(StringBuffer result, String suffix,
private void appendSuffix(StringBuf result, String suffix,
FieldDelegate delegate) {
append(result, expandAffix(suffix), delegate,
getFieldPositions(suffix, NumberFormat.Field.SUFFIX));
Expand All @@ -937,7 +984,7 @@ private void appendSuffix(StringBuffer result, String suffix,
* @param positions a list of {@code FieldPosition} in the given
* string
*/
private void append(StringBuffer result, String string,
private void append(StringBuf result, String string,
FieldDelegate delegate, List<FieldPosition> positions) {
if (!string.isEmpty()) {
int start = result.length();
Expand Down Expand Up @@ -1103,7 +1150,7 @@ private int selectCompactPattern(BigInteger number) {
public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
CharacterIteratorFieldDelegate delegate
= new CharacterIteratorFieldDelegate();
StringBuffer sb = new StringBuffer();
StringBuf sb = StringBufFactory.of();

if (obj instanceof Double || obj instanceof Float) {
format(((Number) obj).doubleValue(), sb, delegate);
Expand Down
28 changes: 26 additions & 2 deletions src/java.base/share/classes/java/text/DateFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,19 @@ else if (obj instanceof Number)
throw new IllegalArgumentException("Cannot format given Object as a Date");
}

@Override
final StringBuf format(Object obj, StringBuf toAppendTo,
FieldPosition fieldPosition) {
if (obj instanceof Date) {
return format((Date) obj, toAppendTo, fieldPosition);
} else if (obj instanceof Number) {
return format(new Date(((Number) obj).longValue()),
toAppendTo, fieldPosition);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Date");
}
}

/**
* Formats a {@link Date} into a date-time string. The formatted
* string is appended to the given {@code StringBuffer}.
Expand All @@ -367,6 +380,11 @@ else if (obj instanceof Number)
public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition);

StringBuf format(Date date, StringBuf toAppendTo,
FieldPosition fieldPosition) {
throw new UnsupportedOperationException("Subclasses should override this method");
}

/**
* Formats a {@link Date} into a date-time string.
*
Expand All @@ -375,8 +393,14 @@ public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
*/
public final String format(Date date)
{
return format(date, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString();
if ("java.text".equals(getClass().getPackageName())
&& "java.text".equals(numberFormat.getClass().getPackageName())) {
return format(date, StringBufFactory.of(),
DontCareFieldPosition.INSTANCE).toString();
} else {
return format(date, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString();
}
}

/**
Expand Down
Loading

0 comments on commit 102db0f

Please sign in to comment.