Wednesday, November 25, 2020

Ideas for Windows

Where should Windows go? What improvements should Microsoft make?

I have some ideas.

First, Microsoft should drop the '10' designation of Windows. Yes, Windows 10 is different from Windows 8.1 and Windows 8 (and Windows 7, and Windows Vista, and...) but that's not important. What's important is how people talk about Windows, and how Microsoft wants people to talk about Windows.

People don't talk about "Windows 10"; they call it "Windows 1809" or "Windows 20H2". And those names are good enough to identify a version of Windows. The "10" is superfluous.

There is another benefit to dropping the '10'. It means that Windows doesn't get embroiled in marketing battles with Apple's macOS. Apple just updated macOS from version 10 to version 11. Is Apple now "ahead" in the operating system race because they have version 11? Is Microsoft behind because they have version 10? (Fans of the old movie "This is Spinal Tap" can make jokes about "our amplifiers go up to 11".)

By dropping the '10' and referring to release numbers, Microsoft avoids all of the comparisons. Or at least the meaningless comparisons of '10' and '11'.

Looking beyond version numbers, Microsoft is moving into a position which will let it reduce the number of configurations for Windows.

Today, Windows has multiple families: "Windows Server", "Windows Professional", and "Windows Home".  When Windows was sold in a box, these divisions made sense.

As Windows moves to a subscription service, the notion of different Windows versions makes less sense. The subscription model changes the idea of the purchase. Instead of "I'm buying this Windows product today and I will use it for a few years, getting free updates in that time" the idea becomes "I have subscribed to Windows, I pay a monthly fee, and this month I want this configuration of Windows". The difference is that one can change the product during the subscription (much like changing a Netflix account to allow more or fewer screens at the same time).

With a Windows subscription, one could start with Windows Home, then "dial up" the configuration to Windows Professional for a few months.

Maybe the designations of "Home" and "Professional" don't make sense anymore. Perhaps a subscription to Windows gives one access to a set of features (more granular that "Home" or "Professional"), and you can activate (or deactivate) new features as you want. Instead of choosing one of three options, one chooses from a large menu of services, enabling those that make sense.

I think we will see a number of changes as Microsoft moves from the "sale in a box" concept to the subscription concept of software.

Tuesday, November 17, 2020

The joy of a small programming language

I recently had the pleasure of reading the reference manual for Dibol (a programming language from the 1970s). And reading the manual was a pleasure. What made it so was the brevity and directness of the manual, the simplicity of the concepts, and the feeling of confidence in my ability to start programming it the language.

Dibol is a language from the minicomputer era, a short period of computing that occurred prior to the PC revolution. Made by DEC, it was an alternative for COBOL that ran on small systems and operated on simple files. It's syntax was influenced by COBOL, but much simpler.

The entire reference manual ran about 30 pages.

Dibol, I think, would have fit well in the Unix environment. Unix systems tended to use text files with flexible formats and varying line lengths, and Dibol was built for text files with fixed-length formats, so the match is not perfect. But Dibol is a language that follows the Unix philosophy: a simple tool to perform a simple task.

I could see it as a companion to AWK, a small language which handles text files and variable-length lines.

Dibol didn't "make it" as a programming language. It lives today, in the form of "Synergy/DE" which is a large superset of the original Dibol. So large, in fact, that it perhaps no longer follows the Unix idea of a simple tool. (I suspect the reference manual is longer than 30 pages.) But Dibol and its successors DBL and Synergy/DE have no significant presence in the popularity lists from Tiobe or PYPL or RedMonk.

We have no small languages today -- at least no small languages that enjoy any amount of popularity. AWK may be the most famous of the small languages, and even it is in the lower ranks on popularity lists. The popular languages are big (C++, Java, Python, C#, R, Visual Basic...).

We should be careful with the popularity indices. The methods used by them may skew the results. Tiobe and PYPL count queries about the languages -- people asking questions. I think we can safely assume that people will ask more questions about large languages than small languages, so complex languages have an advantage in the popularity metrics.

RedMonk also looks at Github and the code posted there. It's not clear if RedMonk is counting number of projects, number of files, or lines of code. (A complex language would probably have more lines of code.) But Dibol and other small languages do not show in RedMonk's list.

So we can conclude that there is no significant use of small programming languages. As a programming language, you're either big or you're unknown.

Which, I think, is a shame. The big language are hard to learn and easy to create large, complicated systems. Small languages have the advantage of doing one job and doing it well. We as an industry may be missing out on a lot.

It also means that large programming languages are the "go to" solution for programmers; that programmers prefer large languages. There is some sense in this. A large programming language (C#, Java, take your pick) can handle just about any task. Therefore, a programmer who knows a large programming language is capable (in one sense) of handling any task. Large programming languages give the programmer flexibility, and more opportunity. (I say "in one sense" because knowledge of a programming language is, while necessary, not sufficient for the design of large or specialized applications. System architecture, user requirements, performance analysis, and deployment practices are also required.)

The consistent use of large programming languages means that our solutions will tend to be large. I know of no small Java applications, no small C++ applications, and no small C# applications. There may be small utility programs written in large languages, but I suspect that those utility programs grow over time and become large utility programs.

Large code bases require more effort to maintain than small code bases, so our bias towards large programming languages is, in the long run, costing our customers time and money.

Of course, the alternative (lots of small programs written in small programming languages) can have the problem of multiple languages and not enough people to maintain them. A shop with hundreds of programs written in a dozen or so different programming languages also faces maintenance efforts. Should every programmer in the shop know every programming language used in that shop? That also requires time and effort.

So what should a programmer do? Learn one large language? Learn lots of small languages?

My recommendation is to learn multiple languages, some large and some small. For large languages, pick two of the popular languages C, C++, C#, Java, JavaScript, and Python. Also learn some small languages such as Awk, Lua, and bash.

But don't spend time on Dibol.

Wednesday, November 11, 2020

Flipping bits

Apple has introduced a new line of Mac computers which use Apple's new M1 system-on-a-chip. Apple made several claims about the performance, but those claims were vague -- at least in terms of measured performance. (Claims were in the form of "up to 2 times faster", "up to five times faster", "the fastest Macbook yet".)

Apple's M1 chip contains a processor that is based on ARM architecture, which is quite different from Intel's x86 architecture. How does one compare them?

One of the oldest comparisons of processors is MIPS (millions of instructions per second). Dating back to the mainframe age, it is simple in concept: count the number of instructions in each second of processing. But when comparing different architectures, a comparison of instruction to instruction is not useful. The instructions sets are different, and a computation on one processor might use one instruction, and the same computation on a different processor might take three or four instructions.

A later metric, FLOPS (floating-point operations per second) is somewhat better when the two systems are performing tasks that use a lot of numeric processing. This metric focusses on the instructions used for processing numeric values, specifically floating-point values, and looks at operations and not necessarily discrete instructions. But its focus is its weakness: Tasks that use integer arithmetic and fixed-point data representations aren't usefully measured with FLOPS metrics.

Thinking about the differences between Intel and ARM processors, perhaps we need a different metric, one that is robust for different architectures and different types of processing. And I have thought of one, although it may not be practical.

My idea for measuring performance is to execute a task or function and count the number of bits that are changed (or "flipped") during the process.

The advantage of this metric is that it is neutral to architectures and also neutral to the type of processing.  MIPS doesn't measure different instruction sets well and FLOPS omits integer operations. Bit-flipping, in contrast, works with all architectures and all data types. (I'll get to the downside of the bit-flipping metric later.)

The idea of bit flipping is simple: count each bit that changes state, either from 0 to 1 or from 1 to 0. If a register holds 0x0001 and is cleared, then one bit is changed (from 1 to 0). If a register holds 0x001f and is cleared, then five bits are changed. (If a register holds 0x0000 and it is cleared, then no bits are changed.)

Such a measure has the advantage of working with any type of data. We can use this measure with floating-point data and with integer data. We can even use it with BCD (binary converted decimal) data. We can use it with text data and with objects.

Notice that this measure does not measure time. A comparison of the number of bits changed during a process is a count, not a time. One processor might be flipping more bits but running faster. A higher flip count does not necessarily mean slower performance.

One might think that such a limitation makes the bit-flip metric useless for performance comparisons. If one is interested in speed, and only speed, then the point is valid. Bit-flipping measures the efficiency of the processor: the same task with a lower bit-flip count is more efficient -- and therefore uses less energy. That may be useful to system designers.

One challenge with the bit-flip metric is deciding which bits count. Even though bits are all the same (a single value of either 1 or 0) different bits are stored in different locations and used for different purposes.

One simple difference is memory and registers. Processors store values in memory ("RAM") and also store values in registers, a small set of locations that are part of the processor. Registers are used for computations and change often; memory is used for storage and changes less frequently. Should the bit-flips for memory count the same as bit-flips in registers?

If we agree to count registers and memory differently, then we open the door to other distinctions in bits. Modern processors have caches, usually three layers, which store values too. Caches exist between registers and memory. If registers and memory have different "weights" for bit-flipping, caches should probably have different weight too.

We've been looking at data, but processors also use addresses. In order to read or write a value in memory, the processor must put an address on the buss to tell memory which cell it wants. Those bits change; should we count those changes too?

Addresses have more complications. Modern processors use an advanced form of memory management, which allows for multiple processes. Memory management changes the address that the process requests (a "logical" address) to the real address that holds the value (the "physical" address). Should those bit-flips count? (Keep in mind that physical memory pages are assigned at random, so two separate runs could have different physical pages and therefore different memory addresses and therefore different bit-flip counts.)

After careful consideration, I think the best solution is to count all of the bits. ("All the bits!") Categorize them if you want, report them in groups if you want, assign different weights to the different groups if you want, but count all of them.

We could compare similar tasks on Windows and Mac, on Intel and ARM, even Microsoft Word and Office Libre.

Which brings me to the one drawback to bit-flip counts.

It's hard to do.

Counting bit-flips requires access to memory, registers, and all sorts of innards of the processor. It's not something an application can do, or even a device driver or kernel extension. This kind of observation must occur in the processor; nothing else will do.

To effectively use bit-flipping, we need the cooperation of Intel and ARM (and Apple, who designs the M1 off of the ARM design). We also need clear and precise descriptions of the data we want to collect, so that the counts on Intel processors count the same things as counts on ARM processors.

We also need an answer to the meta-question about data collection: Counting bit-flips in itself changes data values (the counters for bit-flip operations). Do we count those bit-flips too? (For the record, I am against counting those bit flips. Because if we count the bit-flip counter flips, then we have to count the counters for those bit flips, and the count the bit flips for those counters, and on and on. Enough is enough!)

Bit-flipping is a nice thought experiment. Implementation requires changes to processors and the cooperation of manufacturers, which is a tall order. I suspect it will remain a thought experiment.

Unless!

Unless... we limit bit-flips to something simple (such as only the CPU registers, and nothing else) and we leverage virtual modes, letting the "real" processor count the bit flips in the "virtual" processor. (Bit-flipping is a simple operation: XOR the "before" and "after" values, and then count the bits in the result.)

Such an arrangement might just be possible. It still needs cooperation from the processor designers, but such a scaled-down version might be possible.

Thursday, November 5, 2020

Big is the new big

For PCs, big is the new big. It wasn't always this way.

When the PC revolution started, small was big. The advantage of PCs was smallness, in size, in cost, and in effort. PCs were small enough to fit on a desktop, cheap enough to be purchased as "word processors" (to avoid the data processing bureaucracy), and easy enough that one person could operate them.

The programmers of the PC revolution took pride in the smallness of hardware and of programming languages. BASIC, the original language of the PC revolution, could fit on a computer with 8K of RAM. (That's 8192 bytes.) Other programming languages were also small. Even the names emphasized smallness: Tiny-C, Tiny-Pascal.

We rebels of IT considered "big" an aspect of mainframe systems, and associated "big" with slow, lumbering processes that hindered productivity. The Agile movement was defined as the opposite of "BDUF" (Big Design Up Front). Big was what we did not want our systems to be.

Yet something has changed. We no longer want to be small. Now, we want to be big.

Notice the (now decade-old) desire for "big data". That was a full embrace of bigness. There was also "big analytics" which analyzes large datasets.

Other things have become big. Databases have become big. Spreadsheets have become big. Word processors have become big. Our PCs are not stand-alone systems, but nodes in a larger system and reliant on that system for authentication, updates, and basic processing.

Programming languages have become big, with C++, Java, Python, C#, and Visual Basic in the top slots of the Tiobe index for October 2020. The top position is held by C. While some consider C a small programming language, I have my doubts. C uses a small set of keywords, but has a large standard library. It may not be large, but it isn't small.

We have lost our desire for small systems. Our smart phones are physically small, yet their operating systems are complex and app development is for professionals. Even small hardware systems such as the Raspberry Pi run a full Linux distro, which requires a fair amount of administration.

The only small systems are the Arduino and similar systems, which run a slim monitor operating system and are designed for hardware control, not general-purpose computing.

Perhaps we were deluding ourselves. Perhaps we wanted large systems all along. We craved the power of fast processors, ample memory, and disk space that was not limiting -- that much is certain. Perhaps the cost of faster processors, more memory, large disk space, and interconnected systems is bigness. Perhaps it is not possible (or not cost-effective) to operate small systems loosely coupled.

Perhaps.

But perhaps the desire for small, simple systems remains, and perhaps, one day, it will resurface.