Re: Caching in the dynamic database

Jan Wielemaker <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 02/12/2014 01:47 PM, Michael Ben Yosef wrote:
> 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.

I guess it depends a lot on the details what you want to do with it.

>> 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?

In my experience swapping is old school.  Memory is so cheap and
disks are so slow that you want to avoid it completely.  It only
makes sense if there are applications on the system that use a
lot of memory, tend to have long periods (hours, days) of inactivity
and where it doesn't matter much that they wake up slowly after
inactivity.  Otherwise, I'd stay far away from exhausting physical
memory.

In the Prolog context, also remember that Prolog stacks can be pretty
big.  Of course, this all depends on what you do.

>> 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)?

Ok, there is now clause_property(+Ref, -SizeInBytes).  The docs:

True when \arg{SizeInBytes} is the size that the clause uses in memory
in bytes.  The size required by a predicate also includes the predicate
data record, a linked list of clauses, clause selection instructions and
optionally one or more clause indexes.

>> 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.

Ok, hope this helps a little :-)

	Cheers --- Jan
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.