MCE::Shared::Cache(3)

πŸ“¦
version 1.893 Β· 4 versions
, in epel 10

πŸ’– MCE::Shared::Cache(3) πŸ’–

Okay bestie, this is the User Contributed Perl Documentation page for MCE::Shared::Cache β€” the hybrid LRU-plain cache helper. We’re keeping every literal detail, every option, every example, and every vibe. 🫢

🌸 NAME 🌸

MCE::Shared::Cache β€” a hybrid LRU-plain cache helper class. Iconic. No notes. πŸ’…

πŸŽ€ VERSION πŸŽ€

This document describes MCE::Shared::Cache version 1.893. Slay. ✨

πŸ¦‹ DESCRIPTION πŸ¦‹

It’s a cache helper class β€” you can use it as a standalone thing, or let MCE::Shared manage it for you.

This module implements a least-recently used (LRU) cache, and its origin is based on MCE::Shared::Ordhash because of its performance and low-memory characteristics. It is both an LRU implementation and a plain implementation. LRU logic gets applied to new items and to subsequent updates. A fetch, though, only involves LRU reorder if the item is found in the lower section of the cache. That means extra performance for the upper section, because fetch behaves similarly to accessing a plain cache. When it reaches its size restriction, it prunes items from the bottom of the cache.

The 50% LRU-mode (bottom section) / 50% plain-mode (upper-section) split applies to fetches only. 🧚

✨ SYNOPSIS ✨

Non-shared or local construction, for when a single process is living its best solo life:

# non-shared or local construction for use by a single process

use MCE::Shared::Cache;

my $ca;

$ca = MCE::Shared::Cache->new(); # max_keys => undef, max_age => undef
$ca = MCE::Shared::Cache->new( { max_keys => 500 }, @pairs );

$ca = MCE::Shared::Cache->new( max_keys => "unlimited", max_age => "never" );
$ca = MCE::Shared::Cache->new( max_keys => undef, max_age => undef ); # ditto
$ca = MCE::Shared::Cache->new( max_keys => 500, max_age => "1 hour" );
$ca = MCE::Shared::Cache->new( max_keys => "4 KiB" ); # 4*1024
$ca = MCE::Shared::Cache->new( max_keys => "1 MiB" ); # 1*1024*1024

$ca = MCE::Shared::Cache->new( max_age  => "43200 seconds" );
$ca = MCE::Shared::Cache->new( max_age  => 43200 );   # ditto
$ca = MCE::Shared::Cache->new( max_age  => "720 minutes" );
$ca = MCE::Shared::Cache->new( max_age  => "12 hours" );
$ca = MCE::Shared::Cache->new( max_age  => "0.5 days" );
$ca = MCE::Shared::Cache->new( max_age  => "1 week" );
$ca = MCE::Shared::Cache->new( max_age  => undef );   # no expiration
$ca = MCE::Shared::Cache->new( max_age  => 0 );       # now

Construction for sharing with other threads and processes β€” group chat mode activated:

# construction for sharing with other threads and processes

use MCE::Shared;

my $ca;

$ca = MCE::Shared->cache(); # max_keys => undef, max_age => undef
$ca = MCE::Shared->cache( { max_keys => 500 }, @pairs );

$ca = MCE::Shared->cache( max_keys => "unlimited", max_age => "never" );
$ca = MCE::Shared->cache( max_keys => undef, max_age => undef ); # ditto
$ca = MCE::Shared->cache( max_keys => 500, max_age => "1 hour" );
$ca = MCE::Shared->cache( max_keys => "4 KiB" ); # 4*1024
$ca = MCE::Shared->cache( max_keys => "1 MiB" ); # 1*1024*1024

$ca = MCE::Shared->cache( max_age  => "43200 seconds" );
$ca = MCE::Shared->cache( max_age  => 43200 );   # ditto
$ca = MCE::Shared->cache( max_age  => "720 minutes" );
$ca = MCE::Shared->cache( max_age  => "12 hours" );
$ca = MCE::Shared->cache( max_age  => "0.5 days" );
$ca = MCE::Shared->cache( max_age  => "1 week" );
$ca = MCE::Shared->cache( max_age  => undef );   # no expiration
$ca = MCE::Shared->cache( max_age  => 0 );       # now

Hash-like dereferencing, because sometimes you just want the classic look:

# hash-like dereferencing

my $val = $ca->{$key};
$ca->{$key} = $val;

%{$ca} = ();

The OO interface β€” highly recommended, lowkey the main character:

# OO interface

if ( !defined ( $val = $ca->get("some_key") ) ) {
   $val = $ca->set( some_key => "some_value" );
}

$val   = $ca->set( $key, $val );
$ret   = $ca->setnx( $key, $val );         # set only if the key exists
$val   = $ca->get( $key );
$val   = $ca->delete( $key );              # del is an alias for delete
$bool  = $ca->exists( $key );
void   = $ca->clear();
$len   = $ca->len();                       # scalar keys %{ $ca }
$len   = $ca->len( $key );                 # length $ca->{ $key }

$iter  = $ca->iterator( @keys );           # ($key, $val) = $iter->()
@keys  = $ca->keys( @keys );               # @keys is optional
%pairs = $ca->pairs( @keys );
@vals  = $ca->values( @keys );             # vals is an alias for values

$len   = $ca->assign( $key/$val pairs );   # equivalent to ->clear, ->mset
$cnt   = $ca->mdel( @keys );
@vals  = $ca->mget( @keys );
$bool  = $ca->mexists( @keys );            # true if all keys exists
$len   = $ca->mset( $key/$val pairs );     # merge is an alias for mset

Included sugar methods, so you don’t have to call set/get explicitly:

# included, sugar methods without having to call set/get explicitly

$len   = $ca->append( $key, $string );     #   $val .= $string
$val   = $ca->decr( $key );                # --$val
$val   = $ca->decrby( $key, $number );     #   $val -= $number
$val   = $ca->getdecr( $key );             #   $val--
$val   = $ca->getincr( $key );             #   $val++
$val   = $ca->incr( $key );                # ++$val
$val   = $ca->incrby( $key, $number );     #   $val += $number
$old   = $ca->getset( $key, $new );        #   $o = $v, $v = $n, $o

Pipeline, which provides atomicity for shared objects, MCE::Shared v1.09+:

# pipeline, provides atomicity for shared objects, MCE::Shared v1.09+

@vals  = $ca->pipeline(                    # ( "a_a", "b_b", "c_c" )
   [ "set", foo => "a_a" ],
   [ "set", bar => "b_b" ],
   [ "set", baz => "c_c" ],
   [ "mget", qw/ foo bar baz / ]
);

For normal hash behavior, the TIE interface is supported. πŸ’–

# non-shared or local construction for use by a single process

use MCE::Shared::Cache;

tie my %ca, "MCE::Shared::Cache", max_keys => undef, max_age => undef;
tie my %ca, "MCE::Shared::Cache", max_keys => 500, max_age => "1 hour";
tie my %ca, "MCE::Shared::Cache", { max_keys => 500 }, @pairs;

# construction for sharing with other threads and processes
# one option is needed minimally to know to use MCE::Shared::Cache

use MCE::Shared;

tie my %ca, "MCE::Shared", max_keys => undef, max_age => undef;
tie my %ca, "MCE::Shared", max_keys => 500, max_age => "1 hour";
tie my %ca, "MCE::Shared", { max_keys => 500 }, @pairs;

# usage

my $val;

if ( !defined ( $val = $ca{some_key} ) ) {
   $val = $ca{some_key} = "some_value";
}

$ca{some_key} = 0;

tied(%ca)->incrby("some_key", 20);
tied(%ca)->incrby(some_key => 20);

πŸ”Ž SYNTAX for QUERY STRING πŸ”Ž

Several methods take a query string as an argument. The format of that string is described below. When you’re in sharing mode, this query mechanism is a big win for the shared-manager process: it can perform the query where the data actually lives, instead of the client process grepping locally and dragging lots of IPC into the situation. 😭

  • Basic demonstration:
@keys = $ca->keys( "query string given here" );
@keys = $ca->keys( "val =~ /pattern/" );
  • Supported operators: =~ !~ eq ne lt le gt ge == != < <= > >=
  • Multiple expressions delimited by :AND or :OR, mixed case allowed:
"key eq 'some key' :or (val > 5 :and val < 9)"
"key eq some key :or (val > 5 :and val < 9)"
"key =~ /pattern/i :And val =~ /pattern/i"
"val eq foo baz :OR key !~ /pattern/i"
  • key matches on keys in the cache
  • likewise, val matches on values
  • Quoting is optional inside the string:
"key =~ /pattern/i :AND val eq 'foo bar'"   # val eq "foo bar"
"key =~ /pattern/i :AND val eq foo bar"     # val eq "foo bar"

Examples. Search capability key/val: =~ !~ eq ne lt le gt ge == != < <= > >=; key/val means to match against the actual key/val respectively:

# search capability key/val: =~ !~ eq ne lt le gt ge == != < <= > >=
# key/val means to match against actual key/val respectively

@keys  = $ca->keys( "key eq 'some key' :or (val > 5 :and val < 9)" );
@keys  = $ca->keys( "key eq some key :or (val > 5 :and val < 9)" );

@keys  = $ca->keys( "key =~ /$pattern/i" );
@keys  = $ca->keys( "key !~ /$pattern/i" );
@keys  = $ca->keys( "val =~ /$pattern/i" );
@keys  = $ca->keys( "val !~ /$pattern/i" );

%pairs = $ca->pairs( "key == $number" );
%pairs = $ca->pairs( "key != $number :and val > 100" );
%pairs = $ca->pairs( "key <  $number :or key > $number" );
%pairs = $ca->pairs( "val <= $number" );
%pairs = $ca->pairs( "val >  $number" );
%pairs = $ca->pairs( "val >= $number" );

@vals  = $ca->vals( "key eq $string" );
@vals  = $ca->vals( "key ne $string with space" );
@vals  = $ca->vals( "key lt $string :or val =~ /$pat1|$pat2/" );
@vals  = $ca->vals( "val le $string :and val eq 'foo bar'" );
@vals  = $ca->vals( "val le $string :and val eq foo bar" );
@vals  = $ca->vals( "val gt $string" );
@vals  = $ca->vals( "val ge $string" );

πŸ‘‘ API DOCUMENTATION πŸ‘‘

This module involves TIE when you access the object via hash-like behavior. Both non-shared and shared instances are impacted if you do that. It’s likely fast enough for many use cases, but the OO interface is recommended for best performance. πŸ’…

Accessing an item is likely to involve moving its key to the top of the cache. Various methods described below will state "Reorder: Yes" or "Reorder: No" as an indication. πŸ‘€

The methods "keys", "pairs", and "values" return the most frequently accessed items from the upper section of the cache first, before the lower section. Returned values may not be ordered as expected. This β€œabnormally is normal” situation is normal for this hybrid LRU-plain implementation. It comes from fetches not involving LRU movement on keys residing in the upper section of the cache.

When "max_age" is set, accessing an item which has expired will behave similarly to a non-existing item. 🫢

🌟 MCE::Shared::Cache->new ( { options }, key, value [, key, value, ... ] ) 🌟

🌟 MCE::Shared->cache ( { options }, key, value [, key, value, ... ] ) 🌟

Constructs a new object.

# non-shared or local construction for use by a single process

use MCE::Shared::Cache;

$ca = MCE::Shared::Cache->new(); # max_keys => undef, max_age => undef
$ca = MCE::Shared::Cache->new( { max_keys => 500 }, @pairs );

$ca = MCE::Shared::Cache->new( max_keys => "unlimited", max_age => "never" );
$ca = MCE::Shared::Cache->new( max_keys => undef, max_age => undef ); # ditto
$ca = MCE::Shared::Cache->new( max_keys => 500, max_age => "1 hour" );
$ca = MCE::Shared::Cache->new( max_keys => "4 KiB" ); # 4*1024
$ca = MCE::Shared::Cache->new( max_keys => "1 MiB" ); # 1*1024*1024

$ca = MCE::Shared::Cache->new( max_age  => "43200 seconds" );
$ca = MCE::Shared::Cache->new( max_age  => 43200 );   # ditto
$ca = MCE::Shared::Cache->new( max_age  => "720 minutes" );
$ca = MCE::Shared::Cache->new( max_age  => "12 hours" );
$ca = MCE::Shared::Cache->new( max_age  => "0.5 days" );
$ca = MCE::Shared::Cache->new( max_age  => "1 week" );
$ca = MCE::Shared::Cache->new( max_age  => undef );   # no expiration
$ca = MCE::Shared::Cache->new( max_age  => 0 );       # now

$ca->assign( @pairs );

# construction for sharing with other threads and processes

use MCE::Shared;

$ca = MCE::Shared->cache(); # max_keys => undef, max_age => undef
$ca = MCE::Shared->cache( { max_keys => 500 }, @pairs );
        $ca = MCE::Shared->cache( max_keys => "unlimited", max_age => "never" );
        $ca = MCE::Shared->cache( max_keys => undef, max_age => undef ); # ditto
        $ca = MCE::Shared->cache( max_keys => 500, max_age => "1 hour" );
        $ca = MCE::Shared->cache( max_keys => "4 KiB" ); # 4*1024
        $ca = MCE::Shared->cache( max_keys => "1 MiB" ); # 1*1024*1024

        $ca = MCE::Shared->cache( max_age  => "43200 seconds" );
        $ca = MCE::Shared->cache( max_age  => 43200 );   # ditto
        $ca = MCE::Shared->cache( max_age  => "720 minutes" );
        $ca = MCE::Shared->cache( max_age  => "12 hours" );
        $ca = MCE::Shared->cache( max_age  => "0.5 days" );
        $ca = MCE::Shared->cache( max_age  => "1 week" );
        $ca = MCE::Shared->cache( max_age  => undef );   # no expiration
        $ca = MCE::Shared->cache( max_age  => 0 );       # now

        $ca->assign( @pairs );

Reorder: Yes, when given key-value pairs contain duplicate keys


🫢 assign ( key, value [, key, value, ... ] )

Okay so assign is like a factory reset + a fresh drop, all in one 😌 It clears the cache first, then sets a whole bunch of key-value pairs, and hands you back the number of keys that ended up stored in the cache. Basically it's the same energy as calling clear and then mset. Two-for-one, iconic.

$len = $ca->assign( "key1" => "val1", "key2" => "val2" );

Reorder: Yes, when given key-value pairs contain duplicate keys

🧹 clear

Gone. Deleted. Not in this timeline. πŸ’€ Removes all key-value pairs from the cache.

$ca->clear;
%{$ca} = ();

πŸ—‘οΈ delete ( key )

Deletes the value sitting at the given key and returns it β€” or gives you back undef if that key does not exists in the cache. Rip bozo πŸͺ¦

$val = $ca->delete( "some_key" );
$val = delete $ca->{ "some_key" };

✨ del

del is an alias for delete. Same thing, shorter vibe. iykyk.

πŸ” exists ( key )

Checks whether a key is actually living in the cache. Very vibe check of it.

if ( $ca->exists( "some_key" ) ) { ... }
if ( exists $ca->{ "some_key" } ) { ... }

Reorder: No

πŸ’– get ( key )

Grabs the value of a cache key, or undef if the key does not exists. Important detail bestie: LRU reordering happens only if the key is found in the lower section of the cache. If you want zero reordering and no promoting, go look at peek β€” that one does not promote the key internally to the top of the list 🫑

$val = $ca->get( "some_key" );
$val = $ca->{ "some_key" };

Reorder: Yes

πŸ¦‹ iterator ( key [, key, ... ] )

When max_age is set, this prunes any expired keys at the head of the list β€” housekeeping, but make it fashion 🧚

With no arguments it returns a code reference for iterating a list of key-value pairs stored in the cache. Give it arguments and you get a code reference for iterating the given keys in the same order. Keys that do not exist will have the undef value.

The list of keys to return is set when the closure is constructed β€” so keys added to the hash later are not included. And subsequently, the undef value is returned for deleted keys. Closure said what it said πŸ’…

$iter = $ca->iterator;
$iter = $ca->iterator( "key1", "key2" );

while ( my ( $key, $val ) = $iter->() ) {
   ...
}

Reorder: No

🌈 iterator ( "query string" )

When max_age is set, prunes any expired keys at the head of the list. Same deal as above, still slaying.

Returns a code reference for iterating a list of key-value pairs that match the given criteria. It returns an empty list if the search found nothing 😭 The syntax for the query string is described above.

$iter = $ca->iterator( "val eq some_value" );
$iter = $ca->iterator( "key eq some_key :AND val =~ /sun|moon|air|wind/" );
$iter = $ca->iterator( "val eq sun :OR val eq moon :OR val eq foo" );
$iter = $ca->iterator( "key =~ /$pattern/" );

while ( my ( $key, $val ) = $iter->() ) {
   ...
}

Reorder: No

πŸ”‘ keys ( key [, key, ... ] )

When max_age is set, prunes any expired keys at the head of the list ⏰

With no arguments, returns all keys in the cache by most frequently accessed β€” the popular girlies get listed first πŸ‘‘ Otherwise, returns the given keys in the same order. Keys that do not exist will have the undef value. In scalar context, returns the size of the cache.

@keys = $ca->keys;
@keys = $ca->keys( "key1", "key2" );
$len  = $ca->keys;

Reorder: No

πŸŽ€ keys ( "query string" )

When max_age is set, prunes any expired keys at the head of the list.

Returns only keys that match the given criteria. Empty list if the search found nothing, no cap. The syntax for the query string is described above. And in scalar context, it returns the size of the resulting list.

@keys = $ca->keys( "val eq some_value" );
@keys = $ca->keys( "key eq some_key :AND val =~ /sun|moon|air|wind/" );
@keys = $ca->keys( "val eq sun :OR val eq moon :OR val eq foo" );
$len  = $ca->keys( "key =~ /$pattern/" );

Reorder: No

πŸ“ len ( key )

When max_age is set, prunes any expired keys at the head of the list.

With no arguments it returns the size of the cache. Give it a key and it returns the length of the value stored at that key β€” or the undef value if the key does not exists. Two totally different numbers, don't mix them up bestie πŸ™ˆ

$size = $ca->len;
$len  = $ca->len( "key1" );
$len  = length $ca->{ "key1" };

Reorder: Yes, only when key is given

⏳ max_age ( [ secs ] )

Returns the maximum age set on the cache β€” or "never" if it's not defined internally. Hand it some seconds and it sets the default expiry time. It's giving time wizard πŸ§™β€β™€οΈ

$age = $ca->max_age;

$ca->max_age( "43200 seconds" );
$ca->max_age( 43200 );     # ditto
$ca->max_age( "720 minutes" );
$ca->max_age( "12 hours" );
$ca->max_age( "0.5 days" );
$ca->max_age( "1 week" );
$ca->max_age( undef );     # no expiration
$ca->max_age( 0 );         # now

πŸ“¦ max_keys ( [ size ] )

Returns the size limit set on the cache β€” or "unlimited" if it's not defined internally. When you give it a size, it adjusts the cache to the new size, pruning the head of the list if necessary. Yes it will absolutely trim the ends to fit the fit βœ‚οΈ

$size = $ca->max_keys;

$ca->max_keys( undef );    # unlimited
$ca->max_keys( "4 KiB" );  # 4*1024
$ca->max_keys( "1 MiB" );  # 1*1024*1024
$ca->max_keys( 500 );

🧨 mdel ( key [, key, ... ] )

Deletes one or more keys in the cache and returns the number of keys deleted. Heads up: a given key which does not exist in the cache is not counted. No credit for imaginary deletions πŸ’€

$cnt = $ca->mdel( "key1", "key2" );

βœ… mexists ( key [, key, ... ] )

Returns a true value if all given keys exists in the cache. A false value is returned otherwise. All of them or nothing, we don't do half-hearted here.

if ( $ca->mexists( "key1", "key2" ) ) { ... }

Reorder: No

🎁 mget ( key [, key, ... ] )

Gets the values of all the given keys. It returns undef for keys which do not exists in the cache. Bulk grab, very efficient, we love her 🫢

( $val1, $val2 ) = $ca->mget( "key1", "key2" );

Reorder: Yes

πŸ“ mset ( key, value [, key, value, ... ] )

Sets multiple key-value pairs in a cache and returns the number of keys stored in the cache. That's the whole thing, she's simple and she delivers.

$len = $ca->mset( "key1" => "val1", "key2" => "val2" );

Reorder: Yes

πŸ”₯ merge

merge is an alias for mset. Cute nickname, same function.

πŸ‘― pairs ( key [, key, ... ] )

When max_age is set, prunes any expired keys at the head of the list.

With no arguments, returns key-value pairs in the cache by most frequently accessed. Otherwise, returns key-value pairs for the given keys in the same order. Keys that do not exist will have the undef value. In scalar context, returns the size of the cache.

@pairs = $ca->pairs;
@pairs = $ca->pairs( "key1", "key2" );
$len   = $ca->pairs;

Reorder: No

🧚 pairs ( "query string" )

When max_age is set, prunes any expired keys at the head of the list.

Returns only key-value pairs that match the given criteria. It returns an empty list if the search found nothing. The syntax for the query string is described above. In scalar context, returns the size of the resulting list.

@pairs = $ca->pairs( "val eq some_value" );
@pairs = $ca->pairs( "key eq some_key :AND val =~ /sun|moon|air|wind/" );
@pairs = $ca->pairs( "val eq sun :OR val eq moon :OR val eq foo" );
$len   = $ca->pairs( "key =~ /$pattern/" );

Reorder: No

πŸ‘€ peek ( key )

Same as get but without changing the order of the keys. Gets the value of a cache key or undef if the key does not exists. Look, don't touch, no shuffling the deck πŸ’…

$val = $ca->get( "some_key" );
$val = $ca->{ "some_key" };

Reorder: No

πŸš€ pipeline ( [ func1, @args ], [ func2, @args ], ... )

Combines multiple commands for the object to be processed serially. For shared objects, the call is made atomically due to a single IPC to the shared-manager process β€” one trip, many commands, iconic efficiency ✨ The pipeline method is fully wantarray-aware and receives a list of commands and their arguments. In scalar or list context, it returns data from the last command in the pipeline.

@vals = $ca->pipeline(                     # ( "a_a", "b_b", "c_c" )
   [ "set", foo => "a_a" ],
   [ "set", bar => "b_b" ],
   [ "set", baz => "c_c" ],
   [ "mget", qw/ foo bar baz / ]
);

$len = $ca->pipeline(                      # 3, same as $ca->len
   [ "set", foo => "i_i" ],
   [ "set", bar => "j_j" ],
   [ "set", baz => "k_k" ],
   [ "len" ]
);

$ca->pipeline(
   [ "set", foo => "m_m" ],
   [ "set", bar => "n_n" ],
   [ "set", baz => "o_o" ]
);

Reorder: Very likely, see API on given method

🌟 pipeline_ex ( [ func1, @args ], [ func2, @args ], ... )

Same as pipeline, but returns data for every command in the pipeline. Not just the last one β€” the whole group chat gets a reply πŸ’¬

@vals = $ca->pipeline_ex(                  # ( "a_a", "b_b", "c_c" )
   [ "set", foo => "a_a" ],
   [ "set", bar => "b_b" ],
   [ "set", baz => "c_c" ]
);

Reorder: Very likely, see API on given command

🧼 purge ( )

Remove all tombstones and expired data from the cache. Deep clean, self-care Sunday energy πŸ›

$ca->purge;

🫧 remove

remove is an alias for delete. Three names for one job, honestly relatable.

🌸 set ( key, value [, expires_in ] )

Sets the value of the given cache key and returns its new value. Optionally β€” and this is in v1.839 and later releases β€” you can give the number of seconds before the key is expired ⏲️

$val = $ca->set( "key", "value" );
$val = $ca->{ "key" } = "value";

$val = $ca->set( "key", "value", 3600  );  # or "60 minutes"
$val = $ca->set( "key", "value", undef );  # or "never"
$val = $ca->set( "key", "value", 0     );  # or "now"

$val = $ca->set( "key", "value", "2 seconds" );  # or "2s"
$val = $ca->set( "key", "value", "2 minutes" );  # or "2m"
$val = $ca->set( "key", "value", "2 hours"   );  # or "2h"
$val = $ca->set( "key", "value", "2 days"    );  # or "2d"
$val = $ca->set( "key", "value", "2 weeks"   );  # or "2w"

Reorder: Yes

πŸ¦„ setnx ( key, value [, expires_in ] )

Sets the value of a hash key, only if the key does not exist. Returns a 1 for new key or 0 if the key already exists and no operation was performed. Optionally, give the number of seconds before the key is expired. It's the "no takebacks, no overwrites" option 😀

$ret = $ca->setnx( "key", "value" );

Current API available since 1.872.

Reorder: Yes

🌻 values ( key [, key, ... ] )

When max_age is set, prunes any expired keys at the head of the list.

Returns all values in the cache by most frequently accessed when no arguments are given. Otherwise, returns values for the given keys in the same order. Keys that do not exist will have the undef value. In scalar context, returns the size of the cache.

okay so the plain values calls are giving very much:

@vals = $ca->values;
@vals = $ca->values( "key1", "key2" );
$len  = $ca->values;

Reorder: No

πŸ“ values ( "query string" )

When "max_age" is set, it prunes any expired keys at the head of the list. That's the cleanup era. It returns only values that match the given criteria, and it returns an empty list if the search found nothing. The syntax for the "query string" is described above (iykyk). In scalar context, it returns the size of the resulting list.

@vals = $ca->values( "val eq some_value" );
@vals = $ca->values( "key eq some_key :AND val =~ /sun|moon|air|wind/" );
@vals = $ca->values( "val eq sun :OR val eq moon :OR val eq foo" );
$len  = $ca->values( "key =~ /$pattern/" );

Reorder: No

🌈 vals

vals is literally an alias for values. Same energy, shorter name. 🫢

πŸ’… SUGAR METHODS

This module is equipped with sugar methods so you don't have to call set and get explicitly. In shared context, the benefit is atomicity and reduction in inter-process communication.

The API is giving a subset of the Redis primitives (https://redis.io/commands#strings), with key representing the cache key.

Optionally in v1.839 and later releases, give the number of seconds before the key is expired, similarly to set.

🍬 append ( key, string [, expires_in ] )

Appends a value to a key and returns its new length.

$len = $ca->append( $key, "foo" );

Reorder: Yes

🍬 decr ( key [, expires_in ] )

Decrements the value of a key by one and returns its new value.

$num = $ca->decr( $key );

Reorder: Yes

🍬 decrby ( key, number [, expires_in ] )

Decrements the value of a key by the given number and returns its new value.

$num = $ca->decrby( $key, 2 );

Reorder: Yes

🍬 getdecr ( key [, expires_in ] )

Decrements the value of a key by one and returns its old value β€” the before pic. πŸ™ˆ

$old = $ca->getdecr( $key );

Reorder: Yes

🍬 getincr ( key [, expires_in ] )

Increments the value of a key by one and returns its old value β€” also the before pic. πŸ’€

$old = $ca->getincr( $key );

Reorder: Yes

🍬 getset ( key, value [, expires_in ] )

Sets the value of a key and returns its old value. The glow-up is real.

$old = $ca->getset( $key, "baz" );

Reorder: Yes

🍬 incr ( key [, expires_in ] )

Increments the value of a key by one and returns its new value.

$num = $ca->incr( $key );

Reorder: Yes

🍬 incrby ( key, number [, expires_in ] )

Increments the value of a key by the given number and returns its new value.

$num = $ca->incrby( $key, 2 );

Reorder: Yes

🧚 INTERNAL METHODS

Internal "Sereal" freeze-thaw hooks for exporting shared-cache object:

  • FREEZE
  • THAW

Internal "Storable" freeze-thaw hooks for exporting shared-cache object:

  • STORABLE_freeze
  • STORABLE_thaw

πŸ”₯ PERFORMANCE TESTING

One might want to benchmark this module. If yes, remember to use the non-shared construction for running on a single core.

use MCE::Shared::Cache;

my $cache = MCE::Shared::Cache->new( max_keys => 500_000 );

Otherwise, the following is a parallel version for a benchmark script (https://blog.celogeek.com/201401/426/perl-benchmark-cache-with-expires-and-max-size) found on the web. The serial version was created by Celogeek for benchmarking various caching modules.

The MCE progress option makes it possible to track progress while running parallel. This script involves IPC to and from the shared-manager process, where the data resides. In regards to IPC, fetches may take longer on Linux versus Darwin or FreeBSD.

#!/usr/bin/perl

use strict;
use warnings;
use feature qw( say );

use Digest::MD5 qw( md5_base64 );
use Time::HiRes qw( time );
use MCE 1.814;
use MCE::Shared;

$| = 1; srand(0);

# construct shared variables
# serialization is handled automatically

my $c     = MCE::Shared->cache( max_keys => 500_000 );
my $found = MCE::Shared->scalar( 0 );

# construct and spawn MCE workers
# workers increment a local variable $f

my $mce = MCE->new(
    chunk_size  => 4000,
    max_workers => 4,
    user_func   => sub {
        my ($mce, $chunk_ref, $chunk_id) = @_;
        if ( $mce->user_args()->[0] eq 'setter' ) {
            for ( @{ $chunk_ref } ) { $c->set($_, {md5 => $_})  }
        }
        else {
            my $f = 0;
            for ( @{ $chunk_ref } ) { $f++ if ref $c->get($_) eq 'HASH' }
            $found->incrby($f);
        }
    }
)->spawn();

say "Mapping";
my @todo = map { md5_base64($_) } ( 1 .. 600_000 );

say "Starting";
my ( $read, $write );

{
    my $s = time;
    $mce->process({
        progress  => sub { print "Write: $_[0]\r" },
        user_args => [ 'setter' ],
    }, \@todo);
    $write = time - $s;
}

say "Write: ", sprintf("%0.3f", scalar(@todo) / $write);

{
    my $s = time;
    $found->set(0);
    $mce->process({
        progress  => sub { print "Read $_[0]\r" },
        user_args => [ 'getter' ],
    }, \@todo);
    $read = time - $s;
}

$mce->shutdown();

say "Read : ", sprintf("%0.3f", scalar(@todo) / $read);
say "Found: ", $found->get();

The progress option is further described on Metacpan. Several examples are provided, accommodating all input data-types in MCE.

Progress Demonstrations (https://metacpan.org/pod/MCE::Core#PROGRESS-DEMONSTRATIONS) β€” that's the doc link. πŸ’–

🌸 SEE ALSO

  • CHI
  • Cache::FastMmap
  • Cache::LRU
  • Cache::Ref
  • Tie::Cache::LRU
  • Tie::Cache::LRU::Expires

πŸ¦‹ INDEX

MCE, MCE::Hobo, MCE::Shared β€” that's the index, bestie. ✨

πŸ‘‘ AUTHOR

Mario E. Roy, <marioeroy AT gmail DOT com>


That's the whole manpage, bestie! It's from perl v5.40.0, dated 2024-09-10, and it's MCE::Shared::Cache(3). Periodt. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from