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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions