ICU-13717 Adds "fast formatters" optimization to smpdtfmt.cpp to greatly improve the performance of SimpleDateFormat with the new number formatting pipeline.
X-SVN-Rev: 41438
This commit is contained in:
parent
3e2bbc9834
commit
4931366afe
@ -72,6 +72,7 @@
|
||||
#include "cstr.h"
|
||||
#include "dayperiodrules.h"
|
||||
#include "tznames_impl.h" // ZONE_NAME_U16_MAX
|
||||
#include "number_utypes.h"
|
||||
|
||||
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
|
||||
#include <stdio.h>
|
||||
@ -323,6 +324,7 @@ SimpleDateFormat::~SimpleDateFormat()
|
||||
if (fTimeZoneFormat) {
|
||||
delete fTimeZoneFormat;
|
||||
}
|
||||
freeFastNumberFormatters();
|
||||
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
delete fCapitalizationBrkIter;
|
||||
@ -608,6 +610,10 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
|
||||
}
|
||||
}
|
||||
|
||||
UErrorCode localStatus = U_ZERO_ERROR;
|
||||
freeFastNumberFormatters();
|
||||
initFastNumberFormatters(localStatus);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -857,7 +863,8 @@ SimpleDateFormat::initialize(const Locale& locale,
|
||||
fixNumberFormatForDates(*fNumberFormat);
|
||||
//fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberFormat to format/parse
|
||||
|
||||
initNumberFormatters(locale,status);
|
||||
initNumberFormatters(locale, status);
|
||||
initFastNumberFormatters(status);
|
||||
|
||||
}
|
||||
else if (U_SUCCESS(status))
|
||||
@ -1201,6 +1208,43 @@ _appendSymbolWithMonthPattern(UnicodeString& dst, int32_t value, const UnicodeSt
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static number::LocalizedNumberFormatter*
|
||||
createFastFormatter(const DecimalFormat* df, int32_t minInt, int32_t maxInt) {
|
||||
return new number::LocalizedNumberFormatter(
|
||||
df->toNumberFormatter()
|
||||
.integerWidth(number::IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt)));
|
||||
}
|
||||
|
||||
void SimpleDateFormat::initFastNumberFormatters(UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
auto* df = dynamic_cast<const DecimalFormat*>(fNumberFormat);
|
||||
if (df == nullptr) {
|
||||
return;
|
||||
}
|
||||
fFastNumberFormatters[SMPDTFMT_NF_1x10] = createFastFormatter(df, 1, 10);
|
||||
fFastNumberFormatters[SMPDTFMT_NF_2x10] = createFastFormatter(df, 2, 10);
|
||||
fFastNumberFormatters[SMPDTFMT_NF_3x10] = createFastFormatter(df, 3, 10);
|
||||
fFastNumberFormatters[SMPDTFMT_NF_4x10] = createFastFormatter(df, 4, 10);
|
||||
fFastNumberFormatters[SMPDTFMT_NF_2x2] = createFastFormatter(df, 2, 2);
|
||||
}
|
||||
|
||||
void SimpleDateFormat::freeFastNumberFormatters() {
|
||||
delete fFastNumberFormatters[SMPDTFMT_NF_1x10];
|
||||
delete fFastNumberFormatters[SMPDTFMT_NF_2x10];
|
||||
delete fFastNumberFormatters[SMPDTFMT_NF_3x10];
|
||||
delete fFastNumberFormatters[SMPDTFMT_NF_4x10];
|
||||
delete fFastNumberFormatters[SMPDTFMT_NF_2x2];
|
||||
fFastNumberFormatters[SMPDTFMT_NF_1x10] = nullptr;
|
||||
fFastNumberFormatters[SMPDTFMT_NF_2x10] = nullptr;
|
||||
fFastNumberFormatters[SMPDTFMT_NF_3x10] = nullptr;
|
||||
fFastNumberFormatters[SMPDTFMT_NF_4x10] = nullptr;
|
||||
fFastNumberFormatters[SMPDTFMT_NF_2x2] = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
@ -1945,6 +1989,11 @@ void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) {
|
||||
freeSharedNumberFormatters(fSharedNumberFormatters);
|
||||
fSharedNumberFormatters = NULL;
|
||||
}
|
||||
|
||||
// Also re-compute the fast formatters.
|
||||
UErrorCode localStatus = U_ZERO_ERROR;
|
||||
freeFastNumberFormatters();
|
||||
initFastNumberFormatters(localStatus);
|
||||
}
|
||||
|
||||
void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberFormat *formatToAdopt, UErrorCode &status){
|
||||
@ -2000,9 +2049,41 @@ SimpleDateFormat::zeroPaddingNumber(
|
||||
UnicodeString &appendTo,
|
||||
int32_t value, int32_t minDigits, int32_t maxDigits) const
|
||||
{
|
||||
if (currentNumberFormat!=NULL) {
|
||||
FieldPosition pos(FieldPosition::DONT_CARE);
|
||||
const number::LocalizedNumberFormatter* fastFormatter = nullptr;
|
||||
// NOTE: This uses the heuristic that these five min/max int settings account for the vast majority
|
||||
// of SimpleDateFormat number formatting cases at the time of writing (ICU 62).
|
||||
if (currentNumberFormat == fNumberFormat) {
|
||||
if (maxDigits == 10) {
|
||||
if (minDigits == 1) {
|
||||
fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_1x10];
|
||||
} else if (minDigits == 2) {
|
||||
fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_2x10];
|
||||
} else if (minDigits == 3) {
|
||||
fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_3x10];
|
||||
} else if (minDigits == 4) {
|
||||
fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_4x10];
|
||||
}
|
||||
} else if (maxDigits == 2) {
|
||||
if (minDigits == 2) {
|
||||
fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_2x2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fastFormatter != nullptr) {
|
||||
// Can use fast path
|
||||
number::impl::UFormattedNumberData result;
|
||||
result.quantity.setToInt(value);
|
||||
UErrorCode localStatus = U_ZERO_ERROR;
|
||||
fastFormatter->formatImpl(&result, localStatus);
|
||||
if (U_FAILURE(localStatus)) {
|
||||
return;
|
||||
}
|
||||
appendTo.append(result.string.toTempUnicodeString());
|
||||
|
||||
} else if (currentNumberFormat != nullptr) {
|
||||
// Fall back to slow path
|
||||
FieldPosition pos(FieldPosition::DONT_CARE);
|
||||
LocalPointer<NumberFormat> nf(dynamic_cast<NumberFormat*>(currentNumberFormat->clone()));
|
||||
nf->setMinimumIntegerDigits(minDigits);
|
||||
nf->setMaximumIntegerDigits(maxDigits);
|
||||
|
@ -50,6 +50,10 @@ class TimeZoneFormat;
|
||||
class SharedNumberFormat;
|
||||
class SimpleDateFormatMutableNFs;
|
||||
|
||||
namespace number {
|
||||
class LocalizedNumberFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SimpleDateFormat is a concrete class for formatting and parsing dates in a
|
||||
@ -1494,6 +1498,16 @@ private:
|
||||
*/
|
||||
int32_t skipUWhiteSpace(const UnicodeString& text, int32_t pos) const;
|
||||
|
||||
/**
|
||||
* Initialize LocalizedNumberFormatter instances used for speedup.
|
||||
*/
|
||||
void initFastNumberFormatters(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Delete the LocalizedNumberFormatter instances used for speedup.
|
||||
*/
|
||||
void freeFastNumberFormatters();
|
||||
|
||||
/**
|
||||
* Initialize NumberFormat instances used for numbering system overrides.
|
||||
*/
|
||||
@ -1610,6 +1624,20 @@ private:
|
||||
*/
|
||||
const SharedNumberFormat **fSharedNumberFormatters;
|
||||
|
||||
enum NumberFormatterKey {
|
||||
SMPDTFMT_NF_1x10,
|
||||
SMPDTFMT_NF_2x10,
|
||||
SMPDTFMT_NF_3x10,
|
||||
SMPDTFMT_NF_4x10,
|
||||
SMPDTFMT_NF_2x2,
|
||||
SMPDTFMT_NF_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Number formatters pre-allocated for fast performance on the most common integer lengths.
|
||||
*/
|
||||
const number::LocalizedNumberFormatter* fFastNumberFormatters[SMPDTFMT_NF_COUNT] = {};
|
||||
|
||||
UBool fHaveDefaultCentury;
|
||||
|
||||
BreakIterator* fCapitalizationBrkIter;
|
||||
|
Loading…
Reference in New Issue
Block a user