Skip to content

timotaularson/SeparateCompilationSamples

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This is a work-in-progress test of separate native compilation of Julia packages.
It is currently Linux-only, but small improvements should let it run on other systems.
There are still some issues to resolve before this will fully work.

--

Purpose:

Compile and cache native code for packages to allow near-instant loading.
This creates a shared library paired with the current "ji" precompile file for each package,
to be recreated with the same lifecycle as the "ji" precompile file with no extra user
interaction required.

Design:

When a specialization of a function is compiled in Julia usually 2 native functions are created
either in memory (JIT) or in a shared library. The first function does the main work and can have
one of several special optimized calling conventions. The second function is a convenience wrapper
which provides one standard calling convention with which to call the main work function.

For the system image this branch causes the native functions to be exported and and their native
code names to be retained in the system image meta data so they can be linked against.

For a package the native functions are compiled as exported functions into a shared library
and their names are preserved in the "ji" precompile file so when it is loaded the shared library
can be loaded as well and the native functions linked back into the package meta data, allowing
native re-compilation to be skipped except when source code for the package has been modified.

Often a package A is used by a package B where types are needed from B to be able to compile
specialized functions from A. This raises the question of where to store the native code for
such function specializations. This also arises if some functions in package A are not native
compiled but B causes them to be native compiled. A solution is to store them in the shared
library for package B, and keep changes synchronized between packages by the same dependency
change logic which is used to keep the "ji" precompile files up-to-date. If two or more packages
cause compilation of the same specializations of functions from packages they use they will
generate the same code so the related native functions can be linked at will from any package's
shared library without conflict.

--

Remaining known issues:

Miscompiling extra wrapper code into the special calling signature function when compiling
packages (as opposed to how it works correctly in a manual script sample below.)

Native functions need to be made unique between packages
(possibly adding a package hash slug to their names.)

--

Demonstration of what works and what does not yet:

# Build the https://github.com/timotaularson/julia/tree/SeparateCompilation branch of Julia.

# From the directory containing this Demo code
# run the julia executable built from the above branch.
# Note that the last step (calling the DemoPkg.test1 function) is expected to fail currently.
julia> include("DemoScript.jl")
julia> using Pkg
julia> Pkg.activate("DemoPkg")
julia> using DemoPkg
julia> DemoPkg.test1(Int64(1))

# Disassemble the resulting shared libraries and compare the native code.
# The demo script compiles correctly:
$ objdump --disassemble test.so > ScriptDisassembly.txt
# The demo package compiles incorrectly, with extra code wrapping the julia_test1_* function.
$ objdump --disassemble ~/.julia/compiled/v1.6/DemoPkg/*.so > PkgDisassembly.txt

Disassembly of the resulting samples are included, so you don't have to do the steps
below to see the result and possibly help :)

# I would appreciate any clues toward solving this.


About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages