Using large NTuples makes Julia hang

I’m not as patient as you, so I reduced the size to 1536 and did my experiments. My version for NTuple

using BenchmarkTools

# string2ntuple(::Val{N}, s::String) where {N} = ntuple(i -> i <= ncodeunits(s) ? codeunit(s, i) : 0x0, Val(N))
string2ntuple(::Val{N}, s::String) where {N} = ntuple(i -> i <= ncodeunits(s) ? codeunit(s, i) : 0x0, N)

struct Foo{NT, NC} 
    id:: UInt64
    tag::NTuple{NT, UInt8}
    start_comment::NTuple{NC, UInt8}
    end_comment::NTuple{NC, UInt8}
    function Foo{NT, NC}(id, tag, start_comment, end_comment) where {NT, NC} 
        new{NT, NC}(
            id, 
            string2ntuple(Val(NT), tag),
            string2ntuple(Val(NC), start_comment),
            string2ntuple(Val(NC), end_comment))
    end
end

function test()
    dataset = @btime Vector{Foo{32, 1536}}(undef, 1);

    dataset[1] = @btime Foo{32, 1536}(
        0, "test_tag", "start_comment", "end_comment"
    ); 

    data = @btime Foo{32, 1536}[]

    @btime push!(data, Foo{32, 1536}(
        0, "test_tag", "start_comment", "end_comment"
    )) setup=(data = Foo{32, 1536}[]); 

    data = @btime Foo{32, 1536}(
        0, "test_tag", "start_comment", "end_comment"
    ); 

    dataset = @time Foo{32, 1536}[data]
    dataset = @btime Foo{32, 1536}[$data]
    nothing
end

yields

  77.636 ns (1 allocation: 3.19 KiB)
  69.100 μs (8 allocations: 30.77 KiB)
  24.349 ns (1 allocation: 64 bytes)
  69.900 μs (9 allocations: 55.14 KiB)
  69.100 μs (8 allocations: 30.77 KiB)
 56.395801 seconds (4.64 k allocations: 263.561 KiB, 100.00% compilation time) # critical compilation time
  317.031 ns (1 allocation: 3.19 KiB)

and for StaticVector

using StaticArrays, BenchmarkTools

string2svec(::Val{N}, s::String) where {N} = SVector{N, UInt8}(ntuple(i -> i <= ncodeunits(s) ? codeunit(s, i) : 0x0, N))

struct Foo{NT, NC} 
    id:: UInt64
    tag::StaticVector{NT, UInt8}
    start_comment::StaticVector{NC, UInt8}
    end_comment::StaticVector{NC, UInt8}
    function Foo{NT, NC}(id, tag, start_comment, end_comment) where {NT, NC} 
        new{NT, NC}(
            id, 
            string2svec(Val(NT), tag),
            string2svec(Val(NC), start_comment),
            string2svec(Val(NC), end_comment))
    end
end

function test()
    dataset = @btime Vector{Foo{32, 1536}}(undef, 1);

    dataset[1] = @btime Foo{32, 1536}(
        0, "test_tag", "start_comment", "end_comment"
    ); 

    data = @btime Foo{32, 1536}[]

    @btime push!(data, Foo{32, 1536}(
        0, "test_tag", "start_comment", "end_comment"
    )) setup=(data = Foo{32, 1536}[]); 

    data = @btime Foo{32, 1536}(
        0, "test_tag", "start_comment", "end_comment"
    ); 

    dataset = @time Foo{32, 1536}[data]
    dataset = @btime Foo{32, 1536}[$data]
    nothing
end

yielding

  25.201 ns (1 allocation: 96 bytes)
  69.300 μs (11 allocations: 34.00 KiB)
  24.900 ns (1 allocation: 64 bytes)
  69.300 μs (12 allocations: 34.27 KiB)
  69.200 μs (11 allocations: 34.00 KiB)
  0.007673 seconds (4.64 k allocations: 260.451 KiB, 99.27% compilation time) # critical compilation time
  28.945 ns (1 allocation: 96 bytes)

This surprises me, so I’m assuming I’m going wrong somewhere?

Edit: this is on Julia Version 1.9.0-DEV.167