[Nevow] template performance
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible. The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower. The problem is that, I think, there are a lot of objects adaptation. Is it possible to use that same model used by django.template? You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so). As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary. Thanks and regards Manlio Perillo
Just curious. How much slower? Thanks alvin On 12/15/06, Manlio Perillo <manlio_perillo@libero.it> wrote:
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible.
The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower.
The problem is that, I think, there are a lot of objects adaptation.
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Thanks and regards Manlio Perillo
_______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web
-- Alvin Wang
Alvin Wang ha scritto:
Just curious. How much slower?
10 times! manlio@synapsis:~/projects/tests/django$ python static.py 33.58 usec/pass manlio@synapsis:~/projects/tests/nevow$ python static.py 344.71 usec/pass On a Dell Inspiron 6400 with an Intel Duo Core 2 7200 processor. Here is the Python code: import timeit import random from nevow import inevow, rend, loaders COLS = 5 ROWS = 20 class Main(rend.Page): docFactory = loaders.xmlfile("template.xhtml") def data_header(self, ctx, data): return range(COLS) def data_table(self, ctx, data): return [ [random.random() for j in range(COLS)] for i in range(ROWS) ] main = Main() t = timeit.Timer("main.renderSynchronously()", "from __main__ import main") print "%.2f usec/pass" % (10000 * t.timeit(number=1000) / 1000) and the template: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:n="http://nevow.com/ns/nevow/0.1" lang="en" xml:lang=""> <head> <title>Test Nevow performance</title> </head> <body> <table> <caption>RandomTable</caption> <thead> <tr n:render="sequence" n:data="header"> <th n:pattern="item" n:render="string" /> </tr> </thead> <tbody n:render="sequence" n:data="table"> <tr n:pattern="item" n:render="sequence"> <td n:pattern="item" n:render="string" /> </tr> </tbody> </table> </body> </html> Now here is the Django code: import timeit import random from twisted.python import util from django.conf import settings # Ugh! settings.configure(TEMPLATE_DIRS=[util.sibpath(__file__, '')]) from django.shortcuts import render_to_response from django.db import connection COLS = 5 ROWS = 20 def view(): header = range(COLS) table = [ [random.random() for j in range(COLS)] for i in range(ROWS) ] return render_to_response('template.xhtml', {"table": table, "header": header}) t = timeit.Timer("view()", "from __main__ import view") print "%.2f usec/pass" % (10000 * t.timeit(number=1000) / 1000) and the template: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:n="http://nevow.com/ns/nevow/0.1" lang="en" xml:lang="en"> <head> <title>Test Django performance</title> </head> <body> <table> <caption>RandomTable</caption> <thead> <tr> {% for i in header %} <th>{{ i }}</li> {% endfor %} </tr> </thead> <tbody> {% for i in table %} <tr> {% for j in i %} <td>{{ j }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> </body> </html> Regards Manlio Perillo
* Manlio Perillo <manlio_perillo@libero.it> [2006-12-15 11:56:55 +0100]:
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible.
The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower.
The problem is that, I think, there are a lot of objects adaptation.
Can you be more specific about this? What objects are being adapted, and why do you think this is the cause of slowness? -- mithrandi, i Ainil en-Balandor, a faer Ambar
Tristan Seligmann ha scritto:
* Manlio Perillo <manlio_perillo@libero.it> [2006-12-15 11:56:55 +0100]:
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible.
The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower.
The problem is that, I think, there are a lot of objects adaptation.
Can you be more specific about this? What objects are being adapted, and why do you think this is the cause of slowness?
I'm not sure on what's the problem. However if I render this template (without data): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:n="http://nevow.com/ns/nevow/0.1" lang="en" xml:lang="en"> <head> <title>Test performance</title> </head> <body> <p>Some test</p> </body> </html> I got ( 100000 * t.timeit(number=10000) / 10000) ) manlio@synapsis:~/projects/tests/nevow$ python static2.py 9.85 usec/pass manlio@synapsis:~/projects/tests/django$ python static2.py 13.31 usec/pass Nevow for every data object calls inevow.IContainer.child. The problem can be here, since it is called 25 times (the number of rows in the table) Regards Manlio Perillo
* Manlio Perillo <manlio_perillo@libero.it> [2006-12-15 13:33:55 +0100]:
manlio@synapsis:~/projects/tests/nevow$ python static2.py 9.85 usec/pass
manlio@synapsis:~/projects/tests/django$ python static2.py 13.31 usec/pass
Is this python 2.4 or 2.5? The string handling speed-ups in 2.5 have a fairly substantial impact on Nevow rendering speed, I believe.
Nevow for every data object calls inevow.IContainer.child. The problem can be here, since it is called 25 times (the number of rows in the table)
That's easy enough to fix, just don't use data specials :) -- mithrandi, i Ainil en-Balandor, a faer Ambar
Tristan Seligmann ha scritto:
* Manlio Perillo <manlio_perillo@libero.it> [2006-12-15 13:33:55 +0100]:
manlio@synapsis:~/projects/tests/nevow$ python static2.py 9.85 usec/pass
manlio@synapsis:~/projects/tests/django$ python static2.py 13.31 usec/pass
Is this python 2.4 or 2.5? The string handling speed-ups in 2.5 have a fairly substantial impact on Nevow rendering speed, I believe.
Python 2.4. However Python 2.5 should speed up Django, too.
Nevow for every data object calls inevow.IContainer.child. The problem can be here, since it is called 25 times (the number of rows in the table)
That's easy enough to fix, just don't use data specials :)
Right! class Main(rend.Page): docFactory = loaders.xmlfile("template3.xhtml") def render_header(self, ctx, data): def renderRow(data): for i in data: yield tags.th[str(i)] data = range(COLS) return ctx.tag[renderRow(data)] def render_table(self, ctx, data): def renderRow(data): for i in data: yield tags.td[str(i)] def renderTable(data): for i in data: yield tags.tr[renderRow(i)] data = [ [random.random() for j in range(COLS)] for i in range(ROWS) ] return ctx.tag[renderTable(data)] <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:n="http://nevow.com/ns/nevow/0.1" lang="en" xml:lang=""> <head> <title>Test Nevow performance</title> </head> <body> <table> <caption>RandomTable</caption> <thead> <tr n:render="header" /> </thead> <tbody n:render="table" /> </table> </body> </html> manlio@synapsis:~/projects/tests/nevow$ python static3.py 75.71 usec/pass 4.5 times faster! I suspect that using directly flat.flatten is even better but, then, what's the use of the templating system? P.S. Django.template does not escapes string. If I add the filter escape, performance drops from 33.58 usec/pass to 47.16 usec/pass. Regards Manlio Perillo
Manlio Perillo <manlio_perillo@libero.it> writes:
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible.
The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower.
The problem is that, I think, there are a lot of objects adaptation.
How confident are you about that? When I was last playing this game, it seemed to be copying lots and lots of stuff that was the main source of the slowdown, and I got a factor of 2 speedup by dint of a hack: http://codespeak.net/svn/user/mwh/pydoctor/trunk/pydoctor/nevowhtml/__init__...
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
I'm not sure I understand. You can implement IResource.renderHTTP however you like, I guess... Cheers, mwh -- Need to Know is usually an interesting UK digest of things that happened last week or might happen next week. [...] This week, nothing happened, and we don't care. -- NTK Now, 2000-12-29, http://www.ntk.net/
Michael Hudson ha scritto:
Manlio Perillo <manlio_perillo@libero.it> writes:
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible.
The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower.
The problem is that, I think, there are a lot of objects adaptation.
How confident are you about that?
A bit.
[...]
A rend.Page.renderHTTP can build a context from the instance dictionary.
I'm not sure I understand. You can implement IResource.renderHTTP however you like, I guess...
def renderHTTP(self, request): return flatten(self.docFactory, context=self.__dict__) Regards Manlio Perillo
On Fri, 15 Dec 2006 11:56:55 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
First let me say that I really like Nevow template system. Once you became expert with it, it proves to be really flexible.
The problem is the performance. I have done a simple test with the rendering of a table 5 * 20, Nevow against Django, and Nevow is much slower.
The problem is that, I think, there are a lot of objects adaptation.
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Optimization can be a complicated undertaking. I urge you to take a look at the cProfile module included with Python 2.5 or the "lsprof" distribution of the same module for Python 2.4. When you have evidence of a particular bottleneck, please post again. If you have already collected profiling data, please include it whenever you post about performance. Jean-Paul
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 11:56:55 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Optimization can be a complicated undertaking.
I'm not asking for optimization. I'm asking for a possible rewriting of how rend.Page (and flat) works. Regards Manlio Perillo
On Fri, 15 Dec 2006 15:43:44 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 11:56:55 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Optimization can be a complicated undertaking.
I'm not asking for optimization.
You are. You pointed out something which you thought was slow. You suggested a different way to accomplish something much the same. You place greater value on one than the other because of performance reasons. That's what "optimization" means.
I'm asking for a possible rewriting of how rend.Page (and flat) works.
The context is being removed, so that will happen. Since the way you described continues to expose the context as an application level API, I don't think that is how the rewrite will go. Jean-Paul
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 15:43:44 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 11:56:55 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Optimization can be a complicated undertaking.
I'm not asking for optimization.
You are. You pointed out something which you thought was slow.
Well, its a fact (unless my tests are wrong).
You suggested a different way to accomplish something much the same.
I'm not sure if it will be the same.
You place greater value on one than the other because of performance reasons. That's what "optimization" means.
I'm asking for a possible rewriting of how rend.Page (and flat) works.
The context is being removed, so that will happen.
Ok, but how is going this branch of development?
Since the way you described continues to expose the context as an application level API, I don't think that is how the rewrite will go.
I'm talking about a different context. A context that holds data. context = {'table': ..., 'header': ..., 'request': request} return flat.flatten(node, context) Now stan use object adaptation (locate/remember) for obtaing the data requested by a data directive. Regards Manlio Perillo
On Fri, 15 Dec 2006 16:11:46 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 15:43:44 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 11:56:55 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Optimization can be a complicated undertaking.
I'm not asking for optimization.
You are. You pointed out something which you thought was slow.
Well, its a fact (unless my tests are wrong).
I didn't say it wasn't.
You suggested a different way to accomplish something much the same.
I'm not sure if it will be the same.
It's a means of passing objects to different parts of Python code responsible for rendering a template. That's what the existing context code is for. They're basically the same thing.
You place greater value on one than the other because of performance reasons. That's what "optimization" means.
I'm asking for a possible rewriting of how rend.Page (and flat) works.
The context is being removed, so that will happen.
Ok, but how is going this branch of development?
It's not really going anywhere at the moment, presumably because everyone has more important things to work on.
Since the way you described continues to expose the context as an application level API, I don't think that is how the rewrite will go.
I'm talking about a different context.
Um, okay.
A context that holds data.
I don't know what that means. I don't think you can put anything except data into a data structure.
context = {'table': ..., 'header': ..., 'request': request} return flat.flatten(node, context)
Now stan use object adaptation (locate/remember) for obtaing the data requested by a data directive.
There will be no context nor any locate or remember methods in the rewritten system. They are a bad idea, completely independent from performance concerns. Jean-Paul
Jean-Paul Calderone ha scritto:
[...]
I'm talking about a different context.
Um, okay.
A context that holds data.
I don't know what that means. I don't think you can put anything except data into a data structure.
Now Woven/Page context does not contains the data that should be used by a data directive. It contains locate/remember methods so that you register data container from somewhere else.
context = {'table': ..., 'header': ..., 'request': request} return flat.flatten(node, context)
Now stan use object adaptation (locate/remember) for obtaing the data requested by a data directive.
There will be no context nor any locate or remember methods in the rewritten system. They are a bad idea, completely independent from performance concerns.
Ok, this is what i was trying to say. Can you please post an example on how to use the new system? Regards Manlio Perillo
On Fri, 15 Dec 2006 16:41:01 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
[snip]
There will be no context nor any locate or remember methods in the rewritten system. They are a bad idea, completely independent from performance concerns.
Ok, this is what i was trying to say. Can you please post an example on how to use the new system?
The plan is that render methods will take a request and a tag as arguments. There isn't a plan for data factories macro factories. If you look at nevow.page.Element, you will see what the replacement for nevow.rend.Fragment looks like. The replacement for nevow.rend.Page should be somewhat analogous. Jean-Paul
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 16:41:01 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
[snip]
There will be no context nor any locate or remember methods in the rewritten system. They are a bad idea, completely independent from performance concerns.
Ok, this is what i was trying to say. Can you please post an example on how to use the new system?
The plan is that render methods will take a request and a tag as arguments. There isn't a plan for data factories macro factories.
Wait. Does this means that I can no more render a table with the sequence renderer? Should the table be entirely rendered in Python code? I don't like this. One more thing: will macro be supported? Without macros it will be a problem to compose pages, unless I write them entirely in Python (and I *don not* want this). Thanks and regards Manlio Perillo
On Fri, 15 Dec 2006 17:22:46 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 16:41:01 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
[snip]
There will be no context nor any locate or remember methods in the rewritten system. They are a bad idea, completely independent from performance concerns.
Ok, this is what i was trying to say. Can you please post an example on how to use the new system?
The plan is that render methods will take a request and a tag as arguments. There isn't a plan for data factories macro factories.
Wait. Does this means that I can no more render a table with the sequence renderer?
Most likely it does not mean this. Jean-Paul
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 17:22:46 +0100, Manlio Perillo [...]
Wait. Does this means that I can no more render a table with the sequence renderer?
Most likely it does not mean this.
Please, let me understand. How will I (and I should now) render a table using as much XHML code as possible? Regards Manlio Perillo
On Fri, 15 Dec 2006 18:11:11 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 17:22:46 +0100, Manlio Perillo [...]
Wait. Does this means that I can no more render a table with the sequence renderer?
Most likely it does not mean this.
Please, let me understand. How will I (and I should now) render a table using as much XHML code as possible?
Maybe like this: http://twistedmatrix.com/trac/browser/sandbox/exarkun/merit/trunk/merit/reso... I have not explored much further than that yet. If you have any suggestions, feel free to make them. Jean-Paul
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 18:11:11 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 17:22:46 +0100, Manlio Perillo [...]
Wait. Does this means that I can no more render a table with the sequence renderer?
Most likely it does not mean this.
Please, let me understand. How will I (and I should now) render a table using as much XHML code as possible?
Maybe like this:
http://twistedmatrix.com/trac/browser/sandbox/exarkun/merit/trunk/merit/reso...
Ok, thanks. There are some useful patterns. It's very unfortunate that this things are not well documented.
I have not explored much further than that yet. If you have any suggestions, feel free to make them.
I don't (still) know if this will be really useful, but I would like to have something like: class MyPage(page.Element): def __init(self): self.x = {'y': 1} self.x = data(self.x) <p n:render="string" n:data="x.y" /> ==> <p>1</p> For the sequence renderer, the solution used by Django is to "push" the loop variable into the context (used as a stack). The problem is that in Nevow template we can not name this variable. This means that one have to do: <ul n:render="sequence" n:data="list"> <li n:data="@sequence" n:render="string" /> </ul> Regards Manlio Perillo
On Fri, 15 Dec 2006 08:43:44 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote:
Jean-Paul Calderone ha scritto:
On Fri, 15 Dec 2006 11:56:55 +0100, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
Is it possible to use that same model used by django.template?
You pass a context (that is a dictionary usable like a stack: push/pop) to the render function. All the data directive will search the data in the context (like djando, first dictionary lookup, then attribute lookup, and so).
As an example n:data='x.y' ==> ctx['x']['y']. A rend.Page.renderHTTP can build a context from the instance dictionary.
Optimization can be a complicated undertaking.
I'm not asking for optimization. I'm asking for a possible rewriting of how rend.Page (and flat) works.
Re-writing rend,Page and flat to improve execution speed would most certainly be considered optimization. I'm not sure why you think otherwise; could you please explain? Note that I am confident that we'd all like Nevow to be faster, but optimization requires a lot more than just a cursory analysis. I get the impression from reading your post that you think your request is simple/trivial, and perhaps it seems that way, but there is a lot more to this. What you have done, so far, is to measure raw serialization speed, and in so doing, you've found that Django is faster. That part is fine, but the conclusion you've drawn is questionable. Do you know if the difference in speed actually makes any difference in a real web application? I'll bet that other factors, such as database access and network latency generally account for the majority of time that it takes for a request to be serviced. Please understand, I am not trying to offend you or tell you that Nevow doesn't need improving; everyone agrees that it could be a lot better. I am just trying to point out that your observations regarding serialization speed have not been made in a context that demonstrates a serious need to rewrite rend.Page and flat.flatten. Put another way, there are lots of automobiles in the world that go faster than my automobile, but unless my automobile is so slow that it overwhelms all other factors (traffic, for example), I don't really need to fix it, and could better spend my time on other things, like finding a better route to work. Hope this helps, L. Daniel Burr
L. Daniel Burr ha scritto:
[...] Re-writing rend,Page and flat to improve execution speed would most certainly be considered optimization.
Ok, lets consider it an optimization.
Note that I am confident that we'd all like Nevow to be faster, but optimization requires a lot more than just a cursory analysis. I get the impression from reading your post that you think your request is simple/trivial, and perhaps it seems that way, but there is a lot more to this.
My first question was: "Is it possible to use that same model used by django.template?" I have posted my test results only later.
What you have done, so far, is to measure raw serialization speed, and in so doing, you've found that Django is faster. That part is fine, but the conclusion you've drawn is questionable. Do you know if the difference in speed actually makes any difference in a real web application? I'll bet that other factors, such as database access and network latency generally account for the majority of time that it takes for a request to be serviced.
The first test I have done was to compare the two web servers (Nevow + Twisted Web and Django + Lighttpd), obtaining the random data from a database. Again, Nevow was much slower than Django.
Please understand, I am not trying to offend you or tell you that Nevow doesn't need improving; everyone agrees that it could be a lot better. I am just trying to point out that your observations regarding serialization speed have not been made in a context that demonstrates a serious need to rewrite rend.Page and flat.flatten.
I ask again: Nevow uses a lot of object adaptation. Is this really necessary? Regards Manlio Perillo
On Fri, 15 Dec 2006 09:34:07 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote:
L. Daniel Burr ha scritto:
[...] Re-writing rend,Page and flat to improve execution speed would most certainly be considered optimization.
Ok, lets consider it an optimization.
Note that I am confident that we'd all like Nevow to be faster, but optimization requires a lot more than just a cursory analysis. I get the impression from reading your post that you think your request is simple/trivial, and perhaps it seems that way, but there is a lot more to this.
My first question was: "Is it possible to use that same model used by django.template?"
Sure, but you posed that question for a reason. You didn't ask it because you thought it would be fun, you asked it because you found django to be faster, and wanted to use the same technique as django in order to make nevow faster.
I have posted my test results only later.
See above. You wouldn't have asked the question if you didn't want an optimization to be performed.
What you have done, so far, is to measure raw serialization speed, and in so doing, you've found that Django is faster. That part is fine, but the conclusion you've drawn is questionable. Do you know if the difference in speed actually makes any difference in a real web application? I'll bet that other factors, such as database access and network latency generally account for the majority of time that it takes for a request to be serviced.
The first test I have done was to compare the two web servers (Nevow + Twisted Web and Django + Lighttpd), obtaining the random data from a database.
Again, Nevow was much slower than Django.
Ok, that's great. Can you please provide the numbers? What was the concurrency level used?
Please understand, I am not trying to offend you or tell you that Nevow doesn't need improving; everyone agrees that it could be a lot better. I am just trying to point out that your observations regarding serialization speed have not been made in a context that demonstrates a serious need to rewrite rend.Page and flat.flatten.
I ask again: Nevow uses a lot of object adaptation. Is this really necessary?
Please google for posts to this list regarding adaptation and various rendering-speed concerns by one Andrea Arcangeli. In his case, he found Cheetah to be much faster than Nevow, just as you found Django to be much faster than Nevow. The long and short of it is that yes, object adaptation is more expensive that not using any adaptation at all. The real question is, do you care enough to become familiar with the branch in which the context-removal changes are being made, and to help in moving that work forward?
Regards Manlio Perillo
Hope this helps, L. Daniel Burr
L. Daniel Burr ha scritto:
On Fri, 15 Dec 2006 08:43:44 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
What you have done, so far, is to measure raw serialization speed, and in so doing, you've found that Django is faster.
One more thing. This is not only a question Django vs Nevow. If you read one of my previous messages, you will find that using data directives for rendering a table will slow down the rendering by a factor equal to 4.5. Regards Manlio Perillo
On Fri, 15 Dec 2006 09:51:59 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote:
L. Daniel Burr ha scritto:
On Fri, 15 Dec 2006 08:43:44 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
What you have done, so far, is to measure raw serialization speed, and in so doing, you've found that Django is faster.
One more thing.
This is not only a question Django vs Nevow.
I fully understand that. You could have used Cheetah, or Clearsilver, or any of a number of template engines, and found similar results.
If you read one of my previous messages, you will find that using data directives for rendering a table will slow down the rendering by a factor equal to 4.5.
Yes, I understand that too. I will point out that I have *never* used a data directive in any of my applications. I'm not sure why you feel that you need them. The fact that they are going away at some point is a very good thing, in my opinion. Given that data directives are going away, why even worry about this?
Regards Manlio Perillo
Hope this helps, L. Daniel Burr
L. Daniel Burr ha scritto:
[...]
Yes, I understand that too. I will point out that I have *never* used a data directive in any of my applications. I'm not sure why you feel that you need them.
Because I want to write XHTML code as much as possible. This is possible with Djando and it is "fast", why it should not be possible with Nevow?
The fact that they are going away at some point is a very good thing, in my opinion.
If data directive are going away and I will no more be able to write: <table> <caption>RandomTable</caption> <thead> <tr n:render="sequence" n:data="header"> <th n:pattern="item" n:render="string" /> </tr> </thead> <tbody n:render="sequence" n:data="table"> <tr n:pattern="item" n:render="sequence"> <td n:pattern="item" n:render="string" /> </tr> </tbody> </table> I will migrate to twisted web2 + django template, where I can write: <table> <caption>RandomTable</caption> <thead> <tr> {% for i in header %} <th>{{ i }}</li> {% endfor %} </tr> </thead> <tbody> {% for i in table %} <tr> {% for j in i %} <td>{{ j }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> However I want to be sure. Maybe I'm using Nevow in the wrong way. How do you render a table like the one in the example? Thanks and regards Manlio Perillo
On Fri, 15 Dec 2006 10:31:55 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote:
L. Daniel Burr ha scritto:
[...] Yes, I understand that too. I will point out that I have *never* used a data directive in any of my applications. I'm not sure why you feel that you need them.
Because I want to write XHTML code as much as possible. This is possible with Djando and it is "fast", why it should not be possible with Nevow?
The fact that they are going away at some point is a very good thing, in my opinion.
If data directive are going away and I will no more be able to write:
<table> <caption>RandomTable</caption> <thead> <tr n:render="sequence" n:data="header"> <th n:pattern="item" n:render="string" /> </tr> </thead> <tbody n:render="sequence" n:data="table"> <tr n:pattern="item" n:render="sequence"> <td n:pattern="item" n:render="string" /> </tr> </tbody> </table>
You can still have patterns, and you can still render tables.
I will migrate to twisted web2 + django template, where I can write:
<table> <caption>RandomTable</caption> <thead> <tr> {% for i in header %} <th>{{ i }}</li> {% endfor %} </tr> </thead> <tbody> {% for i in table %} <tr> {% for j in i %} <td>{{ j }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table>
I will note that this is most definitely *not* XHTML, so your statement "...want to write XHTML code as much as possible." doesn't make sense. The nevow template would probably pass XHTML validation, but this Django template surely won't, so I don't understand your point. Moreover, you've embedded iteration logic in the Django template, so if some idea of "XHTML purity" is driving you, the the Django approach, while faster, is less pure.
However I want to be sure. Maybe I'm using Nevow in the wrong way.
How do you render a table like the one in the example?
You could do something like this (untested): template.xhtml: <table xmlns="http://www.w3.org/1999/xhtml" xmlns:n="http://nevow.com/ns/nevow/0.1"> <caption>RandomTable</caption> <thead> <tr n:render="headers"> <th n:pattern="item"> <n:slot name="content"/> </th> </tr> </thead> <tfoot/> <tbody n:render="rows"> <tr n:pattern="item"> <td n:pattern="item"> <n:slot name="content"/> </td> </tr> </tbody> </table> from nevow import flat, loaders, page class MyTable(page.Element): docFactory = loaders.xmlfile('template.xhtml') def headers(self, request, tag): headerPattern = tag.patternGenerator('item') columns = [] for i in range(5): header = headerPattern() header.fillSlots('content', i) columns.append(header) return tag.clear()[columns] def rows(self, request, tag): rowPattern = tag.patternGenerator('item') rows = [] for i in range(10): row = rowPattern() cells = [] cellPattern = row.patternGenerator('item') for j in range(5): cell = cellPattern() cell.fillSlots('content', j) cells.append(cell) rows.append(row.clear()[cells]) return tag.clear()[rows] page.renderer(headers, rows) This is one possible way to do it, and it works now, with the current nevow release. Note that the template is generally similar to your original one, and we've kept the looping out of the template. The most important thing is to stop thinking in terms of data types (render="sequence", render="string"), and just write render methods that deal with app-level concepts (headers, rows). An important point to make here, is that the code I provided above is based on the same code used to implement the "sequence" directive, so there is really nothing magical going on.
Thanks and regards Manlio Perillo
Hope this helps, L. Daniel Burr
L. Daniel Burr ha scritto:
[...]
I will migrate to twisted web2 + django template, where I can write:
<table> <caption>RandomTable</caption> <thead> <tr> {% for i in header %} <th>{{ i }}</li> {% endfor %} </tr> </thead> <tbody> {% for i in table %} <tr> {% for j in i %} <td>{{ j }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table>
I will note that this is most definitely *not* XHTML, so your statement "...want to write XHTML code as much as possible." doesn't make sense. The nevow template would probably pass XHTML validation, but this Django template surely won't, so I don't understand your point.
The point is that in the template it should be "visible" the XHTML that will result. As an example, this code: <ul nevow:pattern="sums-container"> <nevow:slot name="elements" /> </ul> <li nevow:pattern="sums-element"> <nevow:slot name="date" /> <nevow:slot name="value" /> </li> <ul nevow:pattern="methods-container"> <nevow:slot name="elements" /> </ul> <li nevow:pattern="methods-element"> <nevow:slot name="method" /> <nevow:slot name="value" /> </li> <div> Wallclock duration totals (seconds) <nevow:invisible nevow:render="totalWallClock" /> </div> give me no clue on how the renderized page will look.
Moreover, you've embedded iteration logic in the Django template, so if some idea of "XHTML purity" is driving you, the the Django approach, while faster, is less pure.
Nevow has a better solution: the sequence renderer. But it will go away.
[...]
The most important thing is to stop thinking in terms of data types (render="sequence", render="string"), and just write render methods that deal with app-level concepts (headers, rows).
An important point to make here, is that the code I provided above is based on the same code used to implement the "sequence" directive, so there is really nothing magical going on.
Ok, but what about reusability? Now for every table (in theory) I have to reimplement the sequence logic. Well, I'm sure that it is possible to write generic/reusable code for rendering tables.
Hope this helps,
Yes, thanks. I will try to use slots instead of data. P.S. How tested/stable is the new(?) page module? Regards Manlio Perillo
On Fri, 15 Dec 2006 12:34:53 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
The point is that in the template it should be "visible" the XHTML that will result.
As an example, this code:
<ul nevow:pattern="sums-container"> <nevow:slot name="elements" /> </ul> <li nevow:pattern="sums-element"> <nevow:slot name="date" /> <nevow:slot name="value" /> </li>
<ul nevow:pattern="methods-container"> <nevow:slot name="elements" /> </ul> <li nevow:pattern="methods-element"> <nevow:slot name="method" /> <nevow:slot name="value" /> </li>
<div> Wallclock duration totals (seconds) <nevow:invisible nevow:render="totalWallClock" /> </div>
give me no clue on how the renderized page will look.
Sure, but that is nothing like the example I provided you. In my example, it is clear that the header row contains 1 or more th elements, and that the tbody element will contain 1 or more tr elements, each having 1 or more td elements. I agree that your example above doesn't read as clearly, but I'm sure you can write that in a style similar to what I used for the table example.
Moreover, you've embedded iteration logic in the Django template, so if some idea of "XHTML purity" is driving you, the the Django approach, while faster, is less pure.
Nevow has a better solution: the sequence renderer. But it will go away.
The sequence renderer is basically doing the same thing as the code I used in the "headers" and "rows" methods. We aren't talking about some large class/function that is complicated to reproduce. Adding a sequence renderer that complies with the upcoming changes to nevow is not going to be difficult. Even if no direct substitute is provided, nothing is stopping you from adding your own, or better yet, being the person to contribute a new sequence renderer. I think it would be a good thing to do.
[...] The most important thing is to stop thinking in terms of data types (render="sequence", render="string"), and just write render methods that deal with app-level concepts (headers, rows). An important point to make here, is that the code I provided above is based on the same code used to implement the "sequence" directive, so there is really nothing magical going on.
Ok, but what about reusability? Now for every table (in theory) I have to reimplement the sequence logic.
See above. The existing sequence renderer is just a few lines of code, not a magical entity. Why reimplement it for each table?
Well, I'm sure that it is possible to write generic/reusable code for rendering tables.
Absolutely. The code I provided in my example *is* a generic table element, that you could stick in any page. Just add some methods for querying your DB and you have a reusable element, that will render arbitrary data in tabular format.
Hope this helps,
Yes, thanks. I will try to use slots instead of data.
Slots are a good solution, because they work today, and will allow you to switch to the context-less version of nevow when it is released, without any major breakage.
P.S. How tested/stable is the new(?) page module?
I have used page.Element in a production environment for months now. I switched from using rend.Fragment to page.Element as soon as it was available, and things have worked perfectly, at least for me.
Regards Manlio Perillo
Hope this helps, L. Daniel Burr
L. Daniel Burr ha scritto:
On Fri, 15 Dec 2006 12:34:53 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
P.S. How tested/stable is the new(?) page module?
I have used page.Element in a production environment for months now. I switched from using rend.Fragment to page.Element as soon as it was available, and things have worked perfectly, at least for me.
One more question: is formal compatible with page.Element? Thanks and regards Manlio Perillo
On Sat, 16 Dec 2006 03:31:53 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote:
L. Daniel Burr ha scritto:
On Fri, 15 Dec 2006 12:34:53 -0600, Manlio Perillo <manlio_perillo@libero.it> wrote: [...]
P.S. How tested/stable is the new(?) page module?
I have used page.Element in a production environment for months now. I switched from using rend.Fragment to page.Element as soon as it was available, and things have worked perfectly, at least for me.
One more question: is formal compatible with page.Element?
Not at this time. As far as I know, formal is still using rend.Fragment for its Field and Group objects, among other things. Changing formal to use page.Element is not terribly difficult, but somebody would need to see if the formal developers are interested in changing at this time. I think formal will be more likely to change once the context-removal work is actually finished in nevow; until then, I doubt there is any real urgency.
Thanks and regards Manlio Perillo
L. Daniel Burr
participants (6)
-
Alvin Wang
-
Jean-Paul Calderone
-
L. Daniel Burr
-
Manlio Perillo
-
Michael Hudson
-
Tristan Seligmann