Skip to main content
added 186 characters in body
Source Link
xander
  • 141
  • 2

You can reduce the memory footprint by using BitVector32 instead of bool. A bool in .NET occupies a full word in memory. A BitVector32 allows you to store the equivalent of 32 bools the same memory space.

By replacing all of the bool fields in State with a single BitVector32, I was able to reduce State's memory footprint from 68 bytes to 12 (as measured by Marshal.SizeOf<State>()). Since State is the key in the dictionary, that adds up to a decent reduction in memory usage overall.

After applying my changes to your master branch and running for 1,000,000 steps, the memory usage of the state dictionary dropped from ~215 MB to ~167 MB (as measured by the Visual Studio profiler). After 5,000,000 steps, it dropped from ~864 MB to ~671 MB.

You could push this technique even further by packing numeric values into bit vectors. There are some examples of doing so in the docs.

Here's a sample of the code that I used. All of the changes happened within State. I opted for the most convenient refactoring path... there might be a more efficient/performant way to code all this.

BitVector32 bits;

private const int ReinforcedIndexFingerMask = 1 << 0;
private const int CarpalTunnelPreventionCreamMask = 1 << 1;

public bool ReinforcedIndexFinger
{
    get => bits[ReinforcedIndexFingerMask];
    set => bits[ReinforcedIndexFingerMask] = value;
}

public bool CarpalTunnelPreventionCream
{
    get => bits[CarpalTunnelPreventionCreamMask];
    set => bits[CarpalTunnelPreventionCreamMask] = value;
}
```

As an added bonus, I think you could simplify the GetHashCode() and Equals() implementations by comparing the bit vector directly, rather than comparing every value individually.

You can reduce the memory footprint by using BitVector32 instead of bool. A bool in .NET occupies a full word in memory. A BitVector32 allows you to store the equivalent of 32 bools the same memory space.

By replacing all of the bool fields in State with a single BitVector32, I was able to reduce State's memory footprint from 68 bytes to 12 (as measured by Marshal.SizeOf<State>()). Since State is the key in the dictionary, that adds up to a decent reduction in memory usage overall.

After applying my changes to your master branch and running for 1,000,000 steps, the memory usage of the state dictionary dropped from ~215 MB to ~167 MB (as measured by the Visual Studio profiler). After 5,000,000 steps, it dropped from ~864 MB to ~671 MB.

You could push this technique even further by packing numeric values into bit vectors. There are some examples of doing so in the docs.

Here's a sample of the code that I used. All of the changes happened within State. I opted for the most convenient refactoring path... there might be a more efficient/performant way to code all this.

BitVector32 bits;

private const int ReinforcedIndexFingerMask = 1 << 0;
private const int CarpalTunnelPreventionCreamMask = 1 << 1;

public bool ReinforcedIndexFinger
{
    get => bits[ReinforcedIndexFingerMask];
    set => bits[ReinforcedIndexFingerMask] = value;
}

public bool CarpalTunnelPreventionCream
{
    get => bits[CarpalTunnelPreventionCreamMask];
    set => bits[CarpalTunnelPreventionCreamMask] = value;
}
```

You can reduce the memory footprint by using BitVector32 instead of bool. A bool in .NET occupies a full word in memory. A BitVector32 allows you to store the equivalent of 32 bools the same memory space.

By replacing all of the bool fields in State with a single BitVector32, I was able to reduce State's memory footprint from 68 bytes to 12 (as measured by Marshal.SizeOf<State>()). Since State is the key in the dictionary, that adds up to a decent reduction in memory usage overall.

After applying my changes to your master branch and running for 1,000,000 steps, the memory usage of the state dictionary dropped from ~215 MB to ~167 MB (as measured by the Visual Studio profiler). After 5,000,000 steps, it dropped from ~864 MB to ~671 MB.

You could push this technique even further by packing numeric values into bit vectors. There are some examples of doing so in the docs.

Here's a sample of the code that I used. All of the changes happened within State. I opted for the most convenient refactoring path... there might be a more efficient/performant way to code all this.

BitVector32 bits;

private const int ReinforcedIndexFingerMask = 1 << 0;
private const int CarpalTunnelPreventionCreamMask = 1 << 1;

public bool ReinforcedIndexFinger
{
    get => bits[ReinforcedIndexFingerMask];
    set => bits[ReinforcedIndexFingerMask] = value;
}

public bool CarpalTunnelPreventionCream
{
    get => bits[CarpalTunnelPreventionCreamMask];
    set => bits[CarpalTunnelPreventionCreamMask] = value;
}

As an added bonus, I think you could simplify the GetHashCode() and Equals() implementations by comparing the bit vector directly, rather than comparing every value individually.

Source Link
xander
  • 141
  • 2

You can reduce the memory footprint by using BitVector32 instead of bool. A bool in .NET occupies a full word in memory. A BitVector32 allows you to store the equivalent of 32 bools the same memory space.

By replacing all of the bool fields in State with a single BitVector32, I was able to reduce State's memory footprint from 68 bytes to 12 (as measured by Marshal.SizeOf<State>()). Since State is the key in the dictionary, that adds up to a decent reduction in memory usage overall.

After applying my changes to your master branch and running for 1,000,000 steps, the memory usage of the state dictionary dropped from ~215 MB to ~167 MB (as measured by the Visual Studio profiler). After 5,000,000 steps, it dropped from ~864 MB to ~671 MB.

You could push this technique even further by packing numeric values into bit vectors. There are some examples of doing so in the docs.

Here's a sample of the code that I used. All of the changes happened within State. I opted for the most convenient refactoring path... there might be a more efficient/performant way to code all this.

BitVector32 bits;

private const int ReinforcedIndexFingerMask = 1 << 0;
private const int CarpalTunnelPreventionCreamMask = 1 << 1;

public bool ReinforcedIndexFinger
{
    get => bits[ReinforcedIndexFingerMask];
    set => bits[ReinforcedIndexFingerMask] = value;
}

public bool CarpalTunnelPreventionCream
{
    get => bits[CarpalTunnelPreventionCreamMask];
    set => bits[CarpalTunnelPreventionCreamMask] = value;
}
```