821 karma · joined January 8, 2022
Alternate encodings like YCoCg tend to do better.
It is the other way around, shared memory causes Task Manager to _underestimate_ memory usage. Task Manager's default views report the process private working set, no shared memory included. This means that 662MB is the _minimum_ amount of memory commit that would be released by ending the process.
> the OS can overcommit
Windows does not allow overcommit by default. It may compress or optimize memory allocations to reduce the physical working set, but the kernel will start failing memory allocations once physical + swap is exhausted regardless.
Exapunks can be pretty tricky with the distributed nature, which share some similarities with TIS-100. Like Opus Magnum, though, there are no restrictive code size limits, meaning that some puzzles can be solved with brute force masses of code. It's not as bad as Shenzhen I/O where you have to deal both with a tiny MCU and routing.
https://www.audiokinetic.com/en/community/blog/a-guide-for-c...
However, this optimization is less effective on modern CPUs with more powerful indirect predictors using global history.
https://www.reddit.com/r/cpp/comments/1i36ahd/is_this_an_msv...
Similarly, while locking and unlocking memory blocks is no longer generally a concern, most programs still deal with files, and graphics programs still have to call map/unmap functions to access graphics data. All the same tools apply -- helper functions/libraries, RAII, and leak/sanitizer tools to dynamically detect usage errors.
Current versions of the OS ship with functions in MSVCRT.DLL that weren't in the last VC6 version, such as the updated C++ exception handler (__CxxFrameHandler4). AFAIK, there is no redistributable version of it, it's unique to the OS.
The real killer isn't the data operations, though, it's if the overflow checks interfere with converting the loop logic or data addressing to vectorizable form. Indexing with 32-bit signed int vs. unsigned int on a 64-bit platform in C is a classic case -- with unsigned the compiler cannot assume that addressing offsets don't wrap, which then prevents coalescing data accesses into vector loads and stores.
First, regarding application compatibility: the heap was already changed once prior to the segment heap. The Low Fragmentation Heap (LFH) was added in XP and made default in Vista, with applications no longer having to opt into it:
https://learn.microsoft.com/en-us/windows/win32/memory/low-f...
Second, the segment heap has different tradeoffs that make it not a guaranteed win to swap in, it trades off performance for working set:
https://stackoverflow.com/questions/33902068/what-setup-does...
Non-temporal stores are tricky performance wise. They can be dramatically faster than normal stores (~3x), they may be faster on some generations of CPUs than others, they may be slower if subsequent code needs the destination in the CPU cache, and even for GPUs they may not be ideal if an iGPU is sharing part of the cache hierarchy with the CPU. But the worst issue is that occasionally a specific CPU will have some random pathological behavior with them. IIRC, masked non-temporal stores were horrifically slow on some AMD APUs, on the order of hundreds to thousands of cycles per instruction. I find it hard to recommend them much anymore.
There are cases where the quantization method is useful, hashing/binning floats being an example. Standard similarity checks don't work there because of lack of transitivity. But that's fundamentally a different operation than is-similar.
Signed zero and the sign-magnitude representation is more of an issue, but can be resolved by XORing the sign bit into the mantissa and exponent fields, flipping the negative range. This places -0 adjacent to 0 which is typically enough, and can be fixed up for minimal additional cost (another subtract).
It's true that there is no great answer for how to add capabilities and sandboxing after the fact. But what Windows did was build an incredibly restrictive sandbox and then tell everyone who couldn't accommodate even one of the restrictions was "sucks to be you". The result was that developers, when confronted with "all or nothing" for Metro-style apps, were forced to choose nothing. It was also not a good look that Microsoft's own flagship applications like Visual Studio and Office did not show any progress toward adopting UWP, and in the latter case, was specifically exempted from the Windows RT restrictions to continue using Win32 on that platform.
If there had been a better strategy for easing in UWP technology, we might have seen better progress on adoption of Windows Runtime APIs and capabilities so new programs could gradually move toward the new technologies and away from HWNDs. Unfortunately, the technical barriers that were put in place between Win32 and UWP are so large that progress toward breaking them down in the Windows App SDK has been slow.
From the native code side, it was not so great. The .NET 2.0 CLR had very poor support for hosting from the native side and really wanted you to make a program that was .NET first, it didn't work well if you wanted something like primarily a C++ program that hosted a C# UI in the same process. Reverse P/Invoke via native exports wasn't exposed, so creating DLLs for consumption by non-.NET programs was difficult. Mixed mode debugging was and still is painful, with the debugger being glacially slow at some operations like OutputDebugString() processing and blocking some native features like data breakpoints, and the CLR eating access violation exceptions from native code so they couldn't be debugged properly. Build-mode wise, we had to ban C++/CLI assemblies depending on C# assemblies because the C# project system didn't handle incremental builds properly and forced the dependent C++ assembly to rebuild all the time.
These issues still largely exist and are an issue with WPF. It's a great UI framework, but it's unusable unless your front end is primarily a C# program.
These were finally improved for WPF 4, since Visual Studio 2010 switched to it and had a near riot in the betas due to the poor rendering in the text editor.
When I first started porting programs to Windows ARM64, I didn't have an ARM64 device and had to test in QEMU. It ran extremely slowly, probably 1/50th of real time. All UWP programs like Calculator ran like a slug. But which programs still ran reasonably? Classic WinDbg and Task Manager. Two programs that were still plain Win32.
There are significant issues with Win32, namely its lack of a permissions and isolation and lack of hardware acceleration in the old windowing UI (User/GDI). But the idea that Win32 is inherently power inefficient is, IMO, just BS. Its roots go back to CPUs that were orders of magnitude slower than modern CPUs and there is nothing difficult about making a Win32 program that idles at 0% CPU when not in use.
> WinRT (2012) - it (or the embodiment in Windows 8) failed in the market but it also showed both the problem and potential solution to building for new markets while respecting the past
I can't express how wrong this is. WinRT was the most destructive thing that the Windows team ever did to the OS. It drove a hard stake into Windows, splitting it in half and declaring that anything previous to Windows 8, oriented toward desktop, or using primary input through mouse and keyboard over touch was dead. Microsoft basically told all existing Windows developers that if they weren't building a new, touch-oriented, mobile-style app specifically for Windows 8, they didn't matter and wouldn't get any support whatsoever, which is exactly what happened every time they broke existing desktop functionality. Calling this "respecting the past" is a crass insult and taking no responsibility for damaging the Windows development experience and accelerating development away from native Windows apps.
The Huffman decoding implementation is also bigger in production implementations for both speed and error checking. Two Huffman trees need to be exactly complete except in the special case of a single code, and in most cases they are flattened to two-level tables for speed (though the latest desktop CPUs have enough L1 cache to use single-level).
Finally, the LZ copy typically has special cases added for using wider than byte copies for non-overlapping, non-wrapping runs. This is a significant decoding speed optimization.