Есть следующий кусок кода на Crystal
GMULT_AES = [0x00, 0x00, 0x00, 0x00, ...]
puts GMULT_AES[12000]
Элементов в массиве 65535.
При компиляции с флагом --release
сильно возрастает потребление памяти и время компиляции.
При компиляции был получен такой кусок LLVM IR
define internal void @"~GMULT_AES:init"() {
alloca:
%__temp_386 = alloca i32*
%capacity = alloca i32
%ary = alloca %"Array(Int32)"*
br label %entry
entry: ; preds = %alloca
store i32 65536, i32* %capacity
%0 = load i32, i32* %capacity
%1 = call %"Array(Int32)"* @"*Array(Int32)@Array(T)::new<Int32>:Array(Int32)"(i32 596, i32 %0)
store %"Array(Int32)"* %1, %"Array(Int32)"** %ary
%2 = load %"Array(Int32)"*, %"Array(Int32)"** %ary
%3 = load %"Array(Int32)"*, %"Array(Int32)"** %ary
%4 = getelementptr inbounds %"Array(Int32)", %"Array(Int32)"* %3, i32 0, i32 3
%5 = load i32*, i32** %4
store i32* %5, i32** %__temp_386
%6 = load i32*, i32** %__temp_386
%7 = call i32 @"*Pointer(Int32)@Pointer(T)#[]=<Int32, Int32>:Int32"(i32* %6, i32 0, i32 0)
%8 = load i32*, i32** %__temp_386
%9 = call i32 @"*Pointer(Int32)@Pointer(T)#[]=<Int32, Int32>:Int32"(i32* %8, i32 1, i32 0)
%10 = load i32*, i32** %__temp_386
%11 = call i32 @"*Pointer(Int32)@Pointer(T)#[]=<Int32, Int32>:Int32"(i32* %10, i32 2, i32 0)
%12 = load i32*, i32** %__temp_386
%13 = call i32 @"*Pointer(Int32)@Pointer(T)#[]=<Int32, Int32>:Int32"(i32* %12, i32 3, i32 0)
%14 = load i32*, i32** %__temp_386
Аллокаций тут вроде не так много, но зато много строк с load
/call
, которые вызываются на каждый элемент массива
Из-за чего так происходит?
Как более правильно должен создаваться массив с большим кол-ом элементов, чтобы это не сказывалось на скорости компиляции?
P.S. Аналогичную проблему нашёл и в баг-трекере Rust-а https://github.com/rust-lang/rust/issues/49330