60 lines of code changed. 100 times faster.
By changing just 50 lines of code, I was able to make FlingOS™ read files from a FAT file system 64 times faster. Add just ten more lines and reading files from FAT on a USB stick is up to 100 times faster. But how can such small changes lead to such a large increase?
Progression: From good design to better design
The simple answer is: poor design. FlingOS is designed to be easy to understand both in terms of reading the code and in terms of overall structure and control flows. Unfortunately, this can lead to massive inefficiencies. FAT file systems, USB Mass Storage devices and EHCI Controllers are by no means simple, so writing clean code is difficult. Furthermore, writing code you can just jump-into without knowing the rest of the system is even harder. But that is what I have attempted with FlingOS (and hopefully achieved). So how can I call my original code both a poor design and a good design?
When I was first writing the code for USB Mass Storage devices, I decided that reading one sector was easier than multiple sectors. So I implemented the basic code for reading a single sector and that was that. Originally, therefore, the design was very good for simplicity and readability – the key things which make code understandable. But from a performance view it was highly inefficient (for both hardware and software). From one perspective my original design was good and from the other it was poor.
As the features of FlingOS have expanded (conforming to standards along the way), the underlying USB code has become capable of reading multiple sectors in a single request. The USB code has grown somewhat in complexity (by necessity) but remains understandable. With the new capability of reading multiple sectors all at once, suddenly my original design looks poor from both perspectives. Because reading one sector at a time makes no sense if you can just as easily read many at once. This reduces how easy the USB Mass Storage code is to understand because it adds a layer of confusion. As a result, it has become necessary to updater the USB MSD driver code.
But what about reading files from FAT? For that, FlingOS uses the FATFileStream class. Again, this is a story of progression. It started (and remained for a long time) totally simple. It just read one cluster at a time till it had read all the data that was requested. This was largely because reading multiple sectors at a time wasn’t supported by the underlying device drivers, so it was pointless to request more than one cluster at a time. But since the underlying device drivers (the USB Mass Storage driver, PATA driver and PATAPI driver) all now supported multiple-sector reads, why not? In fact, you can increase read speed by requesting as many contiguous clusters as possible. The algorithm for doing so is actually just as easy to understand as reading one sector at a time.
Today, therefore, I finally implemented the USB MSD multiple sector read and FAT File Stream multiple cluster read. It changed just 60 lines of code to utilise the new, underlying features. The result? Up to 64 (contiguous) clusters can be read at once and there’s no specific software cap on number of sectors to read at once. The overall effect of which is the code runs around 100 times faster (over small files. Possibly even faster for large ones due to other factors). This makes drivers loaded from a USB stick much more viable (which is what FlingOS is currently working towards).
Judging a design
So I’d like to leave you with this:
Calling code “bad” or “good” are highly subjective judgements.
You may call one piece of code very poor. Someone else may say it’s the best in the world. It all depends on how you’re judging it – be that by performance, readability, memory efficiency (which itself has many factors), lines-of-code used (ugh…) or any other measurement you care to make. All code will compromise (or excel) at something; you just have to work out what. When you’re judging someone’s code (even your own), remember to state what factors you took into consideration. What was your perspective.