The Software Complexity

Image of the internals of a Commodore 64 showi...

Image of the internals of a Commodore 64 showing the 6510 CPU (40-pin DIP, lower left). The chip on the right is the 6581 SID. The production week/year (WWYY) of each chip is given below its name. (Photo credit: Wikipedia)

There is an old sentence attributed to Bill Gates that said: “640K of RAM is enough for anybody”. I think that Gates has denied that he was its author. But it is interesting to analyze how complexity is evolving in the software sector.

I began to write computer programs in an old Commodore 64 with only 64 KBytes and a 6510 microprocessor of 8 bits from MOS Technologies when I was sixteen. That computer had a very ancient and simple basic interpreter integrated in its ROM and that limited hugely the programming capabilities of that simple device.

Commodore 64 was a success (especially in Germany) for gaming due to its better graphical and sound capabilities than its direct English competence, the Sinclair ZX Spectrum. In order to take advantage of the “full potential” of the device, many programs were developed directly in assembler (the most similar language to machine code).

Although the initial sentence attributed to Gates can seem stupid today when my last computer has 8 Gbytes of RAM with a microprocessor of two cores and a word size of 64 bits, and even my new Smartphone 4 Gbytes, (and they are not at the highest scale), I must recognize that it does not sound stupid when you have written software in assembler. In that case, it can sound even reasonably, because you can bet that you cannot fill 640 Kbytes of memory with a program write in assembler during a month without using libraries of functions (and without taking data into account).

To make a computer program in assembler is very hard, but in terms of the complexity of the task, the language is very simple. When we talk about the complexity without any metrics, sometimes its concept is not well understood, because we do not distinguish between the complexity of the task and the complexity of the system.

A program write in assembler provides a code that always made exactly what you have written because the assembled code specifies with totally precision how the registers of the microprocessor must process the data. As precision is total, uncertainty is null and, in that sense, the program is complicated but it is not complex.

However, this kind of programming is very error prone because people do not think as a microprocessor. Programmers must translate high level actions involved in formal instructions into simple low level handling of numbers. This uncertainty due to the error prone programming provides a system with high level of uncertainty in its behavior. The result can be a very complex system.

Current systems only have a little part of their operative system and some drivers in assembler, because even the operative system is written in a high level language. A high level language provides direct instructions that are turned into machine code through a computer program known as compiler. A compiler can translate a few hundreds of code lines into a lot of thousands of code lines. The degree of complexity in a high level program is much larger than in a low level program, because the structure of the program can be very big. A microprocessor has only a very limited number of registers (internal variables to make calculations), but a high level program can have any set of them provide much more functionality, however the result can be less error prone because the language is nearer the human one. The program can be complex but the resulting system can have less complexity.

With a high level language it is possible to write a program in a month that fill the memory of an old computer as the Commodore 64 once it has been compiled. In that case, there is not a relationship between complexity and memory size; however, as memory increases, software can be made to handle a bigger amount of data through many new variables and functions that operate with them, although the probability to run wrongly due to an error prone language is lower the final uncertainty at the system can be larger because the number of functions and variables where an error can appear is larger.

Systems are more complex due to a more complex hardware (size and number of registers, number of cores, set of instructions) and due to a more complex software (object oriented programming, multiprocessing programming, program threads, multitasking operative systems, virtualization), but not due to the memory size, although more memory lets a more complex software implementation. It is the structure of the systems what provides a lot of complexity instead of the uncertainty of a very error prone programming language.

If there is a relationship between complexity and size it should be better defined by the Moore’s Law, that established the exponential evolution of the number of transistors integrated in a single microprocessor chip.

Moore's Law. Photo Credit Wgsimon

Graph 1 Moore’s Law on number of transistors in a microprocessor by Wgsimon (Source Wikipedia)

We say that something is complex when it can evolve in an unpredictable way under an unexpected event.  With an assembled program in a microprocessor with an accumulator register and two index register things are very hard to implement but errors could be easy to identify, but how can we know what is wrong in a system with dozens of processes that are be written by several programmers each, with different software libraries written in different computer languages, running simultaneously in a quad-core microprocessor, connected to several networks and fed with data from hundreds of computers, if it hangs suddenly?

Of course, system administrators have tools and techniques to identify those problems when they have happened, for instance, some wise computer scientist invented logs, but it would be more useful to predict some faults before they occur specially in certain industrial systems.

I want to notice that not all this complexity is bad if it is well managed, namely, if the system is designed for simplicity. For instance, in a modern computer, when a process hangs not all the system stops, only one of the cores, the system will run slower but other critical task can continue without produce a collapse at the whole system. The collapse will depend on the importance and the links of that process to other processes running at the system. Other process could analyze the system automatically and find that there is a hanged process and stop it permanently or restart it in order to provide a better performance. In a similar way, the complexity of the system could be measured through some control variables in order to anticipate a malfunction.

Sometimes complexity can be attacked with complexity, as in a war, fire can be the best answer to fire. This is not so odd; in order to reduce complexity and stabilize a system, we can use a controller device. Controller devices reduce the number of the most probable states of a system, but they can be complex systems itself, of course they must be tuned to do a certain task properly. Thus, the activity of complexity management can be seen. We must design and tune some kind of complexity control device in order to avoid that the system can collapse under unexpected events.

In the last example, we would take advantage of a complex multicore microprocessor to run a critical process isolated from the rest of the system that in some occasions can be a good strategy to preserve the system in a state of proper performance. Here, hardware complexity provides less software complexity because software has been developed in order take advantage of it. Complexity management is not simply a matter of trying to reduce the structure or the uncertainty; it is a matter of making that the system is working far from its maximum complexity. Any complex systems should be always designed from a complexity viewpoint.

A software system can have a few code lines and be very unstable, and another one can have a lot of code lines and be very robust if it was designed thinking in complexity. Unfortunately, practically no commercial computer system is working today fully designed from a systemic viewpoint, as hardware providers are different to OS providers, and these ones are different to application providers. In any  system applications from many different sources can be running, and this fact makes more important that this complexity is taken into account by IT managers.


 Azul Rojo 0003


Mr. Luis Díaz Saco

Executive President


advanced consultancy services


   Nowadays, he is Executive President of Saconsulting Advanced Consultancy Services. He has been Head of Corporate Technology Innovation at Soluziona Quality and Environment and R & D & I Project Auditor of AENOR. He has acted as Innovation Advisor of Endesa Red representing that company in Workgroups of the Smartgrids Technology Platform at Brussels

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s