Skip to content

Commit df87667

Browse files
committed
Fixed performance issue #7854
1 parent a0ff6b9 commit df87667

File tree

3 files changed

+37
-8
lines changed

3 files changed

+37
-8
lines changed

src/common/TimeZoneUtil.cpp

+35-8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "../common/os/os_utils.h"
3737
#include "unicode/ucal.h"
3838

39+
#include <atomic>
40+
3941
using namespace Firebird;
4042

4143
namespace
@@ -45,8 +47,19 @@ namespace
4547
public:
4648
TimeZoneDesc(MemoryPool& pool)
4749
: asciiName(pool),
48-
unicodeName(pool)
50+
unicodeName(pool),
51+
calendar(nullptr)
52+
{
53+
}
54+
55+
~TimeZoneDesc()
4956
{
57+
UCalendar* val = calendar.exchange(nullptr);
58+
if (val)
59+
{
60+
auto& icuLib = Jrd::UnicodeUtil::getConversionICU();
61+
icuLib.ucalClose(val);
62+
}
5063
}
5164

5265
public:
@@ -70,9 +83,26 @@ namespace
7083
return unicodeName.begin();
7184
}
7285

86+
UCalendar* getCalendar(const Jrd::UnicodeUtil::ConversionICU& icuLib, UErrorCode* err) const
87+
{
88+
UCalendar* val = calendar.load();
89+
if (!val)
90+
{
91+
val = icuLib.ucalOpen(getUnicodeName(), -1, NULL, UCAL_GREGORIAN, err);
92+
if (!val)
93+
return val;
94+
95+
UCalendar* old = calendar.exchange(val);
96+
if (old)
97+
return old;
98+
}
99+
return icuLib.ucalClone(val, err);
100+
}
101+
73102
private:
74103
string asciiName;
75104
Array<UChar> unicodeName;
105+
mutable std::atomic<UCalendar*> calendar;
76106
};
77107
}
78108

@@ -593,8 +623,7 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
593623

594624
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
595625

596-
UCalendar* icuCalendar = icuLib.ucalOpen(
597-
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
626+
UCalendar* icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
598627

599628
if (!icuCalendar)
600629
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
@@ -702,8 +731,7 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
702731

703732
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
704733

705-
UCalendar* icuCalendar = icuLib.ucalOpen(
706-
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
734+
UCalendar* icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
707735

708736
if (!icuCalendar)
709737
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
@@ -771,8 +799,7 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
771799
#endif
772800
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
773801

774-
UCalendar* icuCalendar = icuLib.ucalOpen(
775-
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
802+
UCalendar* icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
776803

777804
if (!icuCalendar)
778805
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
@@ -1067,7 +1094,7 @@ TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& a
10671094
{
10681095
UErrorCode icuErrorCode = U_ZERO_ERROR;
10691096

1070-
icuCalendar = icuLib.ucalOpen(getDesc(id)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
1097+
icuCalendar = getDesc(id)->getCalendar(icuLib, &icuErrorCode);
10711098

10721099
if (!icuCalendar)
10731100
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");

src/common/unicode_util.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ class ImplementConversionICU : public UnicodeUtil::ConversionICU, BaseICU
446446
getEntryPoint("ucal_getTZDataVersion", inModule, ucalGetTZDataVersion);
447447
getEntryPoint("ucal_getDefaultTimeZone", inModule, ucalGetDefaultTimeZone);
448448
getEntryPoint("ucal_open", inModule, ucalOpen);
449+
getEntryPoint("ucal_clone", inModule, ucalClone);
449450
getEntryPoint("ucal_close", inModule, ucalClose);
450451
getEntryPoint("ucal_setAttribute", inModule, ucalSetAttribute);
451452
getEntryPoint("ucal_setMillis", inModule, ucalSetMillis);

src/common/unicode_util.h

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class UnicodeUtil
130130
int32_t (U_EXPORT2* ucalGetDefaultTimeZone) (UChar* result, int32_t resultCapacity, UErrorCode* ec);
131131
UCalendar* (U_EXPORT2* ucalOpen) (const UChar* zoneID, int32_t len, const char* locale, UCalendarType type,
132132
UErrorCode* err);
133+
UCalendar* (U_EXPORT2* ucalClone)(const UCalendar* cal, UErrorCode* status);
133134
void (U_EXPORT2* ucalClose) (UCalendar* cal);
134135
void (U_EXPORT2* ucalSetAttribute) (UCalendar* cal, UCalendarAttribute attr, int32_t newValue);
135136
void (U_EXPORT2* ucalSetMillis) (UCalendar* cal, UDate dateTime, UErrorCode* err);

0 commit comments

Comments
 (0)