]> Sergey Matveev's repositories - public-inbox.git/blob - Documentation/technical/whyperl.txt
doc: add technical/whyperl
[public-inbox.git] / Documentation / technical / whyperl.txt
1 why public-inbox is currently implemented in Perl 5
2 ---------------------------------------------------
3
4 While Perl has many detractors and there's a lot not to like
5 about Perl, we use it anyways because it offers benefits not
6 (yet) available from other languages.
7
8 This document is somewhat inspired by https://sqlite.org/whyc.html
9
10 Other languages and runtimes may eventually be a possibility
11 for us, and this document can serve as our requirements list
12 for possible replacements.
13
14 As always, comments and corrections and additions welcome at
15 <meta@public-inbox.org>.  We're not Perl experts, either.
16
17 Good Things
18 -----------
19
20 * Availability
21
22   Perl 5 is installed on many, if not most GNU/Linux and
23   BSD-based servers and workstations.  It is likely the most
24   widely-installed programming environment that offers a
25   significant amount of POSIX functionality.  Users won't
26   have to waste bandwidth or space with giant toolchains or
27   architecture-specific binaries.
28
29   Furthermore, Perl documentation is typically installed as
30   manpages, allowing users to quickly access and learn it
31   offline.
32
33 * Scripted, always editable by the end user
34
35   Users cannot lose access to the source code.  Code written
36   entirely in any scripting language automatically satisfies
37   the GPL-2.0, making it easier to satisfy the AGPL-3.0.
38
39   Use of a scripting language improves auditability for
40   malicious changes.  It also reduces storage and bandwidth
41   requirements for distributors, as the same scripts can be
42   shared across multiple OSes and architectures.
43
44   Perl's availability and the low barrier to entry of
45   scripting ensures it's easy for users to exercise their
46   software freedom.
47
48 * Predictable performance
49
50   While Perl is neither fast or memory-efficient, its
51   performance and memory use are predictable and does not
52   require GC tuning by the user.
53
54   public-inbox is developed for (and mostly on) old
55   hardware.  Perl was fast enough to power the web of the
56   late 1990s, and any cheap VPS today has more than enough
57   RAM and CPU for handling plain-text email.
58
59   Low hardware requirements increases the reach of our software
60   to more users, improving centralization resistance.
61
62 * Compatibility
63
64   Unlike similarly powerful scripting languages, there is no
65   forced migration to a major new version.  From 2000-2020,
66   Perl had fewer breaking changes than Python or Ruby; we
67   expect that trend to continue given the inertia of Perl 5.
68
69 * Built for text processing
70
71   Our focus is plain-text mail, and Perl has many built-ins
72   optimized for text processing.  It also has good support
73   for UTF-8 and legacy encodings found in old mail archives.
74
75 * Integration with distros and non-Perl libraries
76
77   Perl modules and bindings to common libraries such as
78   SQLite and Xapian are already distributed by many
79   GNU/Linux distros and BSD ports.
80
81   There should be no need to rely on language-specific
82   package managers such as cpan(1), those systems increase
83   the learning curve for users and systems administrators.
84
85 * Compactness and terseness
86
87   Less code generally means less bugs.  We try to avoid the
88   "line noise" stereotype of some Perl codebases, yet still
89   manage to write less code than one would with
90   non-scripting languages.
91
92 * Performance ceiling and escape hatch
93
94   With optional Inline::C, we can be "as fast as C" in some
95   cases.  Inline::C is widely-packaged by distros and it
96   gives us an escape hatch for dealing with missing bindings
97   or performance problems should they arise.  Inline::C use
98   (as opposed to XS) also preserves the software freedom and
99   auditability benefits to all users.
100
101   Unfortunately, most C toolchains are big; so Inline::C
102   will always be optional for users who cannot afford the
103   bandwidth or space.
104
105
106 Bad Things
107 ----------
108
109 * Slow startup time.  Tokenization, parsing, and compilation of
110   pure Perl is not cached.  Inline::C does cache its results,
111   however.
112
113   We work around slow startup times in tests by preloading
114   code, similar to how mod_perl works for CGI.
115
116 * High space overhead and poor locality of small data
117   structures, including the optree.  This may not be fixable
118   in Perl itself given compatibility requirements of the C API.
119
120   These problems are exacerbated on modern 64-bit platforms,
121   though the Linux x32 ABI offers promise.
122
123 * Lack of vectored I/O support (writev, sendmmsg, etc. syscalls)
124   and "newer" POSIX functions in general.  APIs end up being
125   slurpy, favoring large buffers and memory copies for
126   concatenation rather than rope (aka "cord") structures.
127
128 * While mmap(2) is available via PerlIO::mmap, string ops
129   (m//, substr(), index(), etc.) still require memory copies
130   into userspace, negating a benefit of zero-copy.
131
132 * The XS/C API make it difficult to improve internals while
133   preserving compatibility.
134
135 * Lack of optional type checking.  This may be a blessing in
136   disguise, though, as it encourages us to simplify our data
137   models and lowers cognitive overhead.
138
139 * SMP support is mostly limited to fork(), since many
140   libraries (including much of the standard library) are not
141   thread-safe.  Even with threads.pm, sharing data between
142   interpreters within the same process is inefficient due to
143   the lack of lock-free and wait-free data structures from
144   projects such as Userspace RCU.
145
146 * Process spawning speed degrades as memory use increases.
147   We work around this optionally via Inline::C and vfork(2),
148   since Perl lacks an approximation of posix_spawn(3).
149
150   We also use `undef' and `delete' ops to free large buffers
151   as soon as we're done using them to save memory.
152
153
154 Red herrings to ignore when evaluating other runtimes
155 -----------------------------------------------------
156
157 These don't discount a language or runtime from being
158 being used, they're just not interesting.
159
160 * Lightweight threading
161
162   While lightweight threading implementations are
163   convenient, they tend to be significantly heavier than a
164   pure event-loop systems (or multi-threaded event-loop
165   systems)
166
167   Lightweight threading implementations have stack overhead
168   and growth typically measured in kilobytes.  The userspace
169   state overhead of event-based systems is an order of
170   magnitude less, and a sunk cost regardless of concurrency
171   model.