Struct of Arrays (SoA)

Structs of Arrays is a way of rearranging the layout of the data fields of a struct. Specifically, Structs of Arrays (SoA) is a data layout separating elements of a record into one parallel array per field. Take the following example:

// this is just a normal struct, no SOA
Vec3 :: struct {
  x: float;
  y: float;
  z: float;
}

// this is a SOA Vec3 struct
SOA_Vec3 :: struct {
  x: [100] float;
  y: [100] float;
  z: [100] float;
}

Using a combination of #insert directives, metaprogramming, and generating code at compile time, we can generalize the concept of SOA to any structs using the following:

Vec3 :: struct {
  x: float;
  y: float;
  z: float;
}

Person :: struct {
  age: int;
  is_cool: bool;
}

SOA :: struct(T: Type, count: int) {
  #insert -> string {
    t_info := type_info(T);
    builder: String_Builder;  
    defer free_buffers(*builder);
    for fields: t_info.members {
      print_to_builder(*builder, "  %1: [%2] type_of(T.%1);\n", fields.name, count);
    }
    result := builder_to_string(*builder);
    return result;
  }
}

// create an soa_vec3
soa_vec: SOA(Vec3, 10);
for i: 0..soa_vec.count-1 {
  print("soa_vec.x[i]=%, soa_vec.y[i]=%, soa_vec.z[i]=%\n", soa_vec.x[i], soa_vec.y[i], soa_vec.z[i]);
}

// create an soa_person
soa_person: SOA(Person, 10);
for i: 0..soa_person.count-1 {
  print("soa_person.age[i]=%, soa_person.is_cool[i]=%\n", soa_person.age[i], soa_person.is_cool[i]);
}