On 7/9/20 5:12 AM, wjoe wrote:

Considering the many downsides why would I ever want to choose a static over a dynamic array ?


In addition to what others said, dynamic arrays can be more expensive both in space and time.

Time: Dynamic array elements are accessed through an extra pointer compared to static arrays. Depending on the usage pattern of the data, that extra indirection may be slower (e.g. due to the extra load on the CPU's cache).

Space: Every dynamic array is represented by the pair of one pointer (void*) one length (size_t) e.g. 2 * 8 = 16 bytes on a 64-bit system. Assuming the array is just 3 floats, which is a common type used for RGB, 3D coordinates, etc. (3 * 4 = 12 bytes), then those 16 bytes are more than the data itself.

I wrote the following program (as a fun morning exercise, before coffee :o) ) to display bytes used by different kinds of variables:

import std.stdio;
import std.range;
import std.algorithm;
import std.traits;

size_t bytesUsed(T)(T var) {
  static if (isDynamicArray!T) {
    enum dynamicArrayOverhead = (void[]).sizeof;
    // Double check:
    static assert (dynamicArrayOverhead == size_t.sizeof + (void*).sizeof);

return dynamicArrayOverhead + var.map!(element => bytesUsed(element)).sum;

  } else static if (isAssociativeArray!T) {
    static assert (false, "I don't know the implementation of AAs.");

  } else static if (is (T == struct)) {
    // BUG: Ignores alignment
    size_t total;
    foreach (member; var.tupleof) {
      total += bytesUsed(member);
    }
    return total;

  } else static if (is (T == class)) {
    // BUG: Ignores alignment
    size_t total;
    foreach (member; var.tupleof) {
      total += bytesUsed(member);
    }
    enum classOverhead = (void*).sizeof * 2;
    return classOverhead + total;

  } else {
    return var.sizeof;
  }

// BUG: union?
}

unittest {
  struct S {
    int[] arr;
    void* ptr;
  }
assert(bytesUsed(S([1, 2, 3])) == size_t.sizeof + (void*).sizeof + 3 * int.sizeof + 8);
}

void info(alias var)() {
writefln!"'%s' is %s and uses %s bytes."(var.stringof, typeof(var).stringof, bytesUsed(var));
}

void main() {
  // This is an efficient data structure:
  alias Color = float[3]; // red, green, blue
  alias DayColors = Color[7];

  // Comparing it to the dynamic array equivalent:
  DayColors a;
  auto b = makeDayColors();
  info!a;
  info!b;
}

float[] makeColor() {
  // Syntax confusion alert: Return type is *not* a static array. :/
  return new float[3];
}

float[][] makeDayColors() {
  float[][] result = new float[][7];
  foreach (ref e; result) {
    e = makeColor();
  }
  return result;
}

Ali

Reply via email to