Extra line reduces run time by half, but why?

From Advent of Code Day 7, so be warned for spoilers.

I created my solution and found weird behaviors where running other functions/lines made the rest of my code run far faster, but wasn’t sure why. After a very tedious process of clearing the REPL, reloading functions and testing (using @btime), I distilled the issue to a single line that causes my code to become much faster. On my computer, it jumps from ~450 μs to ~200 μs with the additional line. Please see below for code, with the extra line indicated. Can anyone explain what is happening behind the scenes to produce this? I’ve tried running the function without the extra lines many times, and it does not speed up, so this goes beyond my understanding of compilation requirements. Thanks.

Edit: I’ve been investigating further and it looks like the type stability of ‘splitters’ changes, from:

  • splitters::Union{Vector{Any}, Vector{Vector{Int64}}} without to the extra line, to:
  • splitters::Vector{Vector{Int64}} with it

But I still don’t understand why it would be different between the versions?

function day7()
    [findall('^',x) for x in ["^"]] # Honestly no idea why but this makes my code twice as fast
    data =  readlines("Data\\Day7.txt")
    splitters = [findall('^',x) for x in data]
    part1 = 0
    beam_mem = zeros(Int,length(data[1]))
    beams = [x == 'S' for x in data[1]]
    beam_mem[beams] .+= 1
    for level in splitters
        isempty(level) && continue
        for i in level
            if beams[i]
                beams[i-1] = true
                beams[i+1] = true
                beams[i] = false
                beam_mem[i-1] += beam_mem[i]
                beam_mem[i+1] += beam_mem[i]
                beam_mem[i] = 0
                part1 += 1
            end
        end
    end
    return part1,sum(beam_mem)
end

I ran it on my computer and found no difference in speed. It turns out to be 68.600 μs (133 allocations: 4.89 KiB); after commenting out the first line, it is 68.100 μs (124 allocations: 4.61 KiB).

Assuming the contents of your Day7.txt file are

.......S.......
...............
.......^.......
...............
......^.^......
...............
.....^.^.^.....
...............
....^.^...^....
...............
...^.^...^.^...
...............
..^...^.....^..
...............
.^.^.^.^.^...^.
...............

Regardless of whether the first line is commented out, my splitters correctly infer the type as Vector{Vector{Int64}}.

I suggest you check whether there has been a mistake somewhere, because code execution time doesn’t suddenly decrease.

I also do not see a time difference - and in both cases, splitters is correctly inferred. Can you reproduce it in a new REPL?

I’ve tried testing this with alternative Julia versions, and it appears this is no longer occurring as of Julia v1.12. I’ve tried going back and forth between v1.11.7 and v1.12.2 and been able to consistently replicate the type instability with 1.11.

I’ve still found the original behavior to be confusing, but for now I’m taking the fix as ‘use the latest version’.

Thanks