--
-- mail from:GoogleGroups "web2py-developers" mailing list
make speech: web2py-d...@googlegroups.com
unsubscribe: web2py-develop...@googlegroups.com
details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Every adapter returns something different for tool, date, datetime, etc. Moreover they return a list of tuples, not objects. We'd like django want db independent objects most of the times.
--
I have not looked on detail and I am not suggesting we do that. If that is the case we should investigate more.
db = SQLAlchemy(app)
class Message(db.Model): __tablename__ = 'message' id = db.Column(db.Integer, primary_key=True) content = db.Column(db.String(length=512))
@app.route('/complete')def complete(): messages = list(Message.query.all()) messages.append(Message(content='Hello, World!')) messages.sort(key=lambda m: m.content) return flask.render_template('template.html', messages=messages)
db = DAL(app, migrate=False, migrate_enabled=False, pool_size=10)
class Message(Model): tablename = 'message' content = Field()
db.define_models(Message)
@app.expose(template='template.html')def complete(): messages = db(db.Message).select().as_list() messages.append(dict(id=None, content='Hello, World!')) messages.sort(key=lambda m: m['content']) return dict(messages=messages)
Yep. Look similar
what's the reason of poolsize=10 ?
This: db(db.Message).select().as_list()may be the culprit because we loop over all the records twice:- select loops over the list of tuples from the db and parses each into a Row object- as_list loops again and converts the Rows of Row objects into a list of dict object.It will be faster if you do b(db.Message).select(cacheable=True)because it will not create additional unused methods for the Row objects.It may be faster without the .as_list()It would be even faster if select had an option to return a list of dict in the first place by using an alternative _parse(…) method.Massimo
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-developers+unsub...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-developers+unsubscrib...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.
just to check-in, I'm not saying that THAT is the root cause but the most probable one.BTW: being 1 req/sec "behind" flask+sqlalchemy is a hell of a result, so take a minute to "kudos yourself".
back on the "probable cause" .... Working with pydal is a breeze because e.g. if you have a datetime Field but on the backend is a datetime-like string, pydal doesn't complain.IMHO (as pointed out many times) the base adapter has TOO many intricacies to deal with each and different backend that SHOULD be moved/overridden in the specific adapter code. e.g. : even if for historical reasons sqlite stores dates as strings, that's not a valid reason for parse() to inspect postgres resultset holding native datetimes inspecting each and every datetime column for every row.parse() is quite "intelligent" for being so generic, but it comes at a cost of basically basically isinstance()ing every value.
Hi, parse() and parse_value() are the bottleneck but also as_list() is not really performing very well.
Il giorno martedì 10 novembre 2015 18:36:28 UTC+1, Niphlod ha scritto:just to check-in, I'm not saying that THAT is the root cause but the most probable one.BTW: being 1 req/sec "behind" flask+sqlalchemy is a hell of a result, so take a minute to "kudos yourself”.
LoL :)back on the "probable cause" .... Working with pydal is a breeze because e.g. if you have a datetime Field but on the backend is a datetime-like string, pydal doesn't complain.IMHO (as pointed out many times) the base adapter has TOO many intricacies to deal with each and different backend that SHOULD be moved/overridden in the specific adapter code. e.g. : even if for historical reasons sqlite stores dates as strings, that's not a valid reason for parse() to inspect postgres resultset holding native datetimes inspecting each and every datetime column for every row.parse() is quite "intelligent" for being so generic, but it comes at a cost of basically basically isinstance()ing every value.Hi, parse() and parse_value() are the bottleneck but also as_list() is not really performing very well.
On my pc, with 100000 records, using psycopg2 I got:
~4s with rows = db(db.tt).select()
~7s with rows = db(db.tt).select().as_list()
By removing '''value = value.decode(self.db._db_codec)''' from parse_value you can save almost 1s
PaoloOk so, a bit of recap:- the code of the test can be better- the parse() method of the base adapter can be optimized considering the real adapter- the as_list() method can be optimized- the decoding can be optimized
Considering all of this, I'm gonna propose now a proposal I was packing lately:1) Refactor adapters completely, making the BaseAdapter something more like a scaffold, and trying to avoid all the if-blocks depending on the engine (since this should be handled by the fact of subclassing the adapter class)
2) Take out all the SQL "strings" into separated classes called 'dialects', so a BaseDialect class and the all the specific dialect classes -> this would make adapters cleaner and split the abstraction levels between operations (adapter) and sql syntax (dialect)3) Optimize the adapter functions on the specific adapters taking advantage of the refactored code allowing more flexibility
If all of you agree, I will work on 1 and 2 and will leave 3 on "more advanced" developers on the single drivers./Giovannithis for the next monthsActually I would like to propose this for the next month