Two Dimensional Array

A few days ago a group of software engineers were discussing how the order in which the numbers of rows versus columns in a two dimensional array affect performance. That is; if an array has more rows than columns as opposed to more columns than rows, the time it takes to traverse the array will be affected.

The issue discussed is due to the fact that when all is said and done, the code is being executed by a processor (CPU) which needs to load values from the array represented in memory into a register. The time it takes to load the value depends on the representation of the array in memory and the algorithm used to traverse / process the array.

The discussion reminded me of the port of the well known NoSQL database engine Apache Cassandra written in Java to ScyllaDB written in C++. The company SCYLLA (www.scyladb.com) claims that their port is at least one order of magnitude faster than the original database. They achieved that by using C++ instead of Java and making some changes allowed by the different programming language.

I am not going to get into the actual port, but will show the results of a program written in C#. A screen capture of the C# program follows:

As one can see, processing a byte array of 10,000 rows by 1,000 columns took 12.27 seconds. This processing was performed by a function named LargeSmall(). Processing consisted on adding up all the entries in the array. The same array was then processed by the SmallLarge() function. The processing was performed by traversing the same array in a different order.

Initially I populated the array with random values. All was well when running the code written in the same programming language. When using different languages the initialization of the pseudo random number generator produced different values. For simplicity I set all values in the array to one (1).

Regardless of the programming language, it seems that the execution of the first function LargeSmall() tends to be faster than that of the LargeSmall(). The reason for this is that the operations required by the CPU to index the rows is faster than when indexing the columns. The rows just require an increment while the columns require a computation because cells are not contiguous.

I always recommend a test driven approach. Start with some comments in the main and then tackle the additional functions in a progressive way until all is working properly. If during the process a new simpler and faster approach is discovered, go for it. Once all is operational, if needed, spend time optimizing the code.

When optimizing one should make sure that the effort is needed for the resulting gains in performance. It is not worth optimizing a function / method that runs on a background task, not too often called to achieve a few milliseconds. In contrast, if you have a function that is called many times a second, a few milliseconds (or in the worse case seconds) would be mandatory. This is just common sense.

I do not have more time this morning to go into a discussion of when to optimize code. Make sure that the code is peer reviewed and that you listen to comments and suggestions. Also make sure other developers and QA have the time to experiment and test the software before it is released.

All the code in this post was generated in a Windows machine. The C# code was developed using Visual Studio 2017 Enterprise Edition. The Java code was developed using Eclipse Oxygen and the C code was developed using Visual Studio Professional 2013.

If you have comments or questions regarding this or any other post in this blog, please leave me a message or if you prefer send me a message via email. I try to spend a couple hours every day learning, experimenting and posting in this blog.