Skip to content

Repository files navigation

BinaryState

An experiment into storing collections of binary states in 64-bit integers.

Why?

The concept came up when discussing infinite loop detection - how was most efficient to store and compare states when deciding if an infinite loop was occuring - and it felt like a fun techinical investigation and an opportunity to play with bitwise operators.

Was it worth it?

It was fun, and I learned a lot about optimisation, data structures, and benchmarking. I think State.GetState() method is probably my favourite part of the whole project, it has a satisfying typewriter quality to the left shift, right shift to isolate the required index down to 1 or 0. Conversely State.SetState() provided the largest challenge for figuring out how to only change the value if the value needed changing.

What came out of it

This is a wrapper for a ulong that provides accessors to each index in the binary representation of the number.

This is a wrapper for a State[] that provides methods for accessing indexes within each state in the collection (normalised from 0 - max capacity).

Does it work?

Surprisingly yes, I compared setting a specific index, getting a specific index, and comparing two identical objects, and while the getting and setting were slower than (most of) the alternatives, when it comes to comparison it blew the others out of the water.

Test Data

The test data contains 1,000,000 randomly generated boolean values which is then stored in various collections:

  • List<bool>
  • Dictionary<int, bool>
  • StringBuilder
  • bool[]
  • States

There is also a target index which is the target for both Get and Set tests (initially 500,000, now random from the range).

Set Item

Sets a specific index to true

MethodMeanErrorStdDev
List_SetItem1.3268 ns0.0379 ns0.0317 ns
Dictionary_SetItem4.6041 ns0.0864 ns0.0766 ns
StringBuilder_SetItem2,994.7222 ns10.5633 ns9.8809 ns
Array_SetItem0.0104 ns0.0048 ns0.0040 ns
States_SetItem14.8301 ns0.1044 ns0.0872 ns

Get Item

Gets a specific index

MethodMeanErrorStdDev
List_GetItem0.3262 ns0.0337 ns0.0315 ns
Dictionary_GetItem4.4549 ns0.0438 ns0.0365 ns
StringBuilder_GetItem2,974.3999 ns13.7274 ns12.1690 ns
Array_GetItem0.0586 ns0.0149 ns0.0139 ns
States_GetItem14.2449 ns0.0456 ns0.0426 ns

Compare

Compares two separate but identical collections

MethodMeanErrorStdDev
List_Compare1,216.24 us18.215 us17.890 us
Dictionary_Compare10,520.83 us193.107 us322.639 us
StringBuilder_Compare4,989.88 us96.439 us103.189 us
Array_Compare1,227.57 us23.660 us30.764 us
States_Compare54.02 us1.205 us3.476 us

What Next?

If I were to dig further into it I'd want to look at optimising the getters and setters in States to see if there's any time to be shaved off, 14ns is good, but it would be interesting to see if there is any time that can be shaved off. I suspect moving everything from State to States and having the data in the States array be ulong rather than State would be a start.

About

An experiment on storing binary states in 64-bit ints

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages