3 ms·
Using sbrk(2) as an application stack seems like a bad idea. A lot of times that is where malloc gets its heap addresses from. The article even says this but n
by asveikau 7y ago
Using sbrk(2) as an application stack seems like a bad idea. A lot of times that is where malloc gets its heap addresses from.
The article even says this but not strongly enough:
> It is worth mentioning that the C library malloc might be using and caching the results of sbrk it may be unwise to mix this trick with your C library malloc, but it is very useful in new programs that you have no intention of using the C library malloc with.
No it is not a good idea to write "new programs" to apply hacky uses of sbrk(2) and conflict with malloc. Any use of sbrk(2) outside of a malloc implementation is pretty suspect as code smell. And you will be hard pressed to find any program or library that doesn't use malloc, short of embedded use cases.
- ShroudedNight 7y agoThe strange thing [to me] is that, in a discussion of stack allocation patterns, sbrk is a deeply confusing red-herring. 'Little-s' stacks require bulk-allocated pages that are then carved up into object allocations as required, and de-allocated in last-in-first-out ordering. No alloca or sbrk required.
- wruza 7y agoNot only malloc, but the entire libc, as no functions in it explicitly guarantee that they do not call malloc and/or mess “your” brk range. You can guess it by what it does and ENOMEM in possible return status, but that is a stupid idea. sbrk is basically a remnant api and is now either an implementation detail of libc memory management or a fool’s crutch [1]. [1] https://opensource.apple.com/source/Libc/Libc-1272.250.1/emulated/brk.c.auto.html https://opensource.apple.com/source/Libc/Libc-1272.250.1/emu...
- asveikau 7y agoYes. Notably stdio typically uses the heap. So I hope this author isn't planning to use printf for New Programs.
- geocar 7y agoI don't, at least not when I care about performance. stdio is a big unknown with highly variable performance across platforms and libc-versions.
- smabie 7y agoSure, yeah but it’s not like using printf is a problem for error messages or logging. Using write() for that kind of stuff is more hassle than it’s worth.
- geocar 7y agoOh it so is! I can’t count the number of times I’ve gotten 20-50x speed ups just turning off logging. Assuming printf is free (or even cheap) is the sort of thing that’ll get you into trouble. It might not always matter, but when it does if your application is parsing strings at runtime at high volume, it’s going to hurt! I rarely log messages anyway, preferring to set state that I can then printout on command (e.g. siginfo)
- jstimpfle 7y agoSo did you just turn logging off, or did you in fact write a better custom implementation? And how much faster did it go? Did you actually measure that? What kind of system was that on? My first thought is, probably there was an fsync() or similar after logging each message. Also, printf() and friends have to lock the streams, so there might be some contention somewhere in case you're multi-threaded. That's not a problem that you can solve without some custom routing of logging messages. Using printf, you can easily write dozens of megabytes of the most complicated formatting code on contemporary systems (I'm just pulling a number out of thin air here). More than any system should want to log.
- geocar 7y agoPeople who deal in megabytes have different problems than people who deal in petabytes. Usually just turn it off. At least at first. Note I’m talking diagnostic here; If I need the log messages obviously I have to write a custom streaming system even if the system printf is fast enough because the API complicates recovery. Printf can also vary in performance by 10msec or more based on the internal state. That’s not good enough since my entire application has a hard limit of around 30msec. I can’t even do one printf — even every N messages (for any N) because I’ll never catch up.
- Reelin 7y agoIt seems like sbrk is a bad idea because it's a legacy API that manipulates global program state in a very error prone manner. Is there ever any reason to use it instead of mmap? More generally, I was very confused by the entire stack section. Why sbrk instead of mmap? Why should C provide special functions for creating or using a stack? Isn't a stack just a region of memory and a pointer into it? Isn't their high performance entirely due to data access patterns that facilitate cache locality while minimizing instruction count and pointer dereferences? I may well have some misconceptions, but if so this article did nothing to address them. Edit: Aha! From the mmap man page: > MAP_STACK (since Linux 2.6.27) > Allocate the mapping at an address suitable for a process or thread stack. > This flag is currently a no-op on Linux. However, by employing this flag, applications can ensure that they transparently obtain support if the flag is implemented in the future. ... some architectures may (later) require special treatment for stack allocations. ...
- Lt_Riza_Hawkeye 7y agoDon't forget MAP_GROWSDOWN > MAP_GROWSDOWN > This flag is used for stacks. It indicates to the kernel virtual memory system that the mapping should extend downward in memory. The return address is one page lower than the memory area that is actually created in the process's virtual address space. Touching an address in the "guard" page below the mapping will cause the mapping to grow by a page. This growth can be repeated until the mapping grows to within a page of the high end of the next lower mapping, at which point touching the "guard" page will result in a SIGSEGV signal.