Swi-Prolog database performance

690 views
Skip to first unread message

idinatas

unread,
May 7, 2014, 5:45:59 AM5/7/14
to swi-p...@googlegroups.com
Hi list,

I have a few questions I've been wanting to ask for a long time, about the
performance hit from using the assert/retract family of predicates.

The Swi documentation (section 4.13) has this to say:

As facts and clauses asserted using assert/1 or one of its derivatives become
part of the program, these predicates compile the term given to them.
retract/1 and retractall/1 have to unify a term and therefore have to
decompile the program. For these reasons the assert/retract mechanism is
expensive. On the other hand, once compiled, queries to the database are
faster than querying the recorded database discussed below.

My first question is, what exactly is the cost of assert/retract? How
expensive is that mechanism?

Next: what are the alternatives? Is it possible to compile a predicate without
compiling the whole program? If so, is it more economical to limit database
manipulation to assert operations, avoiding retract ones as much as possible?

Also: are the costs so high that one would get significant gains by using a
different relational database, eg a SQL database, to read from and write terms
to during execution?

And finally: by Clocksin & Mellish, findall, setof etc are implemented using
assert/retract. That must mean that such predicates also incur the costs
discussed above. Is that correct?

Thank you all in advance for any answers- I've googled far and wide for an
answer to my questions before getting the courage to ask them here.

Kind regards,
Stassa

Michael Hendricks

unread,
May 7, 2014, 11:49:11 AM5/7/14
to idinatas, swi-p...@googlegroups.com
Hi Stassa.  Welcome to the list.

It's a good question.  I've answered inline below.

On Wed, May 7, 2014 at 3:45 AM, 'idinatas' via SWI-Prolog <swi-p...@googlegroups.com> wrote:
My first question is, what exactly is the cost of assert/retract? How
expensive is that mechanism?

I put together a quick benchmarking program to find out.  You can see the source at https://gist.github.com/mndrix/eb86e6679d6c25720eff

On my system, assert/1 is about 50% slower than record/2 (1500 ns vs 1000 ns).  To my surprise, it's 25% faster to call retractall/1 than it is to call erase/1 for recorded facts (5500 ns vs 6900 ns).  If we had an eraseall/1 predicate, it'd probably be faster.
 
Next: what are the alternatives? Is it possible to compile a predicate without
compiling the whole program? If so, is it more economical to limit database
manipulation to assert operations, avoiding retract ones as much as possible?

I try to avoid assert/retract and record/erase if possible.  By using plain Prolog data structures to track my data, I often get cleaner code and excellent performance.  If that's not possible, you could try flag/3 which is 35% faster than record (730 ns), although the semantics are quite a bit different.

Another possibility is to place a Prolog data structure in a global variable.  I consider this more of a hack than a good idea.  It also has different semantics on backtracking.  However, it gives you "assertions" that are roughly as fast as record/2 (1300 ns) and gives you erasure almost for free (0 ns).
 
Also: are the costs so high that one would get significant gains by using a
different relational database, eg a SQL database, to read from and write terms
to during execution?

You'll probably have to measure your specific configuration to know for sure.  There are substantial variations between databases and across networks.

A fast, local key-value store like LevelDB might also be an option.  I'm not aware of any existing bindings for SWI Prolog though.
 
And finally: by Clocksin & Mellish, findall, setof etc are implemented using
assert/retract. That must mean that such predicates also incur the costs
discussed above. Is that correct?

findall and friends use an internal data structure written in C (see src/pl-bag.c in the source code) so I suspect they're much faster than an implementation built on assert/retract.

I hope that helps.

-- 
Michael

Stassa Patsantzis

unread,
May 7, 2014, 6:00:40 PM5/7/14
to swi-p...@googlegroups.com, idinatas
Hi Michael,

Thank you for your very useful information and also for the benchmarking code, I believe I'll find it useful.

I try to avoid assert/retract and record/erase if possible.  By using plain Prolog data structures to track my data, I often get cleaner code and excellent performance.  If that's not possible, you could try flag/3 which is 35% faster than record (730 ns), although the semantics are quite a bit different.

I usually manage without assert/retract also. Recently though I wanted to store a large number of compound terms that represent data associated with points on a three-dimensional grid, for a puzzle. Previously, I would put them all in a list and scan it repeatedly. The problem is that once you have more than a dozen terms or so in a list like that, it becomes rather cumbersome and a pain to debug. So I thought I could take advantage of Swi's indexed database and assert my point-terms with an extra first argument for a hash and retrieve them directly from the database as needed. I think that's faster than scanning a list but if the cost of asserting/retracting counters that speedup then there's no, er, point in it.

flag/3 is OK for smaller facts, it doesn't seem easy to use here. I've given record/erase a try, but the documentation warns that assert/retract is faster once compiled and I didn't go too far with it. 

Another possibility is to place a Prolog data structure in a global variable.  I consider this more of a hack than a good idea.  It also has different semantics on backtracking.  However, it gives you "assertions" that are roughly as fast as record/2 (1300 ns) and gives you erasure almost for free (0 ns).

I'm very reluctant to use global variables.

You'll probably have to measure your specific configuration to know for sure.  There are substantial variations between databases and across networks.

Agreed, I'll have to do quite a bit of testing. It's useful to know what others' experience is also.


A fast, local key-value store like LevelDB might also be an option.  I'm not aware of any existing bindings for SWI Prolog though.

Mmmnyeah. That sounds like a bit too much work at this point :)


findall and friends use an internal data structure written in C (see src/pl-bag.c in the source code) so I suspect they're much faster than an implementation built on assert/retract.

Thanks- I'm running out of excuses for not looking at the Swi sources.

Thank you for your help, Michael. Much appreciated.

Cheers!
Stassa

Stassa Patsantzis

unread,
May 7, 2014, 6:02:24 PM5/7/14
to swi-p...@googlegroups.com, idinatas
btw:

53 ?- number(1_000).
true.

54 ?- A is 1_000 * 2.
A = 2000.

I caught that in your github repo and it looked terribly wrong, but it's perfectly correct.I had no idea. Thanks.

Jan Wielemaker

unread,
May 8, 2014, 4:31:07 AM5/8/14
to Stassa Patsantzis, swi-p...@googlegroups.com
Michael, Stassa,

Good to do some timing :-) Note that the timings may depend a lot on
the size and structure of the terms. I wouldn't rule out global
variables that quickly. They can be quite nice.

On 05/08/2014 12:00 AM, 'Stassa Patsantzis' via SWI-Prolog wrote:
>
> flag/3 is OK for smaller facts, it doesn't seem easy to use here. I've
> given record/erase a try, but the documentation warns that
> assert/retract is faster once compiled and I didn't go too far with it.

I would rule out flag/3. It is old school from the days that SWI-Prolog
didn't have much for global storage and I needed something simple and
quick. It is not compatible with anything and serves little purpose.

Cheers --- Jan

Michael Ben Yosef

unread,
May 8, 2014, 6:38:03 AM5/8/14
to swi-p...@googlegroups.com, idinatas
Hi Stassa,


I usually manage without assert/retract also. Recently though I wanted to store a large number of compound terms that represent data associated with points on a three-dimensional grid, for a puzzle. Previously, I would put them all in a list and scan it repeatedly. The problem is that once you have more than a dozen terms or so in a list like that, it becomes rather cumbersome and a pain to debug. So I thought I could take advantage of Swi's indexed database and assert my point-terms with an extra first argument for a hash and retrieve them directly from the database as needed. I think that's faster than scanning a list but if the cost of asserting/retracting counters that speedup then there's no, er, point in it.

Were balanced trees (such as the ones from library(assoc)) not appropriate for this task?

Kind regards,

Another Michael 

Stassa Patsantzis

unread,
May 9, 2014, 9:21:03 AM5/9/14
to
Hi Jan,


On Thursday, 8 May 2014 09:31:07 UTC+1, Jan Wielemaker wrote:

I wouldn't rule out global variables that quickly.  They can be quite nice.

Hmmm. This seems to contradict you:

Global variables save you from having to specify arguments in [predicates].
Take full advantage of this. Elect one or more of these global variables to
specify what kinds of processes to do on the others. Maintenance programmers
foolishly assume that [Prolog predicates] will not have side effects.

Taken from here: http://arxiv.org/pdf/0911.2899v3.pdf :)

More seriously- global variables look nice yes, particularly where they live on
the stack and they're thread-local. But I didn't consider them because I'm
going through this phase where I want to have everything separated into
modules with crisp interfaces and so on. The documentation hints that it would
be possible to have per-module global variables; that would be great :)


Hi other Michael, 

On Thursday, 8 May 2014 11:38:03 UTC+1, Michael Ben Yosef wrote:

Were balanced trees (such as the ones from library(assoc)) not appropriate for this task?

I think the reason why either library(assoc) or library(rbtrees) was not my first
option is because the notation is a little on the cumbersome side. It's an
option, certainly, though the 'value' part would have to be a compound or a
dict anyway.

Another reason why asserting/retracting compound terms seems attractive to me
is because I've been trying to look at the Prolog database as if from the
point of view of a SQL developer. In that sense, retrieving and updating data
stored in simple relations seems very natural and hassle-free. Even from the
point of view of someone who knows some Prolog already, keeping your 'data' as
facts associated with a module is a very simple and nice way to use the Prolog
database as, well, a database.

I understand well enough how asserting/retracting in the middle of a query can
cause trouble but imagine a typical website or even some piece of enterprise
software, only with Prolog as a logic engine and/or backend. What would you do
if you had to store, say, 100,000 records of users? It would be nice to be
able to design that part of the program exactly as a traditional relational
database (only much simpler because you could do away with all the foreign
keys clutter) and then actually create it in Prolog rather than SQL.

Regards,
Stassa

Boris Vassilev

unread,
May 9, 2014, 11:07:16 AM5/9/14
to Stassa Patsantzis, swi-p...@googlegroups.com
There is another issue here altogether.

It comes down to your very specific use case. You can program it, best in little code that takes not too long to write and that is "obviously" correct. If the program solves your problem fast enough, then you are done. If it doesn't, and you plan to run your program many times, you would need actually profile.

Then you can start making decisions about what needs to be done better or faster. Last time I did something in Prolog I spend a day and bothered people on the list with "iterating over arguments of a term of arbitrary length", and at the end it turned out that it is still faster, and easier, to unpack to a list and iterate over the list. Anyway my program was spending about 80% of the time elsewhere... embarrassing.

For your particular use case, linear search might still be good enough. If it isn't, try using a data structure that fits your problem (would a range tree be a good choice for coordinates??). Many data structures are really straight forward to implement in Prolog, compared to Pascal/C-style languages.

As for using the Prolog database, my impression is that it gives a cleaner solution only if you normalize your data, which is a bit forced with some kinds of data. And it has to fit in memory (maybe I am wrong about this?).

Disclaimer: in the past year I have had very little time / need to actually write code, and I am not a computer scientist, really.

Cheers,
Boris


On Fri, May 9, 2014 at 4:18 PM, 'Stassa Patsantzis' via SWI-Prolog <swi-p...@googlegroups.com> wrote:
Hi Jan,


On Thursday, 8 May 2014 09:31:07 UTC+1, Jan Wielemaker wrote:
I wouldn't rule out global variables that quickly.  They can be quite nice.

Hmmm. This seems to contradict you:

Global variables save you from having to specify arguments in [predicates].
Take full advantage of this. Elect one or more of these global variables to
specify what kinds of processes to do on the others. Maintenance programmers
foolishly assume that [Prolog predicates] will not have side effects.

Taken from here: http://arxiv.org/pdf/0911.2899v3.pdf :)

More seriously- global variables look nice yes, particularly where they live on
the stack and they're thread-local. But I didn't consider them because I'm
going through this phase where I want to have everything separated into
modules with crisp interfaces and so on. The documentation hints that it would
be possible to have per-module global variables; that would be great :)


Hi other Michael, 

On Thursday, 8 May 2014 11:38:03 UTC+1, Michael Ben Yosef wrote:
Were balanced trees (such as the ones from library(assoc)) not appropriate for this task?

I seem to remember it was library(rbtrees) that was the fast implementation of
a balanced tree, whereas library(assoc) didn't give you any gains in
performance?

Anyway, I think the reason why either balanced tree library is not my first

option is because the notation is a little on the cumbersome side. It's an
option, certainly, though the 'value' part would have to be a compound or a
dict anyway.

Another reason why asserting/retracting compound terms seems attractive to me
is because I've been trying to look at the Prolog database as if from the
point of view of a SQL developer. In that sense, retrieving and updating data
stored in simple relations seems very natural and hassle-free. Even from the
point of view of someone who knows some Prolog already, keeping your 'data' as
facts associated with a module is a very simple and nice way to use the Prolog
database as, well, a database.

I understand well enough how asserting/retracting in the middle of a query can
cause trouble but imagine a typical website or even some piece of enterprise
software, only with Prolog as a logic engine and/or backend. What would you do
if you had to store, say, 100,000 records of users? It would be nice to be
able to design that part of the program exactly as a traditional relational
database (only much simpler because you could do away with all the foreign
keys clutter) and then actually create it in Prolog rather than SQL.

Regards,
Stassa

--
You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+...@googlegroups.com.
Visit this group at http://groups.google.com/group/swi-prolog.
For more options, visit https://groups.google.com/d/optout.

Jan Wielemaker

unread,
May 10, 2014, 3:53:12 AM5/10/14
to Stassa Patsantzis, swi-p...@googlegroups.com
On 05/09/2014 03:18 PM, 'Stassa Patsantzis' via SWI-Prolog wrote:
>
> On Thursday, 8 May 2014 09:31:07 UTC+1, Jan Wielemaker wrote:
>
> I wouldn't rule out global variables that quickly. They can be
> quite nice.
>
>
> Hmmm. This seems to contradict you:
>
> Global variables save you from having to specify arguments in
> [predicates].
> Take full advantage of this. Elect one or more of these global
> variables to
> specify what kinds of processes to do on the others. Maintenance
> programmers
> foolishly assume that [Prolog predicates] will not have side effects.

You wanted something global. Yes, these comments are true, bot also hold
for assert/retract, records, flags, ... From your comments, I have the
impression that passing variables is fine with you, and so is have
datastructures that backtrack. It is only the complexity of the term
during debugging that hinders you if I recall correctly. In that case,
both SWI7 dicts and using the portray hook may improve your situation.

> Taken from here: http://arxiv.org/pdf/0911.2899v3.pdf :)
>
> More seriously- global variables look nice yes, particularly where they
> live on
> the stack and they're thread-local. But I didn't consider them because I'm
> going through this phase where I want to have everything separated into
> modules with crisp interfaces and so on. The documentation hints that it
> would
> be possible to have per-module global variables; that would be great :)

Just name them <module>_xyz and it should not really be a problem.

Cheers --- Jan

Stassa Patsantzis

unread,
May 11, 2014, 9:18:41 AM5/11/14
to
Hi Jan,    

On Saturday, May 10, 2014 8:53:12 AM UTC+1, Jan Wielemaker wrote:   
Just name them <module>_xyz and it should not really be a problem.
   
I suppose I had that coming, didn't I? :)

On Saturday, May 10, 2014 8:53:12 AM UTC+1, Jan Wielemaker wrote:
It is only the complexity of the term
during debugging that hinders you if I recall correctly.

That was the short version. I also mentioned 'cumbersome'. The long version is that I had a long list of terms representing points in 3-dimensional space with some satelite data and a lot of boilerplatish code to handle that list. It all felt way too imperative so I made a few experiments with asserting/retracting those point-terms directly to the Prolog database. I really liked the feel of it, but I didn't go too far down that road mostly because I remembered the warning about using assert/retract (and my own previous bad experiences). Later I started thinking about it again but I don't want to go back to that project yet because it smarts a bit (I lost a race to solve that puzzle against a guy solving it in Haskell) (it was fun though).

I started a new project so I'm considering that option again and I wanted some feedback while I'm still exploring other parts of it. Specifically, I'm trying out Prolog as a logic engine for a C# application, using the SwiPlCs package. I mentioned SQL because there's some tradition in applications integrating C# with a relational database and I'd like to make the best use of this prior knowledge. There are differences in that Prolog is not just used as an rdbms, but on the other hand there's very little information on using Prolog as an rdbms, so I thought I'd, you know, ask around. 

I'm not being fussy by arguing with every suggestion on this thread, I really do appreciate them. At the same time I have considered each of them carefully. For example, I did consider dicts for my point data structures (I've been using 7.1.* development versions since they came out for that very reason). I decided against them because the recommendation in the Swi documentation is that: "Compound terms are still the representation of choice, provided that the number of arguments is low and fixed or compactness or performance are of utmost importance". Dicts are amazeballs but it seemed like in my original use case compounds were the recommended option.

Now of course I have a different use case. Dicts are very attractive but I was thinking of them more in the context of javascript-like "objects". I also find library(rdf) very attractive but from what I can tell that uses assert/retract also, and that's part of the motivation for my original question about the costs of that mechanism. Also, there is that ominous warning about SubPropertyOf SubPropertyOf in the documentation for library(rdf) that has scared me off in the past, even though I have no idea what it means in practical terms. I guess I'll just have to find out.

Needless to say, I'm being extra careful and considering all my options before I commit to any implementation because I would like the parts of the application to be easily replaceable- for example, if I find out that assert/retract or library(rdf) is not what I need I'll try the Prolog-to-ODBC interface etc. I've played with that before and I like it lots but I thought maybe I could be more cutting edge and try more Prolog-y mechanisms.

And that's the full version of it really :) I hope this helps explain my original question and apologies for any confusion caused in my foolish attempt at being short and to the point.

Kind regards,
Stassa

Stassa Patsantzis

unread,
May 11, 2014, 9:14:55 AM5/11/14
to swi-p...@googlegroups.com
Hi Boris, thank you for replying.


On Friday, May 9, 2014 4:07:16 PM UTC+1, boris.vassilev wrote:
It comes down to your very specific use case. You can program it, best in little code that takes not too long to write and that is "obviously" correct. If the program solves your problem fast enough, then you are done. If it doesn't, and you plan to run your program many times, you would need actually profile.

Of course. But I find it useful to know what others' experiences are. If I want to bounce ideas off someone about C# there's literally thousands of people who would listen. Prolog coders are rather more rare.


On Friday, May 9, 2014 4:07:16 PM UTC+1, boris.vassilev wrote:
As for using the Prolog database, my impression is that it gives a cleaner solution only if you normalize your data, which is a bit forced with some kinds of data. And it has to fit in memory (maybe I am wrong about this?).

I think I'm too used to seeing data manipulation using SQL databases and I'm captivated by the similarity with Prolog predicates. It goes without saying I'll have to design my data carefully and of course test to identify memory loads etc.

Kind regards,
Stassa

Boris Vassilev

unread,
May 12, 2014, 1:48:50 AM5/12/14
to Stassa Patsantzis, swi-p...@googlegroups.com
Hi,

just wondering: why are you not considering using a Prolog term that is a data structure fitting your exact problem (as was Michael's suggestion earlier as well)?

Cheers,
Boris


--

Jan Wielemaker

unread,
May 12, 2014, 3:30:00 AM5/12/14
to Stassa Patsantzis, swi-p...@googlegroups.com
On 05/11/2014 03:10 PM, 'Stassa Patsantzis' via SWI-Prolog wrote:

> Now of course I have a different use case. Dicts are very attractive but
> I was thinking of them more in the context of javascript-like "objects".

They can be used that way. There are other things you can do with them
though :-) It is mostly up to the fantasy of the users to find nice
way of using them.

> I also find library(rdf) very attractive but from what I can tell that
> uses assert/retract also, and that's prat of the motivation for my
> original question about the costs of that mechanism. Also, there is that
> ominous warning about SubPropertyOf SubPropertyOf in the documentation
> for library(rdf) that has scared me off in the past, even though I have
> no idea what it means in practical terms. I guess I'll just have to find
> out.

I think the fact that subPropertyOf reasoning does not deal with
SubPropertyOf SubPropertyOf has mostly theoretical value. I've
not see it happen in practice, but here you seem to have control over
your data, so it is not an issue at all. The RDF database offers some
nice things over the Prolog one. One is a standard import and export
format. Others are quite advanced indexing and proper transactions.
And no, it does not do assert/retract. The data is stored using
a linked in C library.

> Needless to say, I'm being extra careful and considering all my options
> before I commit to any implementation because I would like the parts of
> the application to be easily replaceable- for example, if I find out
> that assert/retract or library(rdf) is not what I need I'll try the
> Prolog-to-ODBC interface etc. I've played with that before and I like it
> lots but I thought maybe I could be more cutting edge and try more
> Prolog-y mechanisms.

To a certain extend, these are all pretty interchangeable. They all
have different properties if it comes to persistency, startup times,
performance, etc. See also http://www.swi-prolog.org/FAQ/PrologLAMP.txt

The choice between using Prolog terms and some form of side-effect
storage also depends on how you want your data to behave on backtracking.

Using the Prolog dynamic db as a relational DB is not uncommon. To name
two projects: JTransformer
(https://sewiki.iai.uni-bonn.de/research/jtransformer/start) and Thea
(http://www.semanticweb.gr/thea/). Especially since SWI-Prolog (like
YAP) has JIT index on multiple
arguments, you typically get really great performance.

Cheers --- Jan

> And that's the full version of it really :) I hope this helps explain my
> original question and apologies for any confusion caused in my attempt
> at being short and to the point.
>
> Kind regards,
> Stassa
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.

Stassa Patsantzis

unread,
May 13, 2014, 6:21:29 PM5/13/14
to swi-p...@googlegroups.com, Stassa Patsantzis
Hi Jan,


On Monday, May 12, 2014 8:30:00 AM UTC+1, Jan Wielemaker wrote:
I think the fact that subPropertyOf reasoning does not deal with
SubPropertyOf SubPropertyOf has mostly theoretical value.  I've
not see it happen in practice, but here you seem to have control over
your data, so it is not an issue at all.  The RDF database offers some
nice things over the Prolog one.  One is a standard import and export
format.  Others are quite advanced indexing and proper transactions.
And no, it does not do assert/retract.  The data is stored using
a linked in C library.    

A-ha! That's great! I was probably misled by the names of rdf predicates like
rdf_assert/3 and rdf_retract/4 in thinking that library(rdf) uses assert/
retract. Well, thanks for clarifying that, it sounds like library(rdf) is what
I'm looking for at least for a start.

I experimented a little with Cliopatria last year and had some fun with turtle.
I like rdf a lot, it also goes a long way towards helping to build hierarchies,
which is something else I've been trying to find a good way to do in Prolog.

Using rdf in the far-back-end with C# in the front opens lots of very exciting
avenues.


On Monday, May 12, 2014 8:30:00 AM UTC+1, Jan Wielemaker wrote:
To a certain extend, these are all pretty interchangeable.  They all
have different properties if it comes to persistency, startup times,
performance, etc.  See also http://www.swi-prolog.org/FAQ/PrologLAMP.txt

That PrologLAMP.txt FAQ was one of the bits of documentation on swi-prolog.org
that got me thinking about using Prolog as a relational database to replace SQL
:)


On Monday, May 12, 2014 8:30:00 AM UTC+1, Jan Wielemaker wrote:
The choice between using Prolog terms and some form of side-effect
storage also depends on how you want your data to behave on backtracking.

I've been thinking about that. My plan was to isolate the database operations
from the logic of the application, so that I should never have to assert into or
retract from the logic part. My hope would be that this would make the question
of backtracking over data irrelevant.

On Monday, May 12, 2014 8:30:00 AM UTC+1, Jan Wielemaker wrote:
Using the Prolog dynamic db as a relational DB is not uncommon.  To name
two projects: JTransformer
(https://sewiki.iai.uni-bonn.de/research/jtransformer/start) and Thea
(http://www.semanticweb.gr/thea/).  Especially since SWI-Prolog (like
YAP) has JIT index on multiple
arguments, you typically get really great performance.

Thank you! That's exactly the kind of thing I was asking about. And very nice to
know also :)

Kind regards,
Stassa

Stassa Patsantzis

unread,
May 13, 2014, 6:24:50 PM5/13/14
to
Hi Boris,

On Monday, May 12, 2014 6:48:50 AM UTC+1, boris.vassilev wrote:
just wondering: why are you not considering using a Prolog term that is a data
structure fitting your exact problem (as was Michael's suggestion earlier as
well)?

Do you mean compound terms that can be accessed by index, using arg/3, like
'Prolog arrays'? I considered storing vectors of 3d points using arg/3 terms like
that when I was doing that puzzle I talked about earlier. I think one reason I didn't
go with them was that they aren't much easier to debug than lists. The other big
reason of course is destructive assignment. I've always heeded the warnings
and steered clear of such operations in Prolog, which is why I haven't experimented
enough with assert/retract either.

I guess sometimes you can be _too_ cautious :)

Kind regards,
Stassa

Raivo Laanemets

unread,
May 14, 2014, 8:40:38 AM5/14/14
to swi-p...@googlegroups.com
One call pattern that current indexing schemes for predicates cannot handle are range/order queries. For example, if you have p(1, a). p(2, b). p(3, c) etc and you want to call every p clause that has its first argument >= 3 and < 9. When you have lots of clauses for p/2 and its 2nd arguments are not atoms but large complex terms, you would get significant overhead of term copying (I think it is doing term copy even though I do not find docs saying it) by simply calling p(N, Data), N >= 3, N < 9. It is possible to build some kind of index yourself using nth_clause/3 and clause references but such index cannot be really used as you cannot call specific clauses by reference (at least I do not have found a way to do it). Database engines with B-tree indexes (which implies ordering) and explicit range queries can handle these kind of situations a bit better.

Jan Wielemaker

unread,
May 14, 2014, 12:54:36 PM5/14/14
to Raivo Laanemets, swi-p...@googlegroups.com
On 05/14/2014 02:40 PM, Raivo Laanemets wrote:
> One call pattern that current indexing schemes for predicates cannot
> handle are range/order queries. For example, if you have p(1, a). p(2,
> b). p(3, c) etc and you want to call every p clause that has its first
> argument >= 3 and < 9. When you have lots of clauses for p/2 and its 2nd
> arguments are not atoms but large complex terms, you would get
> significant overhead of term copying (I think it is doing term copy even
> though I do not find docs saying it) by simply calling p(N, Data), N >=

Yes. Some systems might avoid that by moving side-effect free tests before
! as early as possible. SWI-Prolog doesn't do that at the moment.

> 3, N < 9. It is possible to build some kind of index yourself using
> nth_clause/3 and clause references but such index cannot be really used
> as you cannot call specific clauses by reference (at least I do not have
> found a way to do it). Database engines with B-tree indexes (which

That is indeed doable. Be aware that nth_clause(+,+,-) is a linear
scan. nth_clause(-,-,+) and clause(-,-,+) however do a direct lookup.

> implies ordering) and explicit range queries can handle these kind of
> situations a bit better.

Yes, currently only the RDF database literal indexing can answer such
queries quickly. I'm not aware of Prolog systems that can answer
range queries on the database quickly.

Cheers --- Jan
Reply all
Reply to author
Forward
0 new messages