Raku
start-up times are notoriously huge.
On my machine (old one but the most modern I own):
time raku -e 'put "Hello, World!"'
495.67 - 567.02 millis
(1.53 secs for the 1st time launch)
time perl -E 'say "Hello, World!"'
13.63 - 19.51 millis
time sh -c 'echo "Hello, World!"'
4.31 - 6.88 millis
c
:
#include <stdio.h>
int main(void) {
puts("Hello, World!");
return 0;
}
time ./hello
5.03 - 7.67 millis
time clang hello.c -o hello
(compile)
126.39 - 195.66 millis
Raku
does boast many nifties built-in which make it heavy.
Yet sometimes you need a rather simple script, and you would prefer Raku
for its elegance, but launch-time spent waiting brings dissatisfaction and you don't pick Raku
for your next simple script.
Is there a way to help it?
Like starting Raku
once and keeping it running, and making it handle all Raku
scripts, with and without modules, big and small, and raku -e ...
as well?
Something like FastCGI
but for local shell?
Even sacrificing permanently huge amount of memory is better for me than wasting time waiting.
In KiloBytes, according to ps
:
Virtual size Resident set size
raku -e 'loop {sleep 1}' 146704 107200
perl -e 'while (1) {sleep 1}' 1252 4036
sh -c 'while true; do sleep 1; done' 892 900
#include <unistd.h>
void main(void) { for(;;) {sleep(1);} } 172 780
Update:
Elaborating upon
raku -e 'while prompt "Enter filename: " -> $filename { EVALFILE $filename }'
from https://stackoverflow.com/a/73873471/14812514
Concocted from https://docs.raku.org/type/IO::Socket::INET and https://www.tutorialspoint.com/perl/perl_socket_programming.htm
raku-persistent
, heavy server:
#! /usr/bin/env raku
use MONKEY-SEE-NO-EVAL;
my $listen = IO::Socket::INET.new( :listen,
:localhost<localhost>,
:localport(3333) );
loop {
my $conn = $listen.accept;
try {
while my $buf = $conn.recv() {
put now - (EVAL $buf)[1] - 37; # also subtract leap seconds
EVALFILE (EVAL $buf)[0];
}
}
$conn.close;
CATCH { default {.payload.say} }
}
ra
, light client:
#! /usr/bin/env perl
use strict;
use warnings;
use Time::HiRes;
use Socket;
my $file = shift || '/tmp/test.raku';
my $arg1 = shift || Time::HiRes::time;
# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 3333;
my $server = "localhost"; # Host IP running the server
# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
or die "Can't create a socket $!\n";
connect(SOCKET, pack_sockaddr_in($port, inet_aton($server)))
or die "Can't connect to port $port! \n";
printf SOCKET '["%s", %f]', $file, $arg1;
close SOCKET or die "close: $!";
/tmp/test.raku
:
put "Hello, World!";
run 'notify-send', 'Hello, World!'
raku-persistent
in one terminal, once;
ra [script.raku]
in another terminal, how many times you want.
Delay ranges 0.008848472 - 1.322056732; in most cases being below 0.07.
This is still a proof of concept since arguments don't get into the target script (and I don't know how except slurp
ing manually, subst
ituting and EVAL
uating - dirty, brittle, bad).
CodePudding user response:
Assuming you have a recent version of Rakudo, I can say that you have indeed a very slow machine:
% time perl -E 'say "Hello, World!"'
Hello, World!
real 0.05s
user 0.00s
sys 0.03s
% time raku -e 'put "Hello, World!"'
Hello, World!
real 0.12s
user 0.12s
sys 0.02s
are the numbers I see on a 2-year M1 MacMini. On a 10 year old MacMini running Debian, I see:
$ time perl -E 'say "Hello, World!"'
Hello, World!
real 0m0.009s
user 0m0.004s
sys 0m0.005s
$ time raku -e 'put "Hello, World!"'
Hello, World!
real 0m0.241s
user 0m0.287s
sys 0m0.041s
Now to get back to your question: yes, you can have something like FastCGI but for a local shell:
% raku -e 'while prompt "Enter filename: " -> $filename { EVALFILE $filename }
run this, enter the name of the script to execute and ENTER, and it will run. Now, this is the principle: this only runs scripts without arguments. You can build on this allowing for arguments and such.
CodePudding user response:
The client-server model you describes seems like a really good idea to me! In fact, I've been toying with a similar idea myself; I actually gave a lightning talk on the subject at the 2022 Perl and Raku Conference, A Nailgun for Raku.
As that talk mentions, this is the basic idea behind Nailgun – which implements the same idea but for Java. As you note, it gets a bit more complex than the proof of concept, but definitely seems like a doable Raku project.
On a different note, I agree with Raiph [edit: with Liz, oops!] that the timings you posted are pretty close to a worst-case scenario in terms of launch speed. My go-to reference for language startup time benchmarks is bdrung/startup-time, which has both a benchmarking framework and the author's own data. For comparison, that author clocks a "Hello, World!" C program between 0.26 ms (for a 2018 laptop) and 2.19 ms (for a Raspberry Pi 3). Those times might provide some context for the 5.03 to 7.67ms time you measured for a "Hello, World!" C programs.