On Fri, 17 Aug 2007, David Greene wrote:>> Posix is pretty available, what system doesn't have them? > > Windows, for one. If POSIX is ok, it's better in my mind to just directlyWindows has POSIX calls.> use open, write and friends, which is what I do now. Going the cstdio > route should only be done for portability reasons to support non-POSIX > systems.I don't think open/write etc are POSIX. Windows has them but you have to use different headers etc to get access to them. I am no expert in this area though.>>> To get portability and most of the performance I plan to look at >>> unbuffered stdio. >> >> Buffering is goodness, no? > > Buffering is goodness. The problem with using buffered cstdio under > iostreams is that you have to go through overflow() and/or xsputn() to send > data to cstdio.I'm not suggesting using iostreams. I'm suggesting using FILE*'s directly.> These are virtual calls and they will be more frequent because there's > no buffering at the iostreams level. It seems wasteful to do buffering > at two different levels so I'd say it's better to do it before the > virtual calls happen, for performance reasons.I agree. -Chris -- http://nondot.org/sabre/ http://llvm.org/
On Friday 17 August 2007 13:17, Chris Lattner wrote:> On Fri, 17 Aug 2007, David Greene wrote: > >> Posix is pretty available, what system doesn't have them? > > > > Windows, for one. If POSIX is ok, it's better in my mind to just > > directly > > Windows has POSIX calls.Ok, I'll admit I don't know a lot about what's available there. I'm going off previous experience where POSIX was a pain. If that's changed, great!> I don't think open/write etc are POSIX. Windows has them but you have to > use different headers etc to get access to them. I am no expert in this > area though.% man open NAME open, creat - open and possibly create a file or device [...] CONFORMING TO SVr4, SVID, POSIX, X/OPEN, BSD 4.3. [...]> I'm not suggesting using iostreams. I'm suggesting using FILE*'s > directly.Ah. Basically operator<< for FILE*. I don't see a lot of benefit to redefining operator<< for every type just to avoid ostreams. The problem isn't basic_ostream _per_se_. There are two issues we're worried about: 1. The static constructor contortions in place to handle the extremely unlikely case of a static object constructor writing to one of the standard streams. 2. Slowness of std::cout and friends due to their reliance on FILE * buffering and resulting excessive virtual function calls. I just implemented "standard" AsmStreams (the name for my custom streams) to handle the cases where we want to dump Asm to standard error. I just point the AsmStreambuf to STDERR_FILENO. I simply avoid the constructor issue by declaring that no user shall write to an AsmStream in a static object constructor. So we don't have worries about multiple constructor calls at program startup. There is no ios_base::Init equivalent for AsmStream. The second concern is addressed as described earlier. I do the buffering at the AsmStream level to minimize virtual calls. This will still be slightly slower than raw FILE * or POSIX calls because there will be some virtual function call overhead. But it should be much better than standard streams and we get all of the nice benefits of iostreams. Of course, all to be evaluated through benchmarking. -Dave
On Fri, 17 Aug 2007, David Greene wrote:> Ah. Basically operator<< for FILE*. I don't see a lot of benefit to > redefining operator<< for every type just to avoid ostreams. The > problem isn't basic_ostream _per_se_. There are two issues we're > worried about:The problem is basic_ostream and the design of the whole iostreams library. Use of virtual base classes makes every virtual method particularly expensive, for example.> 1. The static constructor contortions in place to handle the extremely > unlikely case of a static object constructor writing to one of the > standard streams.I also dislike this strongly, but it isn't really related.> 2. Slowness of std::cout and friends due to their reliance on FILE * > buffering and resulting excessive virtual function calls.Use of FILE* is not the issue, virtual functions are.> I just implemented "standard" AsmStreams (the name for my custom streams) to > handle the cases where we want to dump Asm to standard error. I just point > the AsmStreambuf to STDERR_FILENO. I simply avoid the constructor issue by > declaring that no user shall write to an AsmStream in a static object > constructor. So we don't have worries about multiple constructor calls at > program startup. There is no ios_base::Init equivalent for AsmStream.This gives you the virtual overhead of streams without the buffering overhead of FILE*. Instead of the buffering overhead of stdio you have your own different but exactly equivalent buffering overhead.> The second concern is addressed as described earlier. I do the buffering > at the AsmStream level to minimize virtual calls.How is this different than buffering done by stdio?> This will still be slightly slower than raw FILE * or POSIX calls because > there will be some virtual function call overhead. But it should be much > better than standard streams and we get all of the nice benefits of iostreams.The only problem you seem to have solved is avoiding having to define a few operator<<'s, this doesn't seem like a very good tradeoff to me. -Chris -- http://nondot.org/sabre/ http://llvm.org/