>>> 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. > > Isn't this the motivation behind "#include <iostreams> is hereby > FORBIDDEN?"Yes it is. As I said, I don't like this aspect of the standard streams, but it isn't very related to this problem.>>> 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. > > To some degree. I'd say the bigger issue is that libstdc++-v3 has > put the > buffering behind the virtual calls, causing many more virtual calls > than > necessary. This is a direct consequence of using FILE *.How so? It's entirely possible to use FILE*'s without virtual methods: just don't use iostreams.>> 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. > > What "overhead" are you talking about, specifically? I'm not sure > what you're > getting at here. All buffering necessarily has some overhead.Buffering has overhead from copying data around. It doesn't matter whether you do in by using stdio buffering or by building your own buffers to avoid virtual method 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? > > It's in front of the virtual calls. So you only invoke virtual > calls when the > buffer is full. At that point, you're writing to the file cache at > best or to > disk at worst (or is that to the network?). A virtual call seems a > small > price to pay for the flexibility it provides.How is that different than 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. > > It's more than a few. Do a "grep 'operator<<'" in your C++ > standard include > directory. Arguably we don't need all of those, but we'll need a > lot of them.You only need to define the ones you need, and can do it over time.> It also means developing new manipulators and possibly locale > support if > we want to use it for error messages and the like.Manipulators and locales are two other really ugly things of iostreams :)> What you're talking about is developing a new C++ I/O library, > which is > certainly a worthy goal, but one I'm not being paid to achieve. :)Fair enough. -Chris
On Sunday 19 August 2007 19:34, Chris Lattner wrote:> How so? It's entirely possible to use FILE*'s without virtual > methods: just don't use iostreams.But you lose some flexibility. It may very well be a valid choice, but it needs to be carefully considered. But see below for more on dynamic vs. static polymorphism.> > What "overhead" are you talking about, specifically? I'm not sure > > what you're > > getting at here. All buffering necessarily has some overhead. > > Buffering has overhead from copying data around. It doesn't matter > whether you do in by using stdio buffering or by building your own > buffers to avoid virtual method overhead.Sure. But that has nothing to do with iostreams _per_se_.> >> How is this different than buffering done by stdio? > > > > It's in front of the virtual calls. So you only invoke virtual > > calls when the > > buffer is full. At that point, you're writing to the file cache at > > best or to > > disk at worst (or is that to the network?). A virtual call seems a > > small > > price to pay for the flexibility it provides. > > How is that different than stdio?The virtual calls provide the flexibility to do custom streambufs, which has all sorts of nice encapsulation properties. Now, if I were to redesign iostreams, I would try to turn that dynamic polymorphism into static polymorphism. I think the ability to switch streambufs at runtime is hardly ever used, so we really don't need virtual calls. But maybe we'd have to keep something around for the runtime flexibility to satisfy any current needs. But I've certainly never seen a need for it in real code. One thing I've learned over time is that inheritance and dynamic polymorphism tends to be grossly overused. Most polymorphism is in fact completely static. Some of this current bias towards dynamism reflects the immaturity of template implementations in the late '90's. We're well beyond that level of technology now, however. In any event, the design I've chosen tries to approach the speed of static polymorphism without redesigning the whole library.> > It also means developing new manipulators and possibly locale > > support if > > we want to use it for error messages and the like. > > Manipulators and locales are two other really ugly things of > iostreams :)I haven't dealt with locales, but manipulators are very useful. What they missed was standardizing a way to allow user-defined manipulators with arguments. tr1::functions could help with that in any i/o redesign.> > What you're talking about is developing a new C++ I/O library, > > which is > > certainly a worthy goal, but one I'm not being paid to achieve. :) > > Fair enough.Again, if a group (not just from llvm but crosscutting the C++ community) got together to design a new I/O system I'd be all for it. But I think iostreams gets a worse rap than it really deserves. Yes, there are things in there that makes a modern C++ engineer cringe, but the basic concepts are sound. Some implementations are better than others and this probably reflects areas in which the standard could be improved to more easily get consistency across vendors. -Dave
On Mon, 20 Aug 2007, David Greene wrote:>>> what you're >>> getting at here. All buffering necessarily has some overhead. >> >> Buffering has overhead from copying data around. It doesn't matter >> whether you do in by using stdio buffering or by building your own >> buffers to avoid virtual method overhead. > > Sure. But that has nothing to do with iostreams _per_se_.I'm aware of that.> Now, if I were to redesign iostreams, I would try to turn that dynamic > polymorphism into static polymorphism. I think the ability to switch > streambufs at runtime is hardly ever used, so we really don't need virtual > calls.Right. Overall, go ahead and design your solution. Instead of making abstract arguments we can evaluate the final product and see if it is suitable for wider-spread use in LLVM. -Chris -- http://nondot.org/sabre/ http://llvm.org/