Live data from Hacker News

The time the x86 emulator team found code so bad they fixed it during emulation

devblogs.microsoft.com

101–110 of 179 posts

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#101
post #97
post #26

Earlier quoted context omitted.

I used to be a graphics card/chip architect for macs in the early/mid 90s - our chips were the fastest, but some programs were resistant because they did stupid stuff: pagemaker invalidated the font cache every time it went thru its main loop, quark with ATM did an n*2 thing every time it wrote text etc etc. We had special hardware to accelerate text drawing and it did nothing because the software pissed it away. We…

What would have been the purpose of stupid code like that? Was it a workaround for things that didn’t fully complete on one iteration, so the devs kept hammering away at it until it worked?

They were most likely just bugs. Quite possibly really stupid bugs.

Not every bug results in the program doing the wrong thing, they often just make the program do the right thing very slowly.

And nobody notices, since it still produces the right result.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#102
post #101
post #97

Earlier quoted context omitted.

What would have been the purpose of stupid code like that? Was it a workaround for things that didn’t fully complete on one iteration, so the devs kept hammering away at it until it worked?

They were most likely just bugs. Quite possibly really stupid bugs. Not every bug results in the program doing the wrong thing, they often just make the program do the right thing very slowly. And nobody notices, since it still produces the right result.

Yes, they were bugs, I think programmers (and their marketing people) were more focused on new features than performance

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#103
post #96

Earlier quoted context omitted.

Why does your fread to anything other than multiplying the two arguments?

The idea of having two arguments to fread() is presumably to be able to do something else than all-or-nothing when there's a short read.

Yes, it divides the bytes read by the element size to get the return value.

Which is the obvious reason you'd pass an element size of 1: you want to know how many bytes were read.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#104
post #79

Earlier quoted context omitted.

That's different: you're talking about the application code, like OP. But I think the parent comment's point is that the issue is in the implementation of fread itself in the standard library. It's perfectly reasonable for an application to pass it 1, 65536 (i.e. one byte, up to 65536 times) and expect it not to issue 65536 separate OS calls.

Is it? I get what you're saying, but asking for 1 byte 65536 times, is indeed different than asking for 65536 bytes, 1 time. There may be reasons, such as when you pull off the end of a buffer, it shifts. And the buffer size is 1 byte. Or 10. Or whatever. No, I'm not saying that's why. I'm simply saying there is a difference between asking for 1 byte or 65k bytes of something. Even dd runs the same under Linux. dd bs…

> asking for 1 byte 65536 times, is indeed different than asking for 65536 bytes, 1 time.

Yes it's different. As others have noted, the difference is what is returned if less than 65536 are available to read in the file: total failure vs partial read.

There is, unsurprisingly, no requirement that it has an unnecessarily inefficient implementation to meet this behavioral requirement. (The C standard doesn't talk about such things as syscalls but, even if it did, it surely wouldn't require such a thing.)

The irony is that that partial read is actually the default on both Windows and Posix (i.e. both ReadFile and read() will read up to the number of bytes specified). So a one-syscall implementation for fread would have been easier than multiple calls, and certainly would be standard compliant.

The dd example isn't comparable because dd is much lower level, and you really are specifying how the syscalls should be made.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#105
post #26

Earlier quoted context omitted.

I used to be a graphics card/chip architect for macs in the early/mid 90s - our chips were the fastest, but some programs were resistant because they did stupid stuff: pagemaker invalidated the font cache every time it went thru its main loop, quark with ATM did an n*2 thing every time it wrote text etc etc. We had special hardware to accelerate text drawing and it did nothing because the software pissed it away. We…

I remember when 24 bit color was exotic and aspirational and you had to settle for 16.

I got the extra vram in my LC to allow for 24-bit color but it was dog slow. The 16 bit data path didn't help. If I wanted it, I'd get things done in 8 bit or mono until it was ready, then switch to 24 bit for the final look.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#106
Loop unrolling is a basic compiler optimization and depending on the machine language and processor instruction set should be faster taking into account all the house keeping required to execute a conditional, jump, move register values etc. This article is missing the analysis of why. If someone didn’t “like” it and was offended then that seems like an equally silly reason. On the surface 256k to init less does seem silly, but what if it was faster?

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#107
post #81

This reminds me of a story from 15 years ago, where I was developing a technology to download games on demand by hooking into the OS calls. There was a particular game that was superslow when this tech was applied. Original game loading took around 15-20 seconds, whereas once the tech was applied it took easily 3-5 min, even with all data already downloaded. When I started digging into it, I realized the reason was t…

Wait, is that wrong? I always call fread as: fread(data, 1, sizeof(buffer), f); with the rationale that I'm interested in reading sizeof(buffer) individual bytes. The buffer size is incidental, not the size of the items I'm trying to read from the file; "read one item whose size is sizeof(buffer)" seems semantically wrong. Is this just the case of Windows having a bad stdlib fread implementation 15 years ago or is my…

fread should be buffered, but different values may cause buffering at different rates. Perhaps it didn't generate 65535 calls to ReadFile but it generated 16 or 64.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#108

SimCity had a read-after-free bug that Microsoft patched in Windows 95. That was a lot easier for customers than having Maxis fix it, which could have required exchanging copies of the game.

There's also the opposite effect, a windows security update broke GTA San Andreas because it relied on undefined behavior. https://silentsblog.com/2025/04/23/gta-san-andreas-win11-24h...

in this dark age of agents writing code that gets debugged by other agents, i love reading stuff like this: stories of human intuition fixing human mistakes. thanks for a fascinating read.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#109
post #69
post #54

Earlier quoted context omitted.

> Which basically expanded back in the day to 65k reads of 1 byte for several MB file. Each fread translated to 65k reads of ReadFile Windows API What software did that that badly? If the code asks for (up to) 65,536 single byte items, why would you split that into 65,536 calls? Also, that change changes behavior. The old call could read anything from zero to 65,536 bytes, the new one only can read zero or 65,536 byt…

A long time ago I worked with someone who read 1 byte at a time from a socket because they insisted data was cached so the kernel was going to batch it magically somehow. It took me days to convince them to measure it.

I used to make it a general rule to start all my optimisation of any network code by running strace and look for excessive read's and write's, because you'd be shocked how many did stuff like that if they didn't know the length of a string, or to read the length first, instead of reading into a buffer.

I had to convince people with benchmarks regularly that, yes, you could write the handful of lines to do proper user-space buffering and trivially run rings around any code that did extra context switches, because a lot of people didn't realise the cost difference between system calls and calling their own functions.

This included, by the way, the MySQL client library, at one point, which would do small read for length fields instead of larger non-blocking reads into a buffer all the time

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#110

This reminds me of a story from 15 years ago, where I was developing a technology to download games on demand by hooking into the OS calls. There was a particular game that was superslow when this tech was applied. Original game loading took around 15-20 seconds, whereas once the tech was applied it took easily 3-5 min, even with all data already downloaded. When I started digging into it, I realized the reason was t…

The most important fix in SP1 for Office 2007 was fixing exactly that in Excel. Doing ridiculous amount of 4 byte reads made it basically unusable on network filesystems.
Post reply on HN