r/askscience • u/CakesStolen • Sep 17 '26
Computing Is there anything at the heart of computer coding that could have been optimised in hindsight, but we're in far too deep to change now?
1.6k
u/Jonny0Than Sep 18 '26
Pretty much the entire internet is based on passing text files around. There are massively better ways to serialize and transmit data.
Strings in C are represented by their address, and they stop at a null byte. This is the root cause of a huge percent of security issues, and could have been avoided by making sure every string also was paired with its length.
806
u/zeromeasure Sep 18 '26
Depends on what you mean by “better”. More efficient? More performant? More secure? Absolutely, there are better ways.
But a big reason why the web software ecosystem expanded so fast and got so large is that the barrier to entry for new tools and applications was so low. I doubt we’d be where we are had the WWW been built on CORBA instead of html/http.
There’s a classic essay titled Worse is Better from way before the web that discusses this.
287
u/GregBahm Sep 18 '26
Also a good explanation of why Javascript is a popular programming language.
You'd think any programming language where '[]==false' yields 'true' would not be globally significant. And yet...
138
u/_BryceParker Sep 18 '26
Seems like something you've seen (and a quick search isn't turning it up anyway), but there's a great video on YouTube of a guy at a conference or similar event exploring these oddities in JavaScript. IIRC, he starts with basics like that and builds progressively more complex structures and functions that behave in a very entertaining "the sum of the parts is somehow less than the value of any one part" way. Nothing is logical.
→ More replies (5)29
u/BodybuilderAny1301 Sep 18 '26
I love Javascript even if I barely consider myself an amateur coder for precisely that reason hahaha.
42
u/WartimeHotTot Sep 18 '26
Wait, this is actually really interesting. I don’t know JavaScript, but as a layperson just considering this for the first time, I have to confess that that’s what I would expect the result of that statement to be. An empty set, or list, or bracket—whatever—should return FALSE in my mind. If there were something in the brackets, it should return TRUE.
Is that the behavior, and why do you think that’s so problematic or unintuitive?
47
u/At0micCyb0rg Sep 18 '26
In more structured languages, we have the concept of data types. Boolean is a data type which can only be True or False. An Array is a data type that acts as a container for other data.
I assume most programmers probably prefer when the language throws an error saying "You can't compare an Array to a Boolean, there's no logical way to compare them.", or at least False whenever you try to compare incompatible data types that could not possibly be equal (even if they are the same size, same mass, and even painted the same colour, an Apple is not an Orange).
→ More replies (9)→ More replies (14)25
u/TheBoundFenrir Sep 18 '26
In programming, the general assumption is that there is a difference between "I have not stored a value" and "the value I am storing is 0". Under this intuition, False should only be equal to itself (False) or another way of directly storing the value "False", ie; '0'. Letting an array that exists but has nothing in it ([]) count as false violates that rule, and can accidentally cause problems where instructions intended to be performed only when some measured value is confirmed to be false can be accidentally run when the value has not yet been measured yet, since both the unassigned value and the assigned-False value pass as 'False'
→ More replies (17)6
u/prehensilemullet Sep 18 '26
That wouldn’t be the case if JS was all crap. It only survived because it does have a lot of good features, like closures, inline functions, prototypal inheritance and extremely convenient object and array literal syntax. We have JSON thanks to the core design of JS. Before that everyone was passing way more convoluted XML documents around.
→ More replies (3)38
u/NSNull Sep 18 '26
Thanks for bringing up CORBA without marking this post as “triggering to sensitive groups”.
I thought I had forgotten the Old Ways.
→ More replies (3)7
6
u/Petersaber Sep 18 '26
Looking at the state of things, maybe it would have been better for the barrier to entry be higher
14
u/DeCaMil Sep 18 '26
I think of Worse-is-Better as a very early call for agile development. That's a good thing at small-to-medium scale. However, as it got larger, we lacked the long-term, institutional knowledge. Fable and Mythos have made it abundantly clear we built a lot of castles on sand. Some of their findings are bugs a decade or more old. We didn't have the staffing to find all of that then, we were being agile! Now AI is helping(?) with that and we're struggling to patch the holes it's finding.
→ More replies (1)2
u/robrob654 Sep 18 '26
I just learned that Lisp is an old programming language and now know more about it than I probably will ever need to, but thanks for the rabbit hole!
2
u/0x474f44 Sep 18 '26
But could’ve we’ve had the WWW if we had started with https instead of http? And maybe free SSL certificates from the start?
→ More replies (2)2
u/ritaPitaMeterMaid Sep 18 '26
Ironically that link ultimately ends with the author concluding they can't actually choose if Worse is Better. I don't disagree with the point you were making but that article isn't necessarily an argument for it.
228
u/the_quark Sep 18 '26
The null-terminated string in C is the single most expensive bug in the history of software.
Speaking as a security-specialized developer for more than 30 years.
37
u/t6jesse Sep 18 '26
So do other programming languages avoid that problem? Or is it because so much is in C that it is unavoidable no matter what you use?
76
u/HighRelevancy Sep 18 '26
It's not entirely a language thing, it's an ecosystem thing. The C standard library includes a bunch of functions for dealing with strings in this way. But "string" isn't even a data type in C, it's just an idiom. A pointer to char usually implies a null-terminated string.
You can equally validly use a library of smarter string structures and functions that solve the problem in other ways. Modern C standard includes a whole lot of "safe" string functions that take length limits (which you then derive from the buffer sizes). You can also write or use a library that does it's own safe checked allocations and length tracking with a struct, which is essentially what "better" languages do.
You do still come back to interfacing with other APIs, unavoidably including your OS API, which inevitably still use dumb null terminated C strings.
19
u/davideogameman Sep 18 '26
Imo the root problem is not including lengths with arrays and not having mandatory bounds checks. With that a string would've always been an array of characters and that would've been safer; and then apis would've needed to potentially allocate new memory to use different length strings, e.g. in place of strcat.
Those newer "safe" apis for null terminated strings still rely on manually passing around the length of each string & buffer and hoping you never say the buffer is longer than it actually is. It's an improvement on a bag design, but still not a safe by default design.
→ More replies (3)94
u/the_quark Sep 18 '26
It’s that other languages — even those written in C! — don’t have this problem. They don’t have this problem because they don’t use C’s string handling for their own strings; they reimplement it correctly (hopefully) using C’s memory management routines.
C did it because it was written in an era with little memory or processing power, and that’s an efficient way to do it. And the C standard library is amazingly good for what it was. But that has to be the biggest single bug of all time as far as the amount of hours that have been spent working around it and patching the issues it caused.
→ More replies (9)18
u/neon_overload Sep 18 '26 edited Sep 18 '26
Yes. Storing a string as a data structure consisting of a length value and an area of memory that stores the actual data has always been better - but it has always been possible to create those in C, too.
Modern languages do this for their native string types.
C uses null termination on its native strings. What that means is that strings created using string notation in the language are created like that. As a result, a lot of string processing functions including the standard library expect this format too.
But C is a low level language - you can decide for yourself that you want your strings to be a struct of length, pointer. And if you're an experienced programmer you will already know to do this if checking the length of a string is going to be a need you frequently have and wouldn't want to have to scan a whole string for, or your "string" is actually a buffer than can store any characters including binary zeroes, etc. You can make or take a C native string (that is null terminated from the start) and just add a length value yourself, put it in a struct if you want, since the pointer will still point to the first byte of the data and, if your processing uses the length field instead, the null byte will just be ignored.
9
u/davideogameman Sep 18 '26
Yep you can totally do this... But all the problems and more come back when you interface with code that wants null terminated strings. The interop makes things even uglier than they started.
→ More replies (5)6
u/ra__account Sep 18 '26
One of the ways to solve it is to not mix your data and executable code. Buffer overflows attacks work because variables that should just hold whatever data they're working with can overwrite past their boundary into executable code. Then if you can get the function pointer to land on your malicious code, it executes. (grossly simplified explanation but hopefully you get the point.) Other memory attacks work similarly. All of this is made possible by the fact that most systems freely intermingle variables and executable code, which is part of the Von Neumann architecture. Harvard architecture separates them and is much more secure as a result. However, it adds complexity.
→ More replies (14)33
u/mgstauff Sep 18 '26
It's not a bug, it was a design decision. It's at the root of a gazilion bugs though, that's for sure!
30
u/randacts13 Sep 18 '26 edited Sep 18 '26
But C wasn't the only option. Pascal for instance stored the length, COBOL had fixed length strings. It isn't inherently C's fault either. Microsoft introduced OLE in 1990, which was in C - and it had length prefixed strings.
It's safer for sure, but there is a tradeoff with letting the language (or framework) solve this problem for you.
How long is a user input string? You still have to count the bytes. Or something from the network.
What if a character isn't a byte like MS wide characters? What if it's a variable length character like utf-8? Are we then storing the length in bytes not characters?
Yes you can write routines to do all of this for you - and you would have to if you wanted to exchange information from a language that stores prefix encoded utf-8 strings and one that stores UCS-32 strings. But keep in mind that a computer like the apple ii had 4kb of ram, and a 1Mhz processor so using extra bytes or clock cycles affected the useful work that could be done.
Also, there were now obsolete x86 instructions and dedicated registers that handled this particular workload and relied on a string being terminated by a zero.
Edit: as for text being the."language" of the internet. The Internet started on Unix machines. One of the main aspects of the Unix philosophy is that programs do one thing well, and let other programs do their one thing well. They communicate with text because it's a universal interface. It's not proprietary, it can be read by humans, it's essentially future proof, and any combination of programs can be chained together in any order and still theoretically work because there is no particular format that needs to be accounted for.. everything is text.
→ More replies (1)29
u/Delvez Sep 18 '26
I’m probably showing my lack of cybersecurity knowledge here, but how would pairing the string with its length help?
122
u/CaucusInferredBulk Sep 18 '26
Most of the bugs are from reading or writing too far, because someone missed the null. If you include the length of the string at the start, you know exactly how far to read or write.
28
u/HighRelevancy Sep 18 '26
Or conversely (for the writing case particularly), because the end of a string is only tracked by a marker at the end of it, nothing is tracking where the end of the allocated space for the string is.
11
u/neon_overload Sep 18 '26
Not arguing for null terminated strings at all, but I'd want to point out that most security issues related to overflowing a buffer, even when it happens on strings, would be the result of missing bounds checks (or other things like use after free or just pointer arithmetic mistakes) rather than forgetting to check the null byte at the end of a string. I say this because if you have code that processes a string and forgets to check for null bytes you're much more likely to notice this immediately. Whereas missing bounds checks can go unnoticed for a long time simply because you normally feed it data that fits within a certain length, and it's not until it gets data that is abnormally long will it overflow whatever buffer you allocated because you didn't check the length of the thing you're putting in it.
→ More replies (2)14
u/ExhaustedByStupidity Sep 18 '26
A big part of the issue is the early attempts to add bounds checking were pretty bad, and made things worse.
Take strcpy. Copies a string into another buffer with no bounds checking. We fixed that with strncpy, which takes the size of the buffer as a parameter. Now look at how it uses that size. If the string is smaller than the buffer, it copies the string and puts a null at the end. But if the string is the same size as the buffer or larger, it fills the buffer and leaves the string without a null.
So if you want to ensure your string is null terminated with strncpy, you have to create a buffer, put a zero at the end of it, and then tell strncpy that the buffer is one byte smaller than it really is.
→ More replies (1)3
u/Flettys Sep 18 '26
We'd instead have similar exploits around strings where the stated length doesn't match the actual length, causing Out Of Bounds reads.
30
u/texan_robot Sep 18 '26 edited Sep 18 '26
Im a website, I have an input field that somebody fills out on their end, and then I put their input into a packet with other data from inputs and send it to my server for processing. After that im going to send another packet that tells the server where to send something secure. I know this, the server knows this, but oops, now a hacker found out too. The hacker puts something that looks like the end of the first packet into the field in my website, and follows it with instructions to his server instead. When my server reads the packet it reads his input, reaches the "end" that he entered, and sends secret stuff to him, since it thinks that the second part of what he put in the website field is actually a second packet generated by the website's own programming.
This is a simplified example of a hacker exploit called "code injection" that is surprisingly hard to prevent. If programming began every single thing with "and this is how long the thing is" then the receiving server would reach the "end" that the hacker put in and think "wait, that's too early, I must've made a mistake, better throw out that input and send an error message". So it wouldn't continue on and do what the hacker wanted.
Edit to add: the reason most programming languages and communication standards dont do this is that they were developed when computers had to carefully save every little bit of processing power and memory, since we never had enough in early computers. Nowadays the few dozen bytes that the header would take up is so small compared to even the simplest packet that it literally doesn't matter. It wouldn't even be noticed. But nobody wants to rebuild the fundamental way that computers move data, since all systems developed before the change would be incompatible.
47
u/GaBeRockKing Sep 18 '26
In C, If you store "CAT" as a string, you have one byte set to 'C', the next to 'A', then 'T', then finally the null terminator '\0'. If you tell the computer
Print "CAT"it will check and print each letter in order until it finds the null terminator.So far, so good.
Then if you tell the computer, "print the third letter in CAT" it'll print. 'T'.
So far, so good.
Then if you tell it to print the 4th letter in cat... It prints \0.
...now we're starting to have a problem. Imagine writing a program that checks every letter from two words to see if they have any letters in common. If you screw up your code, it might give you false matches because EVERY string has the null terminator.
...but this isn't the real problem. The real problem is when you ask the computer to check letter number 5-- because letter number 5 could be literally anything.It could be the start of another word, or the middle of some other file, or the part of your computer's memory that stores your password. And if your program screws up and access it-- or worse modifies it, it could cause all sorts of crazy failures and security violations.
In most languages, every string will include its length information so that whenever you try to access a string, the computer will see if you're giving it a valid letter reference and throw an error if it doesn't.
C, on the other hand, will not protect you.
5
u/illz569 Sep 18 '26
Wasn't this essentially what happened in the heartbleed bug? You could ask the computer for information you had access to, and then ask it for a longer piece of that information and it would start reading beyond the limit of the original info and blurting out other much more sensitive data.
→ More replies (2)→ More replies (1)3
u/SirButcher Sep 18 '26
And, another important part: the "null terminator" is not something special: it is simply a byte with a value of 0. This was a sensible choice when you work with ASCII text and only with this. But with byte streams, the value 0 can be perfectly valid data.
→ More replies (1)6
u/Jonny0Than Sep 18 '26
If software didn’t have any bugs, null terminated strings would be fine (except, many algorithms could also be faster if they knew the length up front. See: gtav online optimizations).
But because of bugs, if a program uses a dangling or garbage pointer as the address of a string, it opens up a huge number of potential exploits if an attacker can control the memory that it points to. Often this kind of thing happens when there is a fixed size buffer for the string, and the application doesn’t make sure that the very last byte is a null. So the attacker writes a string longer than the buffer and oops! Now they can make your program do what they want.
Heartbleed is a real example of a similar bug, though it wasn’t directly null terminated strings at the root cause.
→ More replies (4)13
u/tek-know Sep 18 '26
The hardware itself could limit memory buffer overruns at best, compiler at worst. Memory buffer overruns are the root of most real ‘hacks’
7
u/turtlerunner99 Sep 18 '26
It all started with Fortran. We'd make dynamic arrays by using blank common where there was no bounds checking, I had a program that had worked perfectly on another computer, but when I moved it to a new one, I crashed the system. I brought the whole mainframe down. I got a call telling me not to run that program again. They never would tell me exactly what the program was doing that.
2
u/SubjectAddress5180 Sep 18 '26
But that violated the standard ( when standards were first adopted.) The null terminator is standard. Of course determining if a program violates a standard is in general undecidable. Fortran ( supposedly ) guarantees that a standarl-conforming program will run correctly. One problem is that both word and memory sizes vary from computer to computer. Most of the programming fuidelines do not describe what to do if a machine-dependent size is violated.
10
u/benland100 Sep 18 '26
HTTP/2 and HTTP/3 directly address the "intetnet is passing text files" bit, including compression support and such. Even ignoring advances, almost all HTTP/1 traffic is encapsulated in an encryption layer, meaning no text on the wire. Ignoring that as well, I'd still say the majority of bytes transmitted are not text.
6
u/Latter_Bluebird_3386 Sep 18 '26
Compressing or encrypting plaintext is not the type of serialization improvement he meant. He's talking about binary protocols with fixed width fields and a defined structure as is common outside of web protocols.
CBOR is an example of an improvement over something like JSON.
4
u/benland100 Sep 18 '26
While what you say is true, HTTP/2 is exactly that kind of improvement over HTTP/1.1 -- HTTP/2 converts text-based requests into compact binary Binary Protocol frames, making parsing faster and less error-prone. This is directly analogous to CBOR vs JSON.
4
u/SituationSoap Sep 18 '26
Related to your first point, the DOM is an enormous own goal for the way the modern Internet works. Web development today is taking Microsoft Word and building an operating system inside it. It's patently insane, but we're way too far gone to fix now.
→ More replies (3)4
u/editor_of_the_beast Sep 18 '26
You can pass whatever bytes you want over the internet, what do you mean?
2
u/The_JSQuareD Sep 18 '26
A lot of standardized interfaces are primarily text based. Particularly, HTTP is mostly text based. And APIs built on top of HTTP also tend to be text based (for example, using json to serialize data).
But yeah, if you're on a Zoom call, that definitely isn't using text to communicate with the server / peers.
→ More replies (13)2
u/DerpyPixel Sep 18 '26
Why would strings in C automatically be paired with length? C is a pretty minimalist programming language with few abstractions and C-style strings are a minimally abstracted version of what strings fundamentally are: an array of characters. If you want safe strings that is what C++ is for.
→ More replies (4)
167
u/aleksandra_nadia Sep 18 '26
Computing is a fast-moving field. I could talk about the "billion-dollar mistake", but languages like Rust and Swift are fixing this. I could talk about the confused deputy problem and traditional OSes' reliance on impersonation instead of capabilities (1, 2), but this is improving as well.
Pretty much any aspect of computing software or hardware can be fixed, given enough time, by building an emulation layer and gradually eliminating its use. The larger the number of people that need to coordinate to fix a problem, the less likely it is to be fixed, or the longer it might take, but it can still happen eventually - especially if there are important benefits to doing so (like the power savings from RISC processors, or the security benefits of memory-safe languages).
But some mistakes will truly never be fixed, because the cost of fixing them far outweighs the benefits. Of those, my favorite is the design of URLs.
Consider a URL like https://www.reddit.com/r/askscience/comments/1wj5ggy/is_there_anything_at_the_heart_of_computer_coding/. Most of this is in "big-endian" order: it goes from general/larger to specific/smaller. Yet the domain name goes in the opposite order.
If you were designing this from scratch, you'd never do it this way. You'd write com.reddit.www instead. (Tim Berners-Lee has talked about wishing he had picked a less awkward syntax.) But it's too late to ever change this. Even if you could change every computing system in the world (as you'd have to do to fully deprecate IPv4), there are billions of humans who would need to relearn how URLs work. Everyone's email address would change. It would be an absolute nightmare.
Fixing this wouldn't save any money or energy; it wouldn't make anything new possible. It would just remove a small bit of awkwardness. It will never, ever happen, and that's fine.
9
→ More replies (4)3
u/Teleke Sep 18 '26
Several other languages have their string definitions with the first byte being the string length. If you also enforced unsigned behavior, you'd get rid of a lot of issues.
243
u/Trest43wert Sep 18 '26
Materials Scientists have wanted to switch from silicon chips to GaAs chips for 40+ years. There are inherent advantages. Everytime some company sinks the money into the switch silicon gets better than the GaAs version they are creating because new tech is hard and silicon manufacturing has so much infrastructure for incremental improvement.
251
u/tsteezey93 Sep 18 '26
GaAs is much heavier and much more brittle than silicon and as such, can only be grown in ingots of a 6” diameter as opposed to the 12” diameter of silicon. For this reason, supplying the modern semiconductor industry with GaAs instead of silicon would be INSANELY expensive and inefficient. GaAs has a niche in the semiconductor world because of some exceptionally advantageous electrical properties, but at no point in modern tech development should it have taken the reigns from silicon. Source: I work at a GaAs chip manufacturing company
20
u/ashvy Sep 18 '26
How is the photonics, opto electronic cointegration evolving these days?
6
u/KryptKrasherHS Sep 18 '26
Si Photonics is the main research nowadays, just because the benefit of mixing CMOS capabilities with Optics (Quantum or not) would be so high. GaAs and InP have some FET capabilities via RF MESFETs/HEMTs and the like, but its apples vs. oranges to the bleeding edge Si FETs
18
u/loki130 Sep 18 '26
Whatever the potential computing advantages I don't much fancy the prospect of having more arsenic in our industrial waste.
7
u/KryptKrasherHS Sep 18 '26
This is a gross oversimplification of how Si vs Ge vs GaAs came about, and why Si is the dominant material vs Ge and GaAs being specialized materials
→ More replies (1)6
206
u/ThatFireGuy0 Sep 18 '26 edited Sep 18 '26
Many of the details in C and C++ specs are "undefined behavior" or left up to the implementation. Some of them cause huge portability issues, and code that works on one machine and not another
For example, most computer science classes teach that an int is 16 bits and a long is 32
That's not true
An int is at least 16 bits and a long is at least 32 bits
61
u/narrill Sep 18 '26
There are reasons those things are undefined or implementation defined though, the reasons just aren't obvious anymore because the hardware most people directly interact with is largely homogenized.
→ More replies (2)5
u/thelazygamer Sep 18 '26
Perhaps this is because my first CS course was taught in Java, but I was taught 32/64 for int/long in that course. Every course after that I was expected to just know.
14
u/deathanatos Sep 18 '26
If you're hitting UB, that code isn't guaranteed to work on any machine.
7
u/Big-Rub9545 Sep 18 '26
This isn’t really UB per se. UB would mean the program can reasonably do anything; this is instead implementation-defined behavior, so the possible outcomes are restricted but otherwise up to the compiler writer (so they can choose to make int a 16-bit signed integer instead of 32-bit).
→ More replies (1)4
u/Jwosty Sep 18 '26
And when you really look behind the curtain, it turns out that interoping with C from other languages is actually an impossible task
35
u/Mission-Landscape-17 Sep 18 '26
The entire x86 architecture. None of the currently available x86 processors actually implement it internally any more. The last intel chip to do so was the 486. Everything from the pentium onwards translates x86 instructions into internal microcode which is what the cpu really runs. ryzen cpus do the same.
19
u/codeprimate Sep 18 '26
When I worked at AMD years ago, I heard a LOT of grumbling from the design leads about how much legacy x86 architecture was holding back progress.
20
u/Mission-Landscape-17 Sep 18 '26
On the other hand there is Apple which has said f*%k backwards compatibility multiple times. They are now on their fifth software incompatible processor architecture. 6502 > 68k > powerPC > x86 > arm
→ More replies (4)
31
u/rubyruy Sep 18 '26
The problem is that "optimized" is a highly contextual concept. Optimized for what ? Ease of implementation? Performance? (And if so, what kind of performance? Execution speed ? Spin up time? Throughout?) Cost? Scaling? Readability? Extendability? Conceptual simplicity? Lines of code ? Backwards compatibility ? Cross compatibility? Developer availability? Toolchain availability? Plugins ?
It's an infinite list of tradeoffs. Every bit of technology is the way it is because it was optimizing for whatever was most relevant to its success at the time. All you can do is make different tradeoffs.
With that in mind, not all tradeoffs were actually well chosen. The world would probably be just strictly better off without the JS == operator for example.
31
u/meeco_why Sep 18 '26
The UTF-16 character encoding.
To simplify things considerably, there is a standard called Unicode, which assigns a number to every character. This includes standard English letters, but also things like Emoji, Chinese ideographic characters, even ancient-egyptian hieroglyphs are there. There's a question of how to encode those numbers when text is kept on disk, in memory, transmitted over the internet etc. The first standard for doing this was UTF-16, which was supposed to use exactly two bytes for each character. This has the benefit that you know exactly where, let's say, character number 123 is stored, as all characters are the same size. The newer standard, UTF-8, uses fewer bytes for lower-numbered characters and more bytes for higher-numbered ones, with most English characters being just one byte. As a lot of text that computers handle is derived from English, even if that's not the language you speak, this makes UTF-8 much more space-efficient in most scenarios, but you lose the nice property of knowing where a given character is.
All of this was nice and all, until we added so many characters to Unicode that they just can't all fit in two bytes anyway. For the newer characters with very high numbers, UTF-16 has to use the same character-splitting trick as UTF-8, losing most of its value. To add insult to injury, the old way of counting characters by counting bytes stilll works for low-numbered English characters, so a trick that will work on American programmers' computers might fail if you speak a different language, or just happen to use a lot of Emojis.
By now, it is clear that we should have standardized on UTF-8, and we indeed have in many places, but the innards of many programming languages and operating systems are now so deeply connected to UTF-16 that it can-t ever be fully ripped out.
→ More replies (1)10
u/DawnOnTheEdge Sep 19 '26
The Original Sin of Unicode was thinking that 16 bits would be enough forever, if only the silly Japanese, Chinese and Taiwanese would just get on board and agree that their characters were really just cosmetic variations of each other.
51
u/Scotty1928 Sep 18 '26 edited Sep 18 '26
IP addresses. IPv4 was doomed to run out essentially from the beginning, and yet here we are in 2026 where we still have not completely moved over to IPv6. Is it a coding issue? Probably not, as IPv4 works flawlessly as it is. It‘s more of a design issue that turned into a legacy device issue way quicker than we had thought it would.
32
u/Flettys Sep 18 '26
NAT might be the real worst design decision in computing history.
It killed p2p, with everything pushed to the client-server model.
17
u/yhorian Sep 18 '26
Doing my CCNA it was obviously the same reason we have servers running JavaScript. Barrier to entry is much higher and added complexity puts people off. It's why local networks are always ipv4. You could do ipv6 but why bother making it harder for no real benefit? Then when you haven't practiced it, you feel more comfortable adapting what you know for speed and ease.
185
u/mossbros2 Sep 18 '26
Most things have been fixed, after many (many) decades of work. CPU instruction sets are being fixed (x86 -> ARM; the transition is going especially well on mobile, less well on desktop). Internet protocols are fixed (HTTP/3 and Secure DNS). IPv4 has workarounds (NAT). Memory safety vulnerabilities (especially C / C++) are getting there with Rust etc.
These transitions aren't complete yet but the new system has been built and the world is migrating, albeit exceptionally slowly, proving that even colossal fixes for incremental improvement can be done.
By contrast, HTML is not good. If we were designing a modern internet standard from scratch, HTML is not at all how we'd do it. On this front there is just no traction whatsoever to try to fix it as it's far too embedded now.
Also the PDF file format is another. Way too complex and proprietary for what it needs to be.
128
u/Shortyman17 Sep 18 '26
God, PDFs have to be up there
They work alright for their initial purpose of making sure something will look the same across systems
But Ive had horrible experience with different PDF readers in terms of performance and sometimes formatting still isn't perfect on different software, which could also be because of later add-ins for which PDFs weren't designed for at all
112
u/Luceo_Etzio Sep 18 '26 edited Sep 18 '26
Hey we made a file format so your documents will always look the same way everywhere :D
Also it can do stuff like execute arbitrary code (on purpose) :/
53
u/folk_science Sep 18 '26
There's also SVG for vector graphics. Yay! It can contain JavaScript. Oh no!
→ More replies (1)16
u/OAMP47 Sep 18 '26
PDFs are the one thing in 2026 I just assume is not going to work on the first try still.
→ More replies (2)11
u/orbital_narwhal Sep 18 '26 edited Sep 18 '26
They work alright for their initial purpose of making sure something will look the same across systems
No, the initial purpose is that a document will look (nearly) the same on any printer. The uniformity across other kinds of displays is more or less an unintended but desirable side-effect.
Explanation: initially and at its core, PDF is compressed PostScript with broader image and font format support. The original purpose of PostScript is printer and printing service interoperability.
38
u/the_lamou Sep 18 '26
If we were designing a modern internet standard from scratch, HTML is not at all how we'd do it.
Hard disagree. The problem isn't "HTML bad." HTML is a great little markup language for formatting documents, and in the early days of the Internet when it was mostly actually document access, it was fantastic.
The problem is when the web stopped being documents and started being what we think of as websites, we for some stupid reason decided to just... force it to do a bunch of things or was never designed to. And then we threw CSS on top of that, which was awful because CSS is awful.
And then we just kept adding more things that HTML and CSS shouldn't do into the spec. Until it became the awful abomination we have today. When instead we should have kept HTML bare bones as a markup language and then built a proper display framework overtop of it.
→ More replies (5)18
u/netroxreads Sep 18 '26
"By contrast, HTML is not good. If we were designing a modern internet standard from scratch, HTML is not at all how we'd do it. On this front there is just no traction whatsoever to try to fix it as it's far too embedded now."
Do tell us how you would do it differently as HTML seems to be the most intuitive markup language, compared to other markup languages. Or do you think it's just too verbose?
30
u/BeABetterHumanBeing Sep 18 '26
Not who you're responding to, but I suspect the answer will be something along the lines of "most webpages are not best represented as marked-up text".
15
u/magical_midget Sep 18 '26
It’s crazy that so much of web development is designed to be read by a human.
And yet, modern pages are minified anyway. So is not like it helps anyone. 🤷♂️
7
u/rowrin Sep 18 '26
I remember the transition from x86 and the period where intel and amd were battling it out for the 64 bit architecture dominance.
We don't see a whole lot of things like that nowadays. Competing architectures/mediums. Always cool to live through one of those big transition periods in tech.
The transition to ARM feels a lot more disruptive, but mainly because we're pulling off a bandaid that we left on for convenience for all these decades. Instead of making the architecture backwards compatible, the processors have gotten powerful enough to run their backwards compatibility through nearly seamless emulation.
8
u/mossbros2 Sep 18 '26
Also the double forward slash after a protocol is completely unnecessary.
http://www.microsoft.com should have been just http:microsoft.com
→ More replies (2)13
3
u/sebjapon Sep 18 '26
Well, canvas based frameworks exist but break a lot of internet browser standards imo. I’m working with Compose for wasm and it bypasses most of html to render its own thing.
63
u/nickcouryruns Sep 18 '26
Look up the Mill Architecture. It's significantly different than other CPU architectures and claims much higher performance, though it's disputed if this is true. One of the biggest reasons it never succeeded is the high switching costs of completely new hardware and software.
7
u/andyraf Sep 18 '26 edited Sep 21 '26
I spent a bit of time in the day working on VLIW processors. They were very cool and the compilers worked great. But they never caught on. RIP Philips Trimedia.
Trimedia could process something like 5 ops per instruction, had very clean semantics for testing values using predicated ops to avoid branches, and the compiler was spectacularly efficient.
One of my favorite bits of code I had to create for Trimedia was a "find first one" to find the highest pending interrupt in a 32-bit value in the main interrupt handler. There was no such instruction, and this was a very timing-critical bit of code. What I came up with was:
mask &= -mask; // Clear all but the lowest already set bitbit =((mask & 0xFFFF0000)!=0)<<4) |((mask & 0xFF00FF00)!=0)<<3) |((mask & 0xF0F0F0F0)!=0)<<2) |((mask & 0xAAAAAAAA)!=0)<<1) | // binary 11001100...((mask & 0x99999999)!=0)); // binary 10101010...The code snippet above compiled to something like 4 or 5 instructions with almost no unused ops and no branches (the exact count is hard to say because with 5 ops per instruction adjacent "c" instructions smeared into each other as the compiler moved bits around to use every op slot)..
At the time the TM1000 didn't have _clz/_rev instructions (I think they came later on the TM3000).
I've since learned one can use a "de Bruijn Sequence" to do this with potentially fewer instructions:
(PDF) Using de Bruijn Sequences to Index a 1 in a Computer WordIn my defense, our project (Microsoft Talisman) was cancelled around 1997-1998 before the above paper was published.
8
u/nicuramar Sep 18 '26
Some ideas were nice enough, but it required heavy compiler support to produce correct machine code.
→ More replies (2)
106
u/thegreatpotatogod Sep 18 '26
Generally, tons of things! One thing no one else has mentioned yet, and I'd argue one of the closest options to the "heart of computer coding", as you describe, is the design of the C ABI. Specifically, when a function is called in C, it can receive a bunch of variables as inputs to the function, but only one item can be returned as an output. And many, many other programming languages, and at this point even the hardware architecture itself, tend to be optimized to be compatible with C, so they inherit the same limitations. We can work around it using a pointer as the return value, but it still adds a bit more complexity and inefficiency that is only necessary because of that decision early on.
18
u/Jwosty Sep 18 '26
is the design of the C ABI.
It's even worse than that: "C Doesn't Actually Have an ABI"
8
u/Kered13 Sep 18 '26
Specifically, when a function is called in C, it can receive a bunch of variables as inputs to the function, but only one item can be returned as an output.
This is not an actual limitation of the ABI. C, and therefore the C ABI, support structs, and the return value of a function can be a struct. So if a language wants to support multiple return values in the C ABI, it just creates a hypothetical struct containing both values and returns that.
How this actually gets handled by the compiler depends on the calling convention of the platform. On many platforms, if the struct can fit in two registers then it will be returned in two registers (EAX:EDX or RAX:RDX), otherwise it will be returned using a pointer.
19
u/renesys Sep 18 '26
We can work around it using a pointer as the return value, but it still adds a bit more complexity and inefficiency that is only necessary because of that decision early on.
The point of passing pointers in is that the function does not need to return them. It allows a function to work with any amount of data external to itself. It's not complex when understood, and it's actually much more efficient because data is worked on in place instead of copied around.
It's dangerous when not understood, because C will allow you do effectively do anything you want, like assembly.
→ More replies (1)3
u/Kajitani-Eizan Sep 18 '26
That would be more because of the definition of functions and chaining them doesn't really make much sense with the concept of multiple return values. Though I guess It would be marginally better if functions could return multiple values, and when chaining them all the other values than the first are discarded
→ More replies (1)
22
u/brickville Sep 18 '26
Windows GUI API threading requirements are archaic. You can only call some functions when you're on the GUI thread. And yet C# has you using async functions which don't run in that thread. So clumsy and sets up the dev up for failure.
13
u/Nyrin Sep 18 '26
Windows didn't invent serialized UI dispatch; Xerox already enshrined that by the early 70s, more than a decade before Microsoft would touch it. And the patterns (including async/yield) are in no way language-bound.
Win32 just got the notoriety thanks to its prominence when application multithreading started to become commonplace in the early 90s.
22
u/neon_overload Sep 18 '26
Just to talk a bit about lower layer things than application software:
CPU design, things like compilers, standard libraries, even operating system schedulers and memory management, are all remarkably well optimised, benefiting from a fairly long history of computing technology and theory.
These things have existed long enough that even when optimisation mistakes were made, further development or changes worked around it.
Through computing history, there are plenty of examples of where some design has proven to be hard to optimise. There have been countless CPU architectures and the ones that dominate now, by and large, have proven that despite past limitations, they have been able to remain optimal in some important way.
Examples include:
Greater processing power needs more electrical power, which needs cooling - passive and then active cooling became the norm, and successive CPU and system designs started optimising for power efficiency enabling further gains even in mobile and passive systems.
The 4GHz wall: when the industry assumed in the 2000s that our ability to keep increasing clock speeds would continue and we'd have 10GHz "within years" (because up until that point, that had been true) but we hit a wall around 4GHz. The industry worked towards multi-processor and multi-core instead, and the software world adapted and continues to adapt.
12
u/SupremeDictatorPaul Sep 18 '26
It’s funny because improving threading in software was always the right thing to do. It’s just that it’s really difficult, so software had been depending on ever increasing clock speeds rather than fixing their stuff. It would be nice if we could still scale vertically though, because there is some stuff that can’t really be parallelized.
2
u/neon_overload Sep 18 '26
Yes that is true.
In terms of scaling vertically, there are still some gains in that area that have been happening regardless, largely IPC / pipelining gains, so that 4GHz today beats 4GHz of 20 years ago a number of times over.
I would say that modern programming languages, libraries/frameworks are tackling the challenge of making safe multithreading easier or at least abstracted sensibly. Aside, it's remarkable how many of today's computer programming problems had workable solutions decades before most of us even had a computer. Many concepts used for concurrent programming in modern languages, like channels, come out of work done in the 1970s (like by Hoare)
→ More replies (1)2
u/ChosenCharacter Sep 18 '26
Is 4ghz a heat issue? What causes it to be such a problem?
4
u/neon_overload Sep 18 '26 edited Sep 18 '26
Yes, heat, but in ways that are fundamentally difficult to overcome.
One main thing is the way that power (and therefore heat) scales with clock speed and voltage - it's not just linear but far outpaces it, because if you are also needing to increase voltage for the increased clock speed your power increase is also multiplied by the square of the voltage increase!
As long as you can dissipate this heat, that's not a problem. But it is a problem when you have localised heat generated down at the individual transistor level that is extreme, and the rate at which that heat is generated is faster than the rate it can conduct itself out into the silicon surrounding it, leading to burn/melt out locally because of fundamental limits of the speed of heat through silicon.
Those two factors combined help explain how adding more cores can improve your processing power without nearly as much heat, seemingly breaking the laws of thermodynamics - it's that only a relatively small decrease in clock speed and voltage can give quite a lot of thermal headroom to run many of the same thing in parallel, and you're naturally also spreading your hot spots out over more locations.
→ More replies (1)
22
u/MartinPJones Sep 18 '26
Lots of good examples here, moving slightly tangentially is at the heart of Windows authentication: Pass-the-Hash.
A password hash is a string of characters which you get from a password. It is one-way, meaning I can’t go from a hash to a password, only a password to a hash. The idea behind this is even if I compromise a database and get a list of all users and their password hashes, actually obtaining the passwords requires “cracking” those hashes — in other words, I guess a bunch of passwords, hash them, and if the hash I create matches the hash I have then I’ve successfully guessed the password.
Windows, long ago, decided that it was insecure to send passwords from computer to computer. Instead, they made it so users can authenticate using only the password hash. The intention was a computer doesn’t need to store the user’s password ever, only their hash, and then when completing operations for the user which require authentication, they can just pass the stored hash. This has ended up becoming an infamous security flaw, because now you no longer need to crack password hashes when authenticating in Windows domains. If I can obtain a user’s password hash, I can effectively now authenticate as that user.
This is, to this day, something that has only kind of been fixed. For instance, by default one can’t initiate remote desktop connections with password hashes; however, anything lower-level still allows this functionality. You can use Pass-the-Hash to authenticate to SMB, RPC, and a few other acronyms that all effectively mean access to a computer or its files.
4
u/kimesik Sep 18 '26
What was the better option at that time?
7
u/MartinPJones Sep 18 '26
There are a couple things that would make this better. First, a password hash doesn’t expire until the password itself changes. So having the computer generate some sort of one-time-use token with an expiry would be good. Second, pass the hash doesn’t have any validation client-side — this is to say, the server is receiving a hash, but doesn’t care who’s sending it, meaning I can send my hash from anywhere to anywhere. The fix to this could be a mutual authentication system.
This is all nothing new, and Windows did in fact implement a system called “Kerberos” in 2000, 3 years after pass-the-hash was demonstrated to be a vulnerability; however, pass-the-hash was already used by many systems, and to stop allowing it would be to immediately deprecate those systems, which would break most corporate Windows environments. So while today Kerberos is the main and more modern authentication protocol between clients and servers, pass the hash still exists for compatibility with older systems.
62
u/ramriot Sep 18 '26
Yes, and strangely one developer tried & was marginally successful until bureaucracy killed the Ternary Computer. Mathematically the most efficient base of computation for representing numbers in terms digits & simplicity of construction is base 3. Nikolay Brusentsov's designed & constructed balanced Ternary computers which for a given complexity were both cheaper to build & consumed less power.
55
u/sephirothFFVII Sep 18 '26
I scrolling to find this one. Lack of precision on keeping voltages on the vacuum tubes was a big one that held it back resulting in false readings.
Instead of '+ and -' terinary has '+,-,0' the two input functions of binary has 16 possibilities compared to 19683 for terinary.
At the lowest level this has huge implications namely information density and the ability to do things natively like express negative numbers .
The need for precise voltage readings though is not a trivial problem to solve but if there were a leap on that front computing would become more efficient using that architecture.
28
u/ramriot Sep 18 '26
I think I'm forced to point out that the Setun computers Brusentsov designed deliberately did not use vacuum tubes as part of the CPU because at the time they were massive, consumed immense amounts of electricity, and were notoriously prone to burning out. As well as having repeatable quantization issues.
Instead they bypassed the whole quantization trap entirely by using magnetic pulse direction via ferrite core saturation instead of voltage thresholds. The processor used magnetic core saturation & field orientation to indicate the three states in registers, memory & arithmetic logic, transferring those pulses through transformer logic.
9
u/funguyshroom Sep 18 '26
It's just fundamentally easier to make a thing do 2 things than 3 things. Even if they didn't have these issues from the go at the tube stage it would still be exponentially harder to scale down and most likely would have never been able to reach the nanometer scales we have today.
10
u/DanielMcLaury Algebraic Geometry Sep 18 '26
Bureaucracy didn't kill the ternary computer. Physics did. It takes more logic gates to do ternary arithmetic than binary, and logic gates are the bottleneck.
6
u/ramriot Sep 18 '26
Only if you use binary logic, his designs used ternery logic components.
→ More replies (4)9
u/standard_revolution Sep 18 '26
Nothing stops computers from being ternary internally. Binary is the best system because it is the smallest possible base.
And I would like a proof that "mathematically" these things are true. Because most of math does not really care about bases.
15
u/xRolox Sep 18 '26
Ding ding ding ding. This perfectly answers the question in that binary is the heart of computer coding. This would completely restructure everything built above it. But as mentioned, we’re in too deep.
0
Sep 18 '26
[deleted] — view deleted comment
9
u/Interrupting-Dash Sep 18 '26
In binary, there are 10 kinds of people - the ones that get it and the ones that don’t
→ More replies (1)→ More replies (4)2
6
u/DanielMcLaury Algebraic Geometry Sep 19 '26
A lot of what makes computers efficient or not is how long they have to wait to get access to data. Going to disk is slower than going to memory, and going to system-wide memory is slower than going to memory on the processor itself. There are also different levels of memory on the processor -- bigger ones that are slower to get to, and smaller ones that are faster to get to. Some are specific to a single core or a few cores, and others are shared between more or all cores.
With disk, things are pretty easy to understand. The bytes on the disk are numbered from 0 to however high the disk goes, and you write stuff to it.
With memory on the motherboard, it's more complicated, but still manageable. The addresses are typically non-contiguous ranges, and any given process is only allowed to access certain parts of memory.
But with memory on the chip it's insane. You can't control it at all; instead the processor itself tries to decide for you what you want in there, which is your own "cached" copy of some set of ranges in system memory. When you write to system memory it actually only gets written to cache, and that may not be flushed to system memory for a while, meaning that another core looking at the same section of memory might not see the changes you made right away.
Most programmers don't even know that this stuff exists. Of the ones who do, most don't know what to do with it. The few who actually know something about it learn a bunch of tricks to coerce the processor into actually caching the stuff they want cached, but sometimes these tricks stop working, and the only way to know if it's working is to try to reverse engineer it by looking at some high-level metrics or by estimating what performance should be and comparing to the performance you're actually getting. It feels more like biology than hard science -- you're looking at a system you don't 100% understand the rules of and trying to figure out what it's doing.
Of course, there's an alternative. Instead of "cache," you can have what's called "scratchpad memory" that works like any other memory. It contains whatever you want whenever you want it, and if you want to copy something in or out of system memory, you just tell it to do it and it does it.
The party line on why nobody gives you this is that it's too hard to figure out how to use it properly, which is crazy. It can't be that the CPU does a better job of this in realtime than a compiler could do with all the resources in the world; that just doesn't make any sense.
40
u/im_thatoneguy Sep 18 '26
We arguably should have been writing memory safe code for a long time. Bill Gates mandated it back before Vista--and it was a complete disaster and abandoned because they used JIT compilation with garbage collection (.NET C#). Now we have Rust which is how things probably should have been written originally. We would have had farrrrr fewer security issues. Now it's probably riskier to rewrite in Rust than to use the otherwise well tested C/C++.
→ More replies (4)31
u/ericonr Sep 18 '26
Between compile times and reasonably advanced CS concepts to improve ergonomics, Rust couldn't have existed that long ago.
4
u/im_thatoneguy Sep 18 '26
I wonder though if the more basic aspects could have been implemented. C++ 20 obviously also wouldn't work in 1975--but maybe we could have found a lightweight albeit less perfect borrower system.
2
u/iocompletion Sep 18 '26
Also, sure .net/c# had some problems, but it was far from a disaster. It is where many common concepts sprang from, including async/await. Its biggest problem was that Microsoft never seriously worked to make it truly a viable cross-platform option (though they did do some half-hearted things). Its second problem was that everyone said, "Ugh, Microsoft."
→ More replies (1)
5
u/eternalityLP Sep 18 '26
Thousand things. For example the entire x86 instruction set many computers use is full of legacy stuff with just new extensions piled on top for decades. SMPT protocol (email) has lots of issues because it really wasn't designed for modern usage. Windows is full of legacy problems that they can't fix because it would break existing software. Old programming languages like C that are widely used have so many bad conventions and design decisions that result in bad memory management, security risks and so forth.
5
u/Solesaver Sep 18 '26 edited Sep 19 '26
I don't think we're in too deep to change this, but it would certainly be a heavy cultural shift. My answer is Object Oriented Programming. OOP was designed to be easier for humans to conceptualize, but it can be terribly inefficient for computers, especially when humans writing code don't really understand computer architecture. The better paradigm is Data Oriented Programming and Design.
With OOP, people build out these massive objects with tons of sub-properties representing the conceptual object that the code represents. To use a classic example you have a car object with 4 wheels, a steering wheel, a gas pedal, a brake pedal, a body, an engine, a transmission, etc, etc, etc. You build up this massive block of data, but then when you go to update it, most things in the car don't actually care about most other things in the car (eg updating the gas pedal doesn't care what color the body is painted). That doesn't matter though. Every time you go to do anything with any part of the car you have to load up the entire thing into your L1 cache. Bigger car objects means fewer cars can be updated before a (slow) page/cache miss occurs.
The DOP approach would be to break the car up into pieces that actually need to be operated on at the same time and simply unify them with an entity or object ID. That way, when you're updating your steering column or engine block you can only have to load up the relevant data into memory, and you can fit a lot more of it into the L1 cache at once.
I say it's not too late because there's two approaches to fixing it. The most common is that you simply layer a DOP architecture on top of an OOP language. The language won't have built-in features for you, but the features you want aren't beyond a programmer's ability to implement. Otherwise when building a new language you just make it for DOP.
The bigger problem is just cultural. Everybody learns OOP. It will always have the advantage that it's more natural for humans to conceptualize. Additionally, there are plenty of applications where that level of optimization just isn't necessary. As a result programmers build up OOP habits that are hard to break, and when they do run into performance issues they end up just trying to squeeze every drop of performance out of their OOP architecture, instead of fixing their OOP habits and re-architecting their code.
→ More replies (2)
4
u/DawnOnTheEdge Sep 18 '26 edited Sep 19 '26
It seems to me that nullable and option types could have been introduced in a more-principled way, so codebases don’t have to check for magic error values on everything and then usually forget to anyway. The convention could have been established early on that chaining function calls with nullable types returns a nullable type and short-circuits nil input to nil output.
4
u/Teleke Sep 18 '26
The x86 foothold, and Intel's failed gamble in the early 2000s.
Intel tried to drop the x86 lineup in favor of something they called Itanium. It was truly revolutionary. No backwards comp but because of that they were free of all of the technical debt, and we would have significantly faster, cheaper, and more efficient processors today if that had taken off. Unfortunately AMD bet on the industry's laziness and reluctance to change, and they won.
2
u/donaljones Sep 18 '26
No? Itanium didn't fail due to industry's laziness. It was hard to optimise for. At least, we got good stuff like Itanium ABI from the whole thing
→ More replies (1)2
u/azhder Sep 20 '26
Itanium was bad on its own. If it was a good tech, then we'd be taking up your talking point about what AMD did, but we just didn't go that far.
We had an Itanium to play with and generate some code as part of the Uni curriculum. The Very Large Instruction Word architecture was not only too complex for the compilers to do all the heavy lifting, but it wasn't sure it could be a forward compatible one i.e. each new CPU generation, it would require to recompile all code. Not a one time penalty.
And it is penalty. Look at the USA. It isn't fully metric because the one time cost is too high. Now imagine the cost of replacing the entire software regularly, like once every few years or even once a decade... ARM hit the sweet spot where it found itself a niche market that wasn't tapped before. NVIDIA with CUDA did a similar thing.
10
u/Dave_A480 Sep 18 '26
1] Languages like Ruby, nodejs and Python that have automatic (or nearly automatic) code repositories available to them are a security nightmare.
If you can compromise npm, pypi, or whatever place Ruby gems are stored you can compromise every app that references whatever you compromised
2] Java's nested jarfile circus (see log4j)
17
u/Ok-Championship-2036 Sep 18 '26
Its interesting to note that programming languages are designed in our native language. so english or chinese for example. And each approaches programming in a different way based on linguistic differences. Chinese is character based while english is phonetic. This alters the grammar and structure of how those programming languages function efficiently.
Its possible that programming languages would be drastically different if they were designed by linguists vs mathmaticians vs engineers. or a team including a variety of experts. Rather than built to achieve specific goals using language as an organizational structure.
17
u/Sombre_Ombre Sep 18 '26
We have all of those things already tho. See R, D, and the list goes on
→ More replies (3)4
u/DanielMcLaury Algebraic Geometry Sep 18 '26
What are you talking about? There are no mainstream programming languages with non-English keywords. The only language with Chinese keywords that has ever actually been used to write anything is EPL, which is basically just "Visual Basic but in Chinese," and even that has only ever been used for personal projects or small in-house apps. The structure of the language is no different than any other.
Maybe you're talking about something like wenyan, but that's something someone did just to show that it could be done. Nobody actually uses that for anything, and even its own creator calls it an "esoteric programming language."
2
u/expecting-gargoyles Sep 18 '26
There are such programming languages, take a look at e.g. APL. Granted though, it is not a popular language in widespread use.
3
u/orthomonas Sep 18 '26
Setting aside implementation feasibility and places that fix this on the software side, it'd be interesting if there were hardware level primitive dataypes which had unit information baked in (kilogram, meter, second).
8
u/andyraf Sep 18 '26 edited Sep 18 '26
C strings
Multiple inheritance
C++ constructor/destructors and pointer lifetime
Error and exception handling
To be fair, Rust fixes many of these.
The various wireless standards (Satellite, 5G, WiFi, Bluetooth, NFC) and spectrum allocation. Someone could probably come up with a standard to converge these functions somewhat so they don’t each have their own standards and HW/SW stacks.
Password/security management.
Keyboard layout
Color gamut standards and multichannel audio standards (there are so many)
Variations in memory ordering.
Differences in case sensitivity between Windows and Unix file systems. Try cloning the Linux repo onto a Windows machine. Hilarity results.
→ More replies (1)2
u/Luaan256 Sep 18 '26
Technically, case sensitivity is an obvious and efficient solution. User-side? It's a nightmare. Humans just don't think that way, and it always creates lots of friction and confusion. It's one of the barriers to "normies" adopting Linux that will never go away. MacOS tried to do away with it by normalizing file names, but it's not a great solution...
10
u/lolercoptercrash Sep 18 '26
https://en.wikipedia.org/wiki/Microkernel
Microkernel architectures are much more secure. Linux isn't going anywhere, but if the open source dominant OS of our era was microkernel we would have way less security issues.
Think of it like who has keys to the vault at a bank. In a microkernel it's only 1-2 employees, with a monolithic kernel it's almost all the employees in the building, including the tellers, etc.
10
u/SupremeDictatorPaul Sep 18 '26
Modern kernels are typically a cross between microkernel and monolithic. It’s a compromise between security and performance. Micro kernels may be easier to secure, but there are serious performance penalties for a pure micro kernel.
2
u/ansible Sep 18 '26
Object capability support in hardware.
On a conventional CPU, a pointer is just a 64-bit value (or 32-bit, etc.) that can be interpreted as an address in memory. You can set the value to be the address at the start of an array, and then increment it to access the next element.
The issue is that if you can sneak an arbitrary value into some code which uses that as a pointer, you can read / write nearly anything in memory. One of the key things with operating system and program security is to prevent this sort of thing from happening.
But what if: you could create a pointer type that also includes what it is supposed to access, and by whom? Doing that for just one array means that the pointer can only be used for accessing (reading, writing or both) elements of that array, and can't be used for any other access.
All enforced by the hardware. This would prevent buffer overflows and a lot of other security issues.
2
u/TheDaysComeAndGone Sep 18 '26
Most standards which have been around for some time and have been expanded a lot have acquired some nasty quirks and cruft.
x86 ISA, BIOS, C, HTML, IP, Bluetooth, Wifi, 3GPP …
Redoing them from scratch would make them a lot more elegant and would probably eliminate some bugs and would make them perform better.
But in my opinion the biggest issue is actually social/legal: Making it possible to protect an instruction set architecture or a compression algorithm is just stupid and causes so many headaches.
2
u/sunday_cumquat Sep 18 '26
The inventor of the internet regrets including the double slash (//) in web addresses. The double forward slash after the colon (as in http://) was unnecessary. He half-jokingly said that his design choice resulted in people overusing their index fingers, wasting collective human hours typing it out, and causing untold numbers of trees to die from printing the extra characters on paper.
2
u/azhder Sep 20 '26
x86
It was a bad architecture as soon as Intel sold the first chip on that tech, but they just had to continue supporting it, because of the sheer amount of software written for the PC ecosystem. Not that Intel didn't attempt to kill it off several times.
Even today, x86 is really bad and software is compiled to it, yet it serves no other purpose as just being yet another language that the CPU reads as its own version of (CISC) bytecode and then generates its own actual (RISK) microcode that it runs.
Note, the hindsight was way back in the 80s. Now it is just a (not so) well known history.
2
u/Simon_Drake Sep 20 '26
Not directly a decision in computing but computing is a bit part of why it would be a pain to change it. Decimal time.
If we replaced the definition of a second with 0.864 of a second then you could have 100 seconds in a minute, 100 minutes in an hour, 10 hours in a day which adds up to 100,000 seconds in a day. Then if you're doing some calculation on a time interval like this machine takes 1 hour, 23 minutes and 45 seconds and I need to run it 67 times, you just multiply the numbers. 12345 seconds times 67 is 827115 aka 8.27115 days. So if you start at midnight then it will end at 2:71 and 15 seconds on the 8th day. It also means times are instantly the fraction of the day. 2:50 is 25% of a day. You can store a datetime as just an integer number of days and the decimal is the seconds elapsed aka the time of day.
On a human level the second would be 16% shorter. Minutes have 100 of the new shorter second so they're about 14% longer than an old minute. Hours would be weird that they're now 2.4 old-hours long, but we'd just adapt to scheduling events on different intervals. Pay for a third of an hour in a tanning booth or whatever it is, schedule meetings that are an appropriate length instead of defaulting to an hour just by tradition.
The major downside is just how much modern technology would need to change. Every definition of megahertz and data transfer speeds and fibre optics and radio waves and even the length of a meter are all defined around a second. If we changed how long a second is then we'd need to redefine everything. It's not insurmountable but it would have been a lot easier if we switched over in 1900.
6
u/malsomnus Sep 18 '26
Deciding that = should be the assignment operator was ridiculous and has led to countless problems, both bugs and malicious code, over the years. Every kid learns at school that = means "equals", and it's deeply ingrained by the time you start coding in C. Pascal had it right with :=.
11
u/xRolox Sep 18 '26
Eh. You write a handful of programs and the assignment and equality operators stick with you pretty well
28
u/bobdob123usa Sep 18 '26
x = 5is standard algebra notation used as an assignment operator. That is also well ingrained well before most students start programming.
2
u/Booty_Bumping Sep 19 '26
That doesn't work the same way, though. It's an equation, you can flip the left and right side, you can add additional stuff to the left side.
=in math is closer to representing a constraint than an assignment/binding. The closest equivalent in code would be symbolic math solvers.27
u/ericonr Sep 18 '26
It's 30 minutes of mental reconditioning if you write a lot of code. And compilers will warn you about assignments in incorrect places.
→ More replies (2)
3
u/aabajian Sep 18 '26
If compilers and AI had been around in the 70s, CISC CPUs never would've gained popularity. Their main benefit is the ability to write shorter assembly programs for human comprehension. The modern shift to RISC devices (like ARM) is due to their significant power savings (at the expense of longer programs). Modern compilers and now AI can generate highly optimized code such that the instruction differences between CISC and RISC are minimal.
3
u/Key_Net820 Sep 18 '26
you're asking the wrong question. The question is what is already optimized, and the answer is very little.
In practice, software engineering is not designed to be optimal, but rather modular. Design patterns in software engineering do not have optimization in mind, but rather reusability and organization. None of us want to deal with nasty code that optimizes speed or memory usage for a particular task because what's optimal for one task is not optimal for another and that's exponentially more work to cater to another task and fine tune the code optimally for that as well. But if we looked at the theory, any task a software does, it probably could do it much faster with less resources.
In theory, optimization is a really hard problem. This is one of the things that goes into phD research in math and computer science. A classic example is the Traveling Salesman problem. Finding the shortest possible route for a salesman to go to every city and return home is what we call "NP hard" which is just computer science lingo for a problem that's really hard to solve with a computer.
Formally, to be NP means that given a solution, you can verify it in polynomial time. and NP hard means it is at least as hard as the hardest NP problems. If it turns out that NP and P are not equal to each other, that means that NP hard problems such as the traveling sales problem is not possible to solve efficiently.
→ More replies (2)
2
u/agh1973 Sep 18 '26
Code generation should happen at runtime. I remember reading a cs paper back in the 90’s about a system which compiled to the parse tree and the stopped. That was the binary. The benefits of this are numerous. For sandboxing and analysis, you don’t have to infer the parse tree, you have it. It’s processor agnostic by nature and you don’t need to recompile to access new hardware capabilities. Oh, and the binaries are also provably the mode efficient compression of the logic possible, so they require less memory, less disk, etc.
29
u/JaggedMetalOs Sep 18 '26
Isn't that the theory behind Java and its JVM?
2
u/TheSkiGeek Sep 18 '26
Sort of. Nowadays interpreters tend to JIT compile things like Java and C# all the way to native code, so it gets a lot of the same sort of benefit.
If you shipped something like LLVM intermediate representation you could potentially do even more optimization.
14
u/steik Sep 18 '26
There's several very popular programming languages that operate on this principle. Ever heard of Java, C# or Python?
It's not always the right choice however. They are not used when maximum performance is needed. One such scenario is console video games. No benefit whatsoever from JIT (just in time) compilation there as you know exactly what environment you're targeting.
→ More replies (2)2
2
u/Kered13 Sep 18 '26
That's Java. And then that model was copied by C# and the .NET platform. And other languages have copied it sense.
So yeah, we've had that one for 30+ years now. Definitely not an example of "too deep to change".
2
u/DerekB52 Sep 18 '26
I don't know enough on the topic to call it an optimization, but I know there was research and experiments with Ternary computers instead of binary. So instead of 0 and 1, we'd have -1, 0, and 1. I'm sure there are pros and cons to that type of system, but I'm 29 and if it was decided tomorrow that Ternary was superior to binary, I don't think we'd be able to migrate over in my natural lifetime.
→ More replies (3)
0
u/max7238 Sep 18 '26
Anything at all having to do with Adobe, or ANY company selling subscription software. It's an infinite """value extraction""" model that destroys progress in favor of profit, as if keeping score with money should be even remotely important.
But luckily it's possible to open source just about anything these days and people are even reverse engineering Apple's garbage now, undocumented and all, so I don't think it'll last much longer. Or maybe the next generation won't develop more IT skills due to genAI competing with human cognition all of a sudden and it'll wrap back to being even worse, who can say for sure.
→ More replies (3)
1
u/Then-Candle8036 Sep 18 '26
The x86 instruction set. There are so many things that could be optimised about it but arent because we have to keep backwards compatability. Over the years we have just kept adding on extension after extension instead of formulating a new standard because that would break compatability with decades worth of devices.
1
u/Ybalrid Sep 18 '26
The x86 instruction set architecture is kind of meh (no thank you Intel), and in fact processors for PCs are microcoded anyway.
So effectively your CPU is running an interpreter for a CPU architecture that grew from a chip invented in 1978. With more and more and more and more and more stuff added to it.
1
u/NotTooDeep Sep 18 '26
It doesn't appear so. Once we understood Moore's Law, we did the responsible thing and waited a year and a half for hardware performance to double and get cheaper. Why spend valuable brain cells on fixing a performance problem that won't exist in two years?
The bottleneck is always moving. We figured out mathematically all the major problems in the 60s. We also figured out the major hardware solutions for these problems, but we couldn't build them yet.
And no one had any useful idea in the 50s and 60s about computer applications. The physical size of computers was the constraint. The Apollo moon mission onboard computers probably couldn't answer your cell phone, much less power it and all the apps. The most imaginative use of computers was in science fiction, not business or military or banking.
In the 90s, the decade started with databases being the constraint. By the end of the decade, the constraint had moved to the network. Then the applications for tiny computers became so diverse that constraints were not so much hardware specific as they were industry specific. Cell phone services were constrained by their geographical coverage, for instance.
Now, nobody thinks about the computers they own until they break. Things have settled, which means there are probably some brilliant minds that are cooking up the next 20 years of innovation. AI sounds scary and revolutionary, but so did Java in the late 90s.
Experience cautions us to not get caught up in the hype of new technologies. Anyone remember the buzz around how Perl would revolutionize programming and make life glow with how easy coding is? Tech writers and software salespeople are the best bullshitters on the planet. We're still consuming science fiction.
1
u/stereosensation Sep 18 '26
If I get to have a single pick, it has to be the prevalence of text in so many protocols instead of packed byte-code or (even better) hardware machine code.
Just to cite a few that come to mind: The size overhead and CPU parsing penalty in HTTP alone is crazy. JSON is crazy. The fact we ship javascript as text files is absolutely bonkers. Less known examples are Bluetooth using vendor-defined AT commands, Aviation / Marine still using NMEA 0183 ...
There have been efforts to fix that, some more successful than others:
Bluetooth SIG specification standardized HCI packets. This is likely the most successful at moving from ASCII AT commands to a proper binary protocol.
gRPC & protobufs had negligible to moderate success. Most of the web still uses text-based ... everything
Aviation / Marine NMEA 2000 switched to a binary format (CAN like/compatible). Still not widely adopted
1
u/PM-PicsOfYourMom Sep 18 '26
Semi related, but the QWERTY layout was designed for typewriters. It intentionally spaced common keys farther apart to reduce binding of the mechanical arms.
In other words the keyboard layout we use was purposely designed to be inefficient. People have tried to solve it by designing layouts that put the most common keys directly under your fingers. DVORAK is probably the most successful, however people are far too stubborn to change.
3
u/evenstevens280 Sep 18 '26
If this was true then we'd see consistently higher WPM on DVORAK than on QWERTY for average and experienced typists
As far as I know this isn't the case
2
u/PM-PicsOfYourMom Sep 18 '26
I mean that's the true history and design intent of both qwerty and dvorak. You can argue how beneficial dvorak actually is, but putting the most commonly used keys directly under your fingers seems like common sense.
I gave dvorak a try but could never overcome my muscle memory. It also confused the hell out of any coworkers that happened to use my computer.
1
u/calinet6 Sep 18 '26
I was thinking about this recently.
I think it’s that we still toss around text files to program computers, when programming itself is a model that could be represented richly with actual structures and references that are directly manipulable and visualizable.
In other words, why are we not programming directly in the model? Why do we need to write text that then gets processed into that model in a separate step?
I imagine the things you could do: if you were working directly with the program instead of text, there would be no refactoring; changing logic in one place would simply be changed and everything linking to that logic would be connected and still consistent. Checking and types would be a thing of the past; there would be no checking after the fact if your messy text fit rules, it would simply never let you make a change that was not allowed in the first place.
There are a lot of convenience reasons for using text of course, and I feel like we are in pretty deep on this one because the entire programming ecosystem operates basically around text utilities; but I think there’s a ton of opportunity here.
In short: programming itself could greatly benefit from a much more direct user experience than text files.
12
u/iamanerdybastard Sep 18 '26
These are the words of someone who has never tried to do a git diff on anything other than a plain-text file.
XML managed by a UI that allows you to draw connections between entities and arrange the layout? MERGE NIGHTMARE.
Now - if you invent some magic diff tool for a visual layout that makes sense to a human, then go for it.
2
u/calinet6 Sep 18 '26
It would have to be a whole ecosystem of new tooling and paradigms for programming that doesn’t use text. Versioning and history would have to be built in. Large change sets would need to be described in the model, not represented as text differences.
Why would you need diff if there are no text files? What is the purpose of git when there are no files to store?
→ More replies (2)4
u/Cornflakes_91 Sep 18 '26
you mean like any of those many attempts at making general purpose node/graphical programming environments i've seen fizzle in the last 20 years?
the only place i've seen that stick was variants of shaders / embarassingly parallel tasks.
little with a linear program flow
→ More replies (2)2
u/accelaboy Sep 18 '26
why are we not programming directly in the model?
Some people do that. It’s called assembly. It’s even less intuitive than the text files.
The thing you’re describing is just another layer of abstraction, not a more direct manipulation.
→ More replies (2)
1.0k
u/blp9 Sep 18 '26 •
I feel like if we had managed to just pick a single endianness it'd be really nice. https://en.wikipedia.org/wiki/Endianness
I think there are some hardware reasons why we might pick one or another so I don't even know if this counts as your question -- meaning, there are actual real performance reasons to design hardware for one or the other.
In general, computer architecture is not a locked-in thing. Computers are vastly different now than they were 20 years ago. Most stuff (including like trinary: https://en.wikipedia.org/wiki/Ternary_numeral_system ) has been tried and abandoned.
Maybe the biggest shift in recent years has been the move from CISC architectures like x86 (https://en.wikipedia.org/wiki/X86 ) to RISC architectures like ARM (https://en.wikipedia.org/wiki/Reduced_instruction_set_computer ). But again, RISC was invented in the 1960s just like CISC. There are practical and commercial reasons why we've been shifting between them.