Listing/1 works slowly in specific circrumstances

I have strange situation using SWI Prolog listing/1 predicate.
I have several dynamic predicates used as database for some state.

Initially state is constructed from scratch by some program. Then I can save it to file by calling listing/1 predicate and redirecting output to file. To load state I just consult this file on clean state and everything works fine except for one specific scenario:

If I save state that was constructed from scratch, listing works fast.
If I try to save state, that was previously restored, listing works very slow - like taking 2 minutes to dump 5000 clauses.

I have no idea what can it be and how to fix it (((

Neither have I :frowning: If you can provide us with something we can run to see what is going on we might be able to find out what happens. If that is hard, the first thing to try is using profile/1 on both the initial save and the slow save and see what has changed.

One option that comes to mind while writing the above is that, when listing from asserted facts, it just lists the database. When listing from loaded source it tries to re-establish the variable names. You can use

?- listing(Pred, [variable_names(generated)]).

See listing/2.

If you want speed though, use write_term/3 or write_canonical/2. listing/0-2 is intended to generate pretty human readable output.

I’ve profiled both cases.

In slow case it spends almost all time in skip/2. And a little bit of prolog_source:seek_to_line/2.

My theory is that it is somehow connected to to fact, that when I restore state by consult, predicate has source code file associated with it and it slows later listing call. Initially predicate is constructed via assert calls, and doesn’t have source code associated.

Okay, I used listing(…, [source(false)]).

It has improved things a lot - from 42 seconds down to 9.

It is still much more that 0.14 seconds of initial state saving, but is acceptable now.

Again, all 9 seconds are spent in skip/2 somehow.

Thanks for guidance!

P.S. Adding variable_names(generated) to options has sped it up to 0.05s!

Now even faster than original!

listing/1 and compiling a file are not really meant for this. As said, listing/1 tries to write something human readable and compiling a file does a lot on term expansion, tracking source locations, etc. Consider library(persistency) or use clause/2 + write_term/3 for saving and a loop using read_term/3 and assertz/1 for loading.

There’s also library(fastrw), e.g., fast_read/2, fast_write/2, fast_term_serialized/2.