Goto Chapter: Top 1 2 3 Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

3 Types of cache
 3.1 Internals
 3.2 Disk cache
 3.3 MongoDB cache

3 Types of cache

A memoised function stores its results in a cache; that is, a backend that stores computed values, along with hashes of their keys. If appropriate, the key itself and any metadata will also be stored in the cache.

Users can decide what type of cache they wish to use by specifying the cache option to MemoisedFunction (2.1-1): a string starting with "file://" will create a disk cache (see Section 3.2), and a string starting with "mongodb://" will create a MongoDB cache (see Section 3.3).

3.1 Internals

A user will generally not need to interact directly with the cache, which should be viewed as a backend to a memoised function. However, one can access the object directly by adding !.cache to a memoised function.

3.1-1 MEMO_IsCache
‣ MEMO_IsCache( arg )( filter )

Returns: true or false

Generic category for memoisation caches (backends).

An object of this type is created automatically by MemoisedFunction (2.1-1), and is stored in the !.cache component of the memoised function. A cache implements IsLookupDictionary, and so entries can be manually added, searched, and looked up using AddDictionary, KnowsDictionary and LookupDictionary.

gap> memo := MemoisedFunction(x -> x * x, rec(funcname := "square"));;
gap> memo!.cache;
<lookup dictionary>
gap> MEMO_IsCache(memo!.cache);
true
gap> AddDictionary(memo!.cache, 4, 16);
gap> KnowsDictionary(memo!.cache, 4);
true
gap> LookupDictionary(memo!.cache, 4);
16

3.2 Disk cache

The default type of cache is a disk cache. This cache saves and loads results at a specified location in the filesystem, and these files can be shared or edited by hand as desired.

To create a disk cache, one should specify a cache option beginning with "file://" to MemoisedFunction (2.1-1). The rest of the string after this prefix should be a path to a directory on the local filesystem. Memoised results will be stored inside this directory, inside a subdirectory named after the memoised function's funcname.

Consider the following example:

gap> ds := MemoisedFunction(DerivedSubgroup,
>                rec(cache := "file://results_for_alice/group_theory"));;
gap> ds(Group((1,2,3,4), (1,2)));
Group([ (1,3,2), (1,4,3) ])
gap> MEMO_IsDiskCache(ds!.cache);
true

This will create a file called HASH.out in a subdirectory called results_for_alice/group_theory/DerivedSubgroup/ inside the local directory, where HASH will be a hash of the key [ Group([ (1,3,2), (1,4,3) ]) ]. The file will contain a pickled version of the function's output.

To change the format of the filename, we could specify a different hash option to MemoisedFunction (2.1-1). To change the format of the file contents, we could specify different pickle and unpickle options. This could make the files human-readable or readable by another system:

gap> pow := MemoisedFunction(\^,
>                rec(funcname := "powers",
>                    cache := "file://arithmetic_results",
>                    hash := k -> StringFormatted("{}_to_the_{}", k[1], k[2]),
>                    pickle := z -> StringFormatted("The answer is {}.", z),
>                    unpickle := str -> Int(str{[15 .. Length(str)-1]})));;
gap> pow(2, 3);
8
gap> pow(10, 5);; pow(1, 0);; pow(8, 4);;
gap> DirectoryContents("arithmetic_results/powers/");
[ ".", "..", "2_to_the_3.out", "10_to_the_5.out", "1_to_the_0.out",
  "8_to_the_4.out" ]
gap> StringFile("arithmetic_results/powers/10_to_the_5.out");
"The answer is 100000."

If storekey is set to true, then a corresponding HASH.key file will be created, and if metadata is specified, then a corresponding HASH.meta file will also be created.

By default, a memoised function will store its results in memo/ in the local directory.

3.3 MongoDB cache

Instead of saving results to a local disk, we can instead save them to a MongoDB database, which may be hosted remotely.

To create a MongoDB cache, one should specify a cache option beginning with "mongodb://" to MemoisedFunction (2.1-1). The rest of the string after this prefix should be the URL of a server configured to handle GAP Memoisation or pypersist requests.

The appropriate files to configure such a server are located in the mongodb_server directory inside this package. Navigate into that directory and run python3 run.py to start a local server (the MongoDB service and the eve python package should both be installed). This server can then be accessed locally using cache := "mongodb://localhost:5000/persist".

gap> quintuple := x -> x * 5;;
gap> mq := MemoisedFunction(quintuple,
>                rec(cache := "mongodb://localhost:5000/persist"));
<memoised function( x ) ... end>
gap> mq(101);
505
gap> mq(101);
505
gap> ClearMemoisedFunction(mq);
true
gap> MEMO_IsMongoDBCache(mq!.cache);
true

To see details of the requests sent to and from the server, set InfoMemoisation to at least 3.

Using a remote server, multiple users can interact with the same database at once, sharing results between them. The same servers can be reached by pypersist to store cached Python results. By default, results from GAP will be stored using the "gapmemo" namespace, and thus kept separate from pypersist results. However, if one wishes to share results with a functionally similar pypersist function, one can change the value of MEMO_MongoDBNamespace to "pypersist" to gain access to the same results.

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 Ind

generated by GAPDoc2HTML