5 ms·
When a program needs memory, the operating system maps a physical page of memory (4KB in most cases) into its virtual memory space. That page might have been i
by jdub 10y ago
When a program needs memory, the operating system maps a physical page of memory (4KB in most cases) into its virtual memory space.
That page might have been in use by a different program only moments before, so the new program could go poking around in it to find interesting stuff. Like SSH keys or passwords or whatever. So the operating system has a responsibility to tidy up pre-loved pages before giving them out.
Once upon a time, filling 4KB with zeroes was a costly operation. It took a bunch of CPU cycles, and worse, would have trashed memory caches closer to the CPU.
So operating systems tend to have queues of discarded pages, background threads to zero them (when nothing more important is happening), and queues of zeroed pages to hand out when a program wants more memory.
This change is DragonFly BSD saying, "Fuck it, we'll do it live". It turns out that with the speed of modern CPUs and the way memory caches work today, they reckon it's faster to just zero the memory synchronously, when the program requests it. No more queues, no more background work, no more weird cache behaviour.
- vardump 10y ago> Once upon a time, filling 4KB with zeroes was a costly operation. It took a bunch of CPU cycles, and worse, would have trashed memory caches closer to the CPU. Even Intel 486 can do that in 50 microseconds. Without cache. Probably in a few microseconds assuming L1 cache. So I wonder if the assumption has ever been true.
- jdub 10y agoI wonder if the acceptance of complexity in page zeroing was more about mapping and zeroing multiple pages… which makes me curious about DragonflyBSD's approach to that, as well as zeroing superpages.
- gumby 10y ago> So I wonder if the assumption has ever been true. This fear went back to the PDP-11 in Unix and even predates Unix. It was true even when disks were really really slow, as CPUs had small or no cache and lacked multiple functional units, much less hardware multithreading. A big PDP-10 mainframe might still have been .7 VAX MIPS -- the first one I programmed's only "high speed" memory was its DTL registers -- core was literally core memory. You can get a feel for what a big deal this was in the fact that it felt radical and expensive for Stroustrup to decide that all new objects would be zeroed. Or you can see in the original posting that there was special memory handling support for special devices -- finally eliminated by this patch!
- vardump 10y ago> You can get a feel for what a big deal this was in the fact that it felt radical and expensive for Stroustrup to decide that all new objects would be zeroed. Or you can see in the original posting that there was special memory handling support for special devices -- finally eliminated by this patch! That's a pretty different issue. Zeroing freshly allocated memory in usermode causes all pages to become committed. Actual zeroing won't take much time, but getting all those pages physically mapped... that's another issue. On memory pressure, that can take arbitrarily long time.
- DSMan195276 10y agoI think that your concern is valid, something that a lot of people aren't aware of, but it probably doesn't really apply in a lot of cases most people deal with. Unless your dealing with entities that take up a page or more, then chances are the rest of the page is being used by something else. If you write to anything in the page, then the entire page has to be committed, and if the page is reused by the allocator then it is also probably already committed. So the chances you can avoid commuting memory for small objects seems likely, and it probably not really worth worrying about. Now, if you're instead allocating large objects, or allocating a large array at one time, then in theory the allocator would get some fresh memory for that large entity (Assuming no piece of memory exists that can fit it). It should be smart enough to know that the OS will give back zeroed memory and avoid zeroing it a second time, so those pages don't have to be committed right away. All that said, if such a thing is actually a worry then you should probably skip the default allocator move to an interface like `mmap()` anyway, which can provide pages of memory that you can be sure are untouched and read as zeros.
- gumby 10y agoThat's right; my point was that the time to zero memory was considered significant overhead regardless of where it occurred. > I think that your concern is valid, something that a lot of people aren't aware of, but it probably doesn't really apply in a lot of cases most people deal with. Unless your dealing with entities that take up a page or more, then chances are the rest of the page is being used by something else. vardump's objection addresses VM pressure, to which you respond. But zeroing objects on allocation is likely to have negative implications on the cache, slightly mitigated only in the case where you immediately initialize nonzero values. RAII can in theory alleviate some of that but I am unaware of any compiler that does this. > All that said, if such a thing [large objects] is actually a worry then you should probably skip the default allocator move to an interface like `mmap()` anyway, which can provide pages of memory that you can be sure are untouched and read as zeros. ... zeroed by the mechanism of this patch!
- cgag 10y agodillon's guess: <dillon> [...] I did a ton of testing. all the pre-zeroing stuff was reducing performance instead of improving it <@dillon> not sure where the crossing point was, but probably somewhere around core-2-duo
- cbsmith 10y agoIt was a big deal for WinNT performance back in the 486 days. I don't remember the numbers, but page zeroing often chewed up a significant amount of CPU time.