Tom Bagby wrote: > WRT the line no stuff, I threw out the instance variable manipulation > because I threw everything out. I didn't justify it by benchmarking > just that. Now that I've been playing around without throwing > everything away first, I benchmarked with them, commented them out and > benchmarked without them. It makes a tiny difference, but not even > remotely significant in the current grand scheme of things. In my > fast & dirty version I did make the lines match up and it was a god > damn bitch. Hard to debug too because I ended up making my compiled > version much less human unreadable. > Yeah, I got that. I've removed that from the TODO. > The engine as it stands is currently not far from being able to pre- > render everything. After I posted the "throw all formatting away for > speed" version (which I'm still using in production, but hopefully > won't have to soon), I started thinking about how to get the pretty > formatting version as close to pre-rendered as possible while working > with the restriction of not throwing formatting tricks away just > because they are unfriendly to optimization (like user adjustable > tabulation). > > Pre-rendering the tags is the first step. In doing that, it gets rid > of a lot of the @one_liner_pending situations that make it difficult > to tell if you can merge text. By also pre-rendering end tags, which > is trivial, all the text in the engine is now pre-rendered. Well, > discounting flattened stuff, which I don't deal with because I don't > understand all the rules for handling it nicely. I don't use a lot of > flattened stuff though, and really the vast majority of lines in real > life files will not be flattened, so optimization-wise it's not worth > worrying about much. So that just leaves our nemesis: custom- > tabulation. > > With all these perf patches applied, and then swap the various > tabulating push text calls with call that just shove text right into > _erbout, you pretty much immediately jump to parity with erb. The > only thing preventing just baking the tabs into the strings and > spitting them out is custom tabulation. And I've been wracking my > brains trying to figure out how to get around it. My main idea is to > bake in the regular tabs, and then use the gsub method of inserting > more tabs per line only if custom tabulation has actually been set. > If its zero, just spit the string out. The problem is that a lot of > the overhead is just doing the damn method calls in the first place, > even just to check if custom tabulation is in action. Spitting lots > of _erbout << "Pre-rendered line" into my fast & dirty compiled method > was why it ended up so much faster than erb. I need to think of a > cheap inline way of figuring out if custom tabulation has been > activated to jump to the slow gsub'ing method. > I don't think it's much of a problem to have custom tabulation be a slow-performance special case. It should only be used for very limited spans of text. The first idea that pops into my head for making it work is to redefine "<<" so that it adds extra tabs, then un-redefine it afterwards. I'm not entirely clear on the internals of how Ruby does method stuff, but I believe that shouldn't have a performance impact on stuff outside of the increased tabulation area. > While I'm at it, I'll mention the one other perf bottleneck I'm aware > of: inserting tabulation into everything that comes back from script. > To get the tabulation of partials right (mostly for that), all the > results of script calls have tabulation gsub'ed in at the beginning of > every line. You'll notice if you turn this off and benchmark that a > fair amount of time is spent doing just this. This is the sort of > things that I really feel should be controlled by engine options. > It's easy to turn off and immediately see a boost, but there is no way > of speeding it up and still retain the default Haml "pretty" > behaviour. In a related note, I made some benchmarks that make use of > lots of partial nesting. They obviously suffer from this and the haml/ > erb ratio becomes worse than shown in the standard benchmark. > There'll definitely eventually be an :ugly option that'll turn off all sorts of pretty stuff for the sake of speed. > That's it. You've mentioned wanting to achieve performance parity > with erb with a rewrite/Haml 2.0, I think you are underestimating how > close the engine already is to such a thing, and should be achievable > in the very short term. As far as I can tell, and you can see I've > been monkeying with the guts quite a bit, there's nothing refactoring > won't fix better than any kind of aggressive rewrite. I have a couple > more patches to clean up and post which hopefully bring it to erb > parity (if I am not defeated by handling custom tabs), so hopefully > I'll shortly prove my point with working code :) I'm glad to hear it. I wasn't planning on a rewrite for Haml 2.0... just a fair amount of refactoring and a shift in how Engine works. You may be right that this won't be necessary... I had also planned to also move the prerendered strings out of the method itself, though, which may still be helpful. Even if we do end up prerendering everything, calling "_erbout <<" a bunch involves a bunch of O(n) string concatenation, which I think also causes a pretty major hit (we should, of course, benchmark to make sure when the time comes). But that's something to worry about *after* the rest of the optimizations.
Anyway, I'll add your the latest patch soon. Thanks again for all your work optimizing... speed was Haml's one real downside, and now that's largely going to be a non-issue, thanks to you. - Nathan --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Haml" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/haml?hl=en -~----------~----~----~----~------~----~------~--~---
