Skip to content

Reduce load time #192

@MilesCranmer

Description

@MilesCranmer

Here's a breakdown of load time contributors (1.11.6)

File Incremental Time (ms)
internal_utils.jl 0.0 (baseline)
fixed_rational.jl 3.7
write_once_read_many.jl 0.2
types.jl 2.1
utils.jl 14.1
math.jl 2.1
arrays.jl 12.9
units.jl 4.2
constants.jl 0.7
uparse.jl 1.8
symbolic_dimensions.jl 5.8
affine_dimensions.jl 0.0
complex.jl 0.4
register_units.jl 1.4
disambiguities.jl 0.9
deprecated.jl 0.8

Measured by progressively uncommenting one include at a time.

So clearly there are some issues with utils.jl and arrays.jl that are blowing up the import time. And also the linear algebra extension which is about 30ms by itself.

Code:

First, comment out all exports and unit imports and the precompilation include. Also comment out the entirety of the LA extension.

Then, run:

#!/usr/bin/env julia

using Statistics
using Printf

# All 16 files in order
ALL_FILES = [
    "internal_utils.jl",
    "fixed_rational.jl",
    "write_once_read_many.jl",
    "types.jl",
    "utils.jl",
    "math.jl",
    "arrays.jl",
    "units.jl",
    "constants.jl",
    "uparse.jl",
    "symbolic_dimensions.jl",
    "affine_dimensions.jl",
    "complex.jl",
    "register_units.jl",
    "disambiguities.jl",
    "deprecated.jl"
]

function modify_src_file(n_files_to_include)
    """Modify src/DynamicQuantities.jl to include only the first n_files_to_include files"""
    src_file = "src/DynamicQuantities.jl"
    content = read(src_file, String)
    
    # Process each file
    for (idx, file) in enumerate(ALL_FILES)
        if idx <= n_files_to_include
            # Uncomment this file
            content = replace(content, "    # include(\"$file\")" => "    include(\"$file\")")
        else
            # Comment this file
            content = replace(content, "    include(\"$file\")" => "    # include(\"$file\")")
        end
    end
    
    write(src_file, content)
end

function run_timing_test(n_trials=40)
    """Run julia import test n_trials+1 times (first is for precompilation)"""
    times = Float64[]
    
    # First run for precompilation
    run(`julia --project=. --startup-file=no -e "@time using DynamicQuantities"`, wait=true)
    
    # Collect n_trials measurements
    for i in 1:n_trials
        output = read(`julia --project=. --startup-file=no -e "@time using DynamicQuantities"`, String)
        # Parse the time from @time output
        m = match(r"([\d.]+)\s+seconds", output)
        if m !== nothing
            push!(times, parse(Float64, m[1]))
        end
    end
    
    return times
end

function main()
    # Save original state
    println("Saving original src/DynamicQuantities.jl state...")
    original_content = read("src/DynamicQuantities.jl", String)
    
    # Output file
    output_file = "import_times_quartiles_auto.txt"
    
    open(output_file, "w") do io
        println(io, "Progressive Import Time Analysis - Quartiles (40 measurements each)")
        println(io, "=====================================================================")
        println(io, "")
        println(io, "Files Included                                  Q25 (ms)    Q75 (ms)")
        println(io, "--------------------------------------------------------------------")
        
        for n_files in 1:16
            # Determine configuration name
            if n_files == 1
                config_name = "1. internal_utils.jl only"
            elseif n_files == 16
                config_name = "16. + deprecated.jl (ALL FILES)"
            else
                config_name = "$(n_files). + $(ALL_FILES[n_files])"
            end
            
            print("Testing $config_name...")
            flush(stdout)
            
            # Modify the source file
            modify_src_file(n_files)
            
            # Run timing tests
            times = run_timing_test(40)
            
            if length(times) >= 40
                # Calculate quartiles
                sort!(times)
                q25 = times[10]  # 25th percentile of 40 values
                q75 = times[30]  # 75th percentile of 40 values
                
                # Write to file
                config_str = rpad(config_name, 48)
                q25_str = @sprintf("%.1f", q25 * 1000)
                q75_str = @sprintf("%.1f", q75 * 1000)
                println(io, "$config_str $q25_str        $q75_str")
                
                println(" Q25: $(round(q25*1000, digits=1))ms, Q75: $(round(q75*1000, digits=1))ms")
            else
                println(" FAILED - only got $(length(times)) measurements")
            end
        end
    end
    
    # Restore original file
    println("\nRestoring original src/DynamicQuantities.jl...")
    write("src/DynamicQuantities.jl", original_content)
    
    println("\nResults saved to: $output_file")
end

# Run the script
main()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions