I was in need of a data-store for clients to read and write short blobs (Edit: i.e. share data between them, that data can be simple strings, including json, or binary data. If the clients are in Perl, serialised nested perl data structure is also a possibility). A shared-memory hashtable seems ideal in my case. A DB seems far-fetched, especially because I need to keep these operations ultra-fast and do not need persistency, ACIDity, and frankly, neither I want to think how to do SQL which invariably, in my case, is googled out and ends up a hit-and-miss and inefficient. OTOH, building a C shared-memory framework with IPC from scratch will take long time. I am leaning towards using Redis especially because it has a C api as my app is in C. It also has a Perl api.
But here is a Pure Perl solution (yet another example of programming sitting on the hunched shoulders of Giants). It seems very fast to me with 100_000 inserts in 0.35 secs within same machine:
# simple-perl-server.pl
package MyPackage;
# base reapped from (with thanks):
# https://metacpan.org/pod/Net::Server
use base qw(Net::Server);
my %Store;
my $port = shift or die "No port\n";
sub process_request {
my $self = shift;
while (<STDIN>) {
s/[\r\n]+$//;
if( /^(.+?)=(.+?)$/ ){
my $x = $1;
my $y = $2;
#print "Added '$x' => '$y'\015\012";
print STDERR "Added '$x' => '$y'\n";
$Store{$x} = $y;
} elsif( /^(.+?)=$/ ){
my $x = $1;
if( exists $Store{$x} ){
print "'$x' => '".$Store{$x}."'\015\012";
} else {
print "'$x' => <undef>\015\012";
}
} elsif( /quit/i ){
print STDERR "$0 : quitting ...\n";
exit(0);
}
} # while <STDIN>
}
MyPackage->run(port => $port, ipv => '*');
# simple-perl-client.pl
# EDIT: this has been edited an hour after posting to set N=100_000
# time reported is correct though
# mostly from here:
# https://codereview.stackexchange.com/questions/106421/network-chat
+-in-perl
# and here:
# https://gist.github.com/chankeypathak/1b1b9b3a27799eb5e277
use strict;
use warnings;
use IO::Socket::INET;
use Time::HiRes qw/gettimeofday/;
my $N = 100_000; # number of inserts
my $start_time = Time::HiRes::gettimeofday();
my $server = shift or die "No server\n";
my $port = shift or die "No port\n";
my $client_socket = IO::Socket::INET->new(
PeerPort => $port,
PeerAddr => $server,
Proto => 'tcp'
) or die "Can't create send socket: $!!\n";
print "Connected to $server:$port!\n";
my $child;
if($child = fork) {
while( 1 ){
my $received = <$client_socket>;
exit unless defined $received;
print $received;
}
}
die "fork: $!\n" unless defined $child;
# set
print "$0 : doing $N sets ...\n";
for my $i (1..$N){
$client_socket->send("x$i=$i\n");
}
print "$0 : done $N sets.\n";
print "$0 : doing $N gets ...\n";
# get
for my $i (1..$N){
$client_socket->send("x$i=\n");
}
print "$0 : done $N gets.\n";
my $end_time = Time::HiRes::gettimeofday();
print "Closing connection ...\n";
$client_socket->send("quit\n\n");
close $client_socket;
sleep(1);
print "$0 : done $N sets/gets in ".($end_time-$start_time)." seconds.\
+n";
Run the server as: perl simple-perl-server.pl 16001
Run the client as: perl simple-perl-client.pl 127.0.0.1 16001
It's quite fast: 0.345 secs for 100_000 inserts, (out-of-the-box redis needed 10x that)
bw, bliako