Allow to set thread-local calendars and calendar prototype for RegularTimePeriod #171
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In JFreeChart 1.5.0,
RegularTimePeriod
subclasses create a new calendar instance every time they need one, which is during every construction, including vianext()
andprevious()
methods. In most setups, this creates a newGregorianCalendar
instance, which is very heavyweight (at least two arrays ofint
and one array ofboolean
, 17 elements each). For example, when creating and displaying a chart for 86400 seconds (one day's worth), this doubles memory consumption (200–250 MB instead of slightly above 100). The GC simply can't cope fast enough with this.Since the calendars are only used temporarily for time calculations (“pegging”) and then immediately discarded, it would make sense to use a single global instance. However, since
Calendar
is mutable, it would create concurrency problems with multi-threaded applications. It's not a problem for displaying a single chart with Swing, but could be a problem for an application that performs some kind of batch processing, producing a lot of charts for a lot of input files. Therefore, it makes sense to make those calendars thread-local.This PR introduces three methods:
RegularTimePeriod.setThreadLocalCalendarInstance()
—a public method that allows every thread to set a thread-local calendar for every futureRegularTimePeriod
creation (except with constructors that accept a time zone or a calendar explicitly).RegularTimePeriod.setCalendarInstancePrototype()
—a public method that allows to set a global prototype (as in the Prototype Pattern) instance that will be then cloned by every thread as needed and cached locally as if it was set withsetThreadLocalCalendarInstance()
.-
RegularTimePeriod.getCalendarInstance()
—a protected method that is now used by allRegularTimePeriod
subclasses whereCalendar.getInstance()
was used previously. If none of theset*()
methods are called, this method resorts to JFreeChart 1.5.0 behavior, spamming a new instance every time one is needed, which means users that don't call the newset*()
methods won't be affected in any way.Constructors accepting a
Calendar
explicitly were added as well. This lead to some code duplication between(..., TimeZone, Locale)
and the new(..., Calendar)
constructors. It can be fixed by either generifyingArgs.nullNotPermitted()
to return the first argument (much likeObjects.requireNonNull()
does), or by switching toObjects.requireNonNull()
(which would change the exception type fromIllegalArgumentException
toNullPointerException
). Please let me know if that's desirable, so I can add another commit to this PR.