Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed performance issue #7854 #7858

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Fixed performance issue #7854 #7858

wants to merge 1 commit into from

Conversation

hvlad
Copy link
Member

@hvlad hvlad commented Nov 20, 2023

No description provided.

@hvlad hvlad self-assigned this Nov 20, 2023
@aafemt
Copy link
Contributor

aafemt commented Nov 20, 2023

I wonder why all this atomic juggling instead of obtaining UCalendar in constructor? TimeZoneDesc itself is created on demand and four of five usages requires calendar.

UCalendar* val = calendar.load();
if (!val)
{
val = icuLib.ucalOpen(getUnicodeName(), -1, NULL, UCAL_GREGORIAN, err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd get icuLib here instead of receive by argument.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered it first, but then found that icuLib is already present at all points where getCalendar() is used.

if (old)
return old;
}
return icuLib.ucalClone(val, err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ucal_clone is not documented to be thread-safe, so it should not be assumed to be.
I do also not know its performance.
I'd instead implement a pool of unused objects where concurrent usage may do open/close additional copies and single usage would be reverted to the pool after its usage.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About performance, with patch I have following result:

TEST DURATION
TZ -> TS 44
TS -> TZ 70
TS -> TS 13
TZ -> TZ 13

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"However, you cannot use a reference to an open service object in two threads at the same time if either of them calls any non-const API."

ucal_clone is const, but ucal_setmillis is not.

In no place it says ucal_clone can be called concurrently with others non-const functions, so it's not safe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ucal_clone is const by itself thus it could be called with no sync.
ucal_setmillis is non-const but it uses own private instance of UCalendar, cloned from existing one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the full cite is:

However, you cannot use a reference to an open service object in two threads at the same time if either of them calls any non-const API. An individual open service object is not thread-safe for concurrent “writes”. Rather, for non-const use, you must use the clone function to create a copy of the service you want and then pass this copy to the second thread. This procedure allows you to use the same service in different threads, but avoids any thread synchronization or deadlock problems.

@hvlad
Copy link
Member Author

hvlad commented Nov 20, 2023

I wonder why all this atomic juggles instead of obtaining UCalendar in constructor? TimeZoneDesc itself is created on demand.

FIrst, all TimeZoneDesc's is created in TimeZoneStartup ctor.
Second, there are 637 items in timeZoneList currently, do you offer to create UCalendar for all of them ?
Last, define what is "juggles" and why you so afraid of it ?

BTW, even if TimeZoneDesc were created on demand, some synchronization would still be required.

@aafemt
Copy link
Contributor

aafemt commented Nov 20, 2023

FIrst, all TimeZoneDesc's is created in TimeZoneStartup ctor.

Oops, you are right, I misread getDesc(). Why they create time zones that are never going to be used?..

@hvlad
Copy link
Member Author

hvlad commented Nov 20, 2023

Why they create time zones that are never going to be used?..

Because it is cheap and simple and allows to avoid synchronization later.

@asfernandes
Copy link
Member

I used your implementation as base for alternative implementation and had better results:

Original:
TEST                 DURATION 
================ ============ 
TZ -> TS                  161 
TS -> TZ                  183 
TS -> TS                   12 
TZ -> TZ                   11 

This PR:
TEST                 DURATION 
================ ============ 
TZ -> TS                   36 
TS -> TZ                   56 
TS -> TS                   12 
TZ -> TZ                   11 

https://github.com/FirebirdSQL/firebird/pull/7859
TEST                 DURATION 
================ ============ 
TZ -> TS                   31 
TS -> TZ                   36 
TS -> TS                   11 
TZ -> TZ                   12 

@hvlad
Copy link
Member Author

hvlad commented Nov 20, 2023

I used your implementation as base for alternative implementation and had better results:

Afraid it will be not as good when run under contention: ucal_open() is much more costly than ucal_clone().
So far I didn't run mt-tests for it, though.

@asfernandes
Copy link
Member

I used your implementation as base for alternative implementation and had better results:

Afraid it will be not as good when run under contention: ucal_open() is much more costly than ucal_clone(). So far I didn't run mt-tests for it, though.

Calendar is maintained in use for small times. In the end, it could hurt only benchmarks probably.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants