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

Make TimeZones.jl relocatable #479

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

lcontento
Copy link

@lcontento lcontento commented Oct 29, 2024

Fixes #467

Half of a possible solution to #467. The other half is at JuliaTime/TZJData.jl#32.

As discussed in the issue, there are many possible ways to fix this. I have tested that this approach works when including TimeZones.jl in a system image and relocating the depot. I think it should also be 100% equivalent to the old code in a normal setup. I cannot exclude that there are other relocatability issues hidden away, but even if this will not be the long term solution to the problem I think it is a decent fix for most people's use-cases.

to ensure relocatability
@omus
Copy link
Member

omus commented Oct 30, 2024

Would be good to re-run and post the benchmarks from #457 around importing to see if this has an impact on load time.

src/TimeZones.jl Outdated

# TimeZone types used to disambiguate the context of a DateTime
# abstract type UTC <: TimeZone end # Already defined in the Dates stdlib
abstract type Local <: TimeZone end

function __init__()
# Must be set at runtime to ensure relocatability
_COMPILED_DIR[] = TZJData.artifact_dir()
Copy link
Member

@omus omus Oct 30, 2024

Choose a reason for hiding this comment

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

An option for backwards compat:

Suggested change
_COMPILED_DIR[] = TZJData.artifact_dir()
# Backwards compatibility with TZJData v1.3.0 and below. Using older versions means TimeZones.jl is not relocatable
_COMPILED_DIR[] = isdefined(TZJData, :artifact_dir) ? TZJData.artifact_dir() : TZJData.ARTIFACT_DIR

Copy link
Author

Choose a reason for hiding this comment

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

If we want to ensure backwards compatibility then relocatability can only be enforced by adding a lower bound to the TZJData version. I would see adding a lower bound to the version of TimeZones as a more natural way to do it, since that's the package I expect people usually add to their Project.toml.
Unless there is sometimes the need for keeping old versions of TZJData pinned, in which case backwards compatibility becomes really necessary. I don't know the package well enough to say if that's the case.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think most downstream users are depending on TimeZones.jl, not TZJData.jl.

Is there a pressing need for TimeZones.jl to support old versions of TZJData.jl? If so, could we just backport JuliaTime/TZJData.jl#32 to older versions of TZJData.jl?

Copy link
Member

Choose a reason for hiding this comment

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

Part of the reason for the TimeZones.jl and TZJData.jl package separation is to allow for changing tzdata independently from the TimeZones.jl code. Setting a lower bound to TZJData.jl means we can't use those old versions. That's not the end of the world but the suggestion I had allows for relocatability and compatibility.

Backporting JuliaTime/TZJData.jl#32 is possible but we would still need to update the compat in TimeZones.jl to allow for each of those patch releases.

Copy link
Author

Choose a reason for hiding this comment

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

If older versions of TZJData are needed then I guess we should go for backward compatibility. If relocatability is backported to the older versions of TZJData we can later remove the fallback. Similarly, if at any point the non-relocatable versions of TZJData become so old that no one would be expected to use them in new code, then a [compat] bound can be added to exclude them so that the fallback can be removed.

In the meanwhile, I think we could check whether TZJData.ARTIFACT_DIR actually exists and if not print an error message suggesting adding a [compat] bound for TZJData to ensure relocatability.

Copy link
Author

Choose a reason for hiding this comment

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

I have added a fallback for older versions by hardcoding the artifact hashes and querying them using TZDATA_VERSION. This is not very elegant but 1) there is no 100% foolproof solution to retrieve the hash AFAIK 2) there are not too many versions. In this way we can ensure relocatability even with the old TZJDatas.

Copy link
Member

Choose a reason for hiding this comment

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

Do you care about relocatability for old TZJData versions? I'm fine with using ARTIFACT_DIR as the fallback. I'd rather break relocatability for old versions than break compat support unnecessarily (if that is a problem).

Copy link
Author

Choose a reason for hiding this comment

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

I think the current fallback works with all old versions of TZJData, so there is no need to change the [compat] bounds.

Copy link
Author

Choose a reason for hiding this comment

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

I have tested it for the last released version of TZJData on a system image and it works, even without the relocatability PR for TZJData.

@lcontento
Copy link
Author

lcontento commented Oct 30, 2024

Would be good to re-run and post the benchmarks from #457 around importing to see if this has an impact on load time.

I tried the benchmarks. The first time I run them after precompiling the packages they are quite slower, but on subsequent runs (after restarting the REPL) they are faster and consistent. This is for all three cases reported below, not sure why (maybe the artifact is redownloaded or rechecked every time the packages is recompiled?). I have reported only the timings for the runs >= 2nd (if you want to see the ones for the 1st run let me know): they all seem comparable and within the error I observe by running multiple times.

Before this PR:

julia> @time_imports import TimeZones
      0.5 ms  Scratch
      3.7 ms  InlineStrings
      0.2 ms  TZJData
      0.4 ms  Compat
      0.2 ms  Compat  CompatLinearAlgebraExt
      0.3 ms  ExprTools
      1.1 ms  Mocking
               ┌ 0.7 ms TimeZones.TZData.__init__() 
               ├ 0.0 ms TimeZones.__init__() 
     31.1 ms  TimeZones 36.28% compilation time

julia> using BenchmarkTools, TimeZones

julia> @btime istimezone("Europe/Warsaw");
  72.906 ns (1 allocation: 48 bytes)

This PR (with vanilla TZJData.jl)

julia> @time_imports import TimeZones
      0.4 ms  Scratch
      3.7 ms  InlineStrings
      0.3 ms  TZJData
      0.4 ms  Compat
      0.2 ms  Compat  CompatLinearAlgebraExt
      0.3 ms  ExprTools
      1.0 ms  Mocking
               ┌ 0.5 ms TimeZones.TZData.__init__() 
               ├ 0.1 ms TimeZones.__init__() 
     30.3 ms  TimeZones 33.97% compilation time

julia> using BenchmarkTools, TimeZones

julia> @btime istimezone("Europe/Warsaw");

  77.583 ns (1 allocation: 48 bytes)

This PR (with relocatable TZJData.jl)

julia> @time_imports import TimeZones
      0.4 ms  Scratch
      3.8 ms  InlineStrings
      1.0 ms  TZJData
      0.5 ms  Compat
      0.2 ms  Compat  CompatLinearAlgebraExt
      0.3 ms  ExprTools
      1.1 ms  Mocking
               ┌ 0.7 ms TimeZones.TZData.__init__() 
               ├ 0.1 ms TimeZones.__init__() 
     30.5 ms  TimeZones 36.08% compilation time

julia> using BenchmarkTools, TimeZones

julia> @btime istimezone("Europe/Warsaw");
  74.769 ns (1 allocation: 48 bytes)

Copy link

codecov bot commented Nov 4, 2024

Codecov Report

Attention: Patch coverage is 41.66667% with 7 lines in your changes missing coverage. Please review.

Project coverage is 91.64%. Comparing base (2bc8f50) to head (0402582).
Report is 18 commits behind head on master.

Files with missing lines Patch % Lines
src/TimeZones.jl 41.66% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #479      +/-   ##
==========================================
- Coverage   92.79%   91.64%   -1.16%     
==========================================
  Files          39       38       -1     
  Lines        1818     1843      +25     
==========================================
+ Hits         1687     1689       +2     
- Misses        131      154      +23     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@lcontento lcontento requested a review from omus November 4, 2024 17:14
@@ -4,6 +4,7 @@ authors = ["Curtis Vogt <[email protected]>"]
version = "1.19.0"

[deps]
Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
Copy link
Member

Choose a reason for hiding this comment

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

Need to update the docs/Manifest.toml

Copy link
Author

Choose a reason for hiding this comment

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

Do you really need a Manifest there? I will try to remove it just to see if it works.

Otherwise I am a bit unsure how to edit it since the entry for TimeZones is at a previous version, so if I added the Artifacts dependency there it would be weird. I am not very familiar with the process for building the documentation in Julia, so I am not sure where exactly the error occurs.

Copy link
Author

Choose a reason for hiding this comment

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

It works without a Manifest there. It seems reasonable to me but again I am not familiar with Documenter.

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.

Relocatability no longer given due to link to TZJData.ARTIFACT_DIR and storing path in const string reference
3 participants