Re: Caching in the dynamic database
Michael Ben Yosef <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <CABnaNcp39=v=jz_JwSyp_OZ2g3q-iuWW-1=eVJqb2hxLFkmEXg@mail.gmail.com> |
Hi Jan,
> my_clause(Id, <properties>)
>
> that is queried as (+, -*).
>
> Now, you could do something like this:
>
> my_clause(Id, Properties) :-
> my_clause_cached(Id, Props0), !,
> Properties = Props0.
> my_clause(Id, Properties) :-
> <db lookup>(Id, Props0),
> asserta(my_clause_cached(Id, Props0)),
> Properties = Props0.
>
> Is that what you have in mind.
I actually had in mind a larger "granularity", so that using files
makes sense. For example,
:- module(my_db, [my_clause/2, evict_my_clause/0, ...]).
:- use_module(library(persistency)).
:- persistent my_clause_cached(Id, Props).
my_clause(Id, Properties) :-
my_clause_cached(Id, Props0), !,
Properties = Props0.
my_clause(Id, Properties) :-
db_sync(reload),
my_clause_cached(Id, Properties)).
evict_my_clause :-
retractall(my_clause_cached(_,_)).
[...wrappers for assert_my_clause_cached/2, etc.]
That relies on being able to partition one's database into larger sets
of clauses that tend to be used all at once or not at all. For
example, I imagine keeping session data related to a particular user
logged on to a web service in one chunk, and evicting that entire
chunk when the user logs off or doesn't send any requests for some
length of time.
But your example is a direct translation of the sort of application
things like memcached are for: placing an in-memory cache in-front of
the database and trying the cache first for every query you would have
sent to the database. Perhaps I should be thinking along these lines
instead. It's a simpler and more general approach.
> Not sure of any of these keys make sense. You typically have to share
> memory with other processes. How much is reasonable?
Let's say we can measure how much space clauses take up. Then we can
keep track of the size of the "cache" and try to ensure it doesn't
exceed some value Max. We could then build a system and test it with
an empty cache on the intended hardware with the final configuration
including all the other code and all other necessary processes running
on the system. Then we measure the amount of free memory still
available, and that - or a slightly smaller value - is then an
appropriate value for Max. (Presumably it's not a disaster if
SWI-Prolog runs out of physical memory, but we'd want to avoid
swapping). Does that seem reasonable?
> What would be
> pretty easy to add is a clause_property/2 that tells you how big a
> clause is. Would that help?
I think it would help a lot! Would it take things like JIT indexes
into account, i.e. if I summed this clause size over all relevant
clauses would I get the full picture of how much space they are taking
up (compared to them all being retracted)?
> Probably you also want something to know
> when it was last used. Not sure how to do that efficiently without using
> extra space. In theory you could invent a time-stamping instruction. Not
> sure what a sensible API would look like though.
I don't think that needs special support. I'm happy to handle that at
the application level.
> I'm surely interested to include support for this stuff, provided that
> the general overhead can remain low.
Great! Thank you.
Kind regards,
Michael