Hi
Sorry, got distracted for a few days...
>> (in list_column_helpers)
>> def render_list_column
>> self.send("column_#{column}")
>> rescue
>> define_render_list_column #create a column override function
>> self.send("column_#{column}")
>> end
>> end
>>
>
> I don't know if it's a good idea. It could break per-request configuration,
> changing form_ui in create and update actions for example,
Hmm, actually I don't think so? In any case the rough proposal is
effectively that we cache the calculation of figuring out how to render
each column - as you say later, there are quite a few ways to achieve
this, this is just one way!
However, to continue this idea a bit further:
- Currently with the ruby VM, calling a function which does not exist
and then "rescue"ing is moderately expensive when the call fails.
However, it's very cheap for every subsequent call when we don't get a
rescue. In comparison checking for the existence of a function before
calling it is less expensive than a rescue, but adds up quite a bit if
we call it every time.
- So the idea was that currently you can override a column format
function by declaring some function "mycol_column", so what we do is
define these for every column it doesn't already exist. Additionally
the icing would be to define it somewhere above the controller class so
that if the user dynamically creates this function in some per-row
config it will override our function. However, if this is not possible
I think it's only a minor tweak to adjust the per_row/per_request
functions to override the newly created functions - one simple solution
would be to define the renderme_column function to literally figure out
the column type for each call (ie revert back to old per call dynamic
rendering)
The big picture here though is that we separate out a library of tight
column rendering helpers (which can still be overridden as per now), but
separate these quite clearly from the function which figures out how we
want to render the column
The current situation is that we run a ton of code to figure out how to
render a column, and then right down in the bowls of that function we
call the render function. This makes for example figuring out how to
add a date format helper quite involved in terms of figuring out how to
hook into this. Instead our algorithm should be to be one pass to
figure out how to render the column, then another pass to run that
render function (much easier to debug and extend)
Now, if you look at the plugins an interesting direction (but possibly
not speedy?) would be to make all datatypes a kind of "plugin" where
each data type (say "Text", "Date", etc) are each given a chance to scan
the list of columns, decide which columns they want to hook into and
claim those columns as their own. It would require some kind of sort
order so that we can prioritise the order plugins can "claim" columns.
This would mean that adding new render's would simply be a case of
adding them into the list of objects which get a chance to scan the col
list and claim columns to render
The interesting bit about this idea is that with some tweaking it could
be made to run at boot time and not per-request. Would need a bit of
thought on how to handle per-request overrides of column rendering
(personally I think it's acceptable to make the user define per-column
renderers to override ours - these can make use of all the built-in AS
code so they can be quite efficient functions and perhaps defined
dynamically)
> Also, what do you think about caching what method call in an attribute of
> column? We should homogenize arguments for overrides and form_ui methods for
> using that.
>
I think we are going down the same path here - the only question is now
best to cache?
I think if we can define procs dynamically then we can implement this in
the fastest possible way. User can then either override our choices, or
we could add a flag which (bizarely) defines the column_render function
to revert to doing some kind of dynamic lookup each time it's run (ie
define something which effectively reverts to the old behaviour!)
> Caching the method for render we can put the logic in other method, and
> method
> which render only should to fill the caching attribute if it's empty
> (caching_attribute ||= method_with_caching_logic) and then use that method.
>
Indeed
I think the big win here is not so much the speed improvement, but the
separation of logic from the rendering implementation - if we get this
right it should become very simple to add new ways to render columns (ie
rendering algorithms, not just overriding that one column)
> I think this is easier to improve, it should be our fist step IMHO, although
> more tests would be useful to avoid regressions with these changes.
>
One easy win is in the area of rendering the action links - I measured
this as something like 10-20% of my overall rendering time on scaffold
with quite a few columns
Additionally I observe that at least current versions of rails ERB have
an apparently brain dead implementation of rendering templates which
seems to do something like straight concatenations of strings, hence
there is a kind of exponential behaviour as the size of partials goes up
and as your partial gets more complex. I saw a very clever trick
implemented in Lua which renders a large bunch of concatenations by
rendering them into an array and then merging that array down as a
series of pyramid concatenations - this reduces the number of memory
allocations to some log2(N) of the normal amount.
The punchline being that if you slightly tweak the partials to remove
whitespace, fold <td></td> onto the same line for short lines, remove
line returns, remove windows \R\Ns (so that the <%- -%> works properly)
then I observe something like a 5% improvement in rendering time JUST by
tweaking the action links partial!
Anyway, the more code we can get out of per-request and into boot time
the better
Cheers
Ed W
--
You received this message because you are subscribed to the Google Groups
"ActiveScaffold : Ruby on Rails plugin" 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/activescaffold?hl=en.