Prolog: optimizing global structures for performance -
Prolog: optimizing global structures for performance -
i have written prolog programme , trying optimize performance (yes, utilize case needs it).
first background on how programme structured, know i've been.
the scheme keeps client (user) orders in logic base, dynamically asserted logic base of operations come in (and dynamically removed 1 time processed using retract). orders structured so:
order(regionid, userid, userbalance, orderid, productid, price, ...) . order(regionid, userid, userbalance, orderid, productid, price, ...) . ... order(regionid, userid, userbalance, orderid, productid, price, ...) .
i liked fine, during testing, populated scheme 50,000 orders , found took inordinately long process (on order of few minutes - needed better). profiled , found time spent going through logic base of operations scooping orders processing, decided seek scheme.
this makes sense because particular users tied particular regions:
order(regionid, [ (userid, userbalance, orderid, productid, price, ...), (userid, userbalance, orderid, productid, price, ...), ...]) . order(regionid, [ (userid, userbalance, orderid, productid, price, ...), (userid, userbalance, orderid, productid, price, ...), ...]) . ... order(regionid, [ (userid, userbalance, orderid, productid, price, ...), (userid, userbalance, orderid, productid, price, ...), ...]) .
what doing here storing long list of user orders each region. test this, made lists within order structures 50,000 in length (50,000 orders). performed much improve original scheme in processing orders (25% - 30% of original time); in adding orders system, performs much worse @ to the lowest degree order of magnitude if not more.
the order adding procedure quite simple. retract order construction instantiated regionid, reassert additional order tacked on head (something this):
retract( order(california, oldorders ) ). assert ( order(california, [ neworder | oldorders ] ) ).
i have presumed reasonably fast i'm adding head, isn't. guess there lot of copying of long list going on behind scenes.
my question how optimize more speed. may suggest different structuring of data, different algorithm, different mechanism storing stuff (i know assert/retract, different prologs may have more exotic mechanisms?), or whatever want. maintain in mind suggestions, don't want go backwards on order processing (vs. adding).
i using eclipse (the prolog, not ide), switch xsb, yap, or other free prolog if suggestion requires it. note need stick faster prologs rather slower ones swi.
thanks suggestions.
i think principal problem you're not benefiting indexing because order processing queries begin user id instantiated , not first argument of term. you're doing query 2 or 3 of these arguments instantiated, prolog able winnow downwards instances of order/n
have same part id based on argument order.
for fun, might seek flipping things around so:
order(userid, regionid, userbalance, orderid, productid, price, ...) .
or even
order(orderid, userid, regionid, userbalance, productid, price, ...) .
and see effect alternatives have on performance. (i might wrong; eclipse 1 know to the lowest degree about.) prologs index on first argument in absence of other information. don't know if eclipse has index declaration swi, in case of swi, used able like:
:- index(order/7, [1,2]).
(assuming 7
right arity) , index on first 2 arguments plenty improve "scoop up" time. nowadays ignored , a much more complex scheme used instead might mean see performance benefits trying in swi. might worth look, since open it. eclipse may have similar this.
as portable option, can build own indexes using term_hash/2
. i've never used alternative myself. basic thought understand bundle values might query on in single term , generate hash term, , utilize build new relation hash value first argument. suspect alternative (untested):
:- initialization rebuild_index/0. :- dynamic order_by_order_id_and_user_id/2. rebuild_index :- order(orderid, userid, ...), term_hash(order(orderid, userid), hash), assertz(order_by_order_id_and_user_id(hash, order(orderid, userid, ...)). find_order_by_order_id_and_user_id(orderid, userid, order) :- term_hash(order(orderid, userid), hash), order_by_order_id_and_user_id(hash, order).
this of course of study work if prolog going generate indexes dynamic predicates.
if using swi-prolog (politely) suggest moving database rdbms , using odbc interface query it. it's much easier optimize performance in database (i'd rather issue create index orders_by_order_id_and_user_id on orders (order_id, user_id)
, see performance "magically" improve have write bunch of boilerplatey access code above) , benefit of rdbms "integration technology" rather persistence/storage technology. don't know if other prolog's have similar capabilities accessing databases.
whatever find out works, please come , submit answer, think we'd benefit knowing little bit more performance ramifications of various alternatives.
performance prolog
Comments
Post a Comment