[DTrace-devel] [PATCH 12/20] Implement variable length integer support
Eugene Loh
eugene.loh at oracle.com
Fri Jun 4 09:58:21 PDT 2021
Shouldn't there be some unit (internals?) testing?
In the commit message, replace
a given unsigned integers
with
a given unsigned integer
Actually, I suggest rewriting the commit message altogether. Simply say
why you're doing this. Information about the implementation should go
in the source code, where interested parties can more easily find it.
E.g., the entire commit message could simply be:
Implement variable length integer support
Strings will be prefixed with their lengths to eliminate frequent
recomputation of those lengths. Since relatively short strings
are common, variable-length integers are used to save space.
In libdtrace/dt_varint.h, I see
#define VARINT_9_PLIM 0xff
#define VARINT_9_SHIFT 0
#define VARINT_9_MAX 0xffffffffffffffff
but they make no sense (and are never used). Drop them.
Are all the BPF vint functions used?
But my main reaction is that this patch is a whole lot of code and
complexity for rather meaningless optimization. I can imagine
applications where one might want to optimize for variable integers, but
here we simply want to prefix a string with its length. Now, if you
have very many, very short strings, then a short prefix makes sense. If
you have even just one long string, the benefit gets lost in the noise.
The patch tries to optimize very aggressively, even though one can
cheaply pick off the low-hanging fruit.
E.g., let's say you have a string that requires a three-byte varint
prefix. Apparently, the string is 16 Kbytes to 2 Mbytes long. So we do
not care if the prefix uses 3 bytes or 8. A five-byte varint is
necessarily accompanied by a string that is 256-Mbyte to 32-Gbyte; we
simply do not care about saving 8-5 = 3 bytes. Let's not optimize for that.
Same with subtracting those VARINT_X_MIN values. That's really trying
to shoehorn as many integers as possible into these varints; that is a
solution to someone else's problem. It makes no sense here. The
savings we're pursuing are miniscule.
What's the cost? Hard to say. One can argue (hope) that no one will
ever have to look at this code again and that dragging hundreds of lines
of this code along doesn't matter. On the other hand, loading BPF code
into the kernel and handing branching code to the BPF verifier is not to
be taken lightly. I don't know how to assess that cost, but here are
some metrics:
wc -l bpf/*.c bpf-unknown-none-objdump -d build/bpf--*.o | wc -l
14 bpf/map_tvar.c
21 bpf/get_tvar.c 17 build/bpf--get_tvar.o
18 bpf/set_tvar.c 19 build/bpf--set_tvar.o
40 bpf/probe_error.c 21 build/bpf--probe_error.o
24 bpf/agg_lqbin.c 21 build/bpf--agg_lqbin.o
40 bpf/agg_qbin.c 71 build/bpf--agg_qbin.o
104 bpf/memcpy.c 119 build/bpf--memcpy.o
191 bpf/get_bvar.c 191 build/bpf--get_bvar.o
82 bpf/strnlen.c 233 build/bpf--strnlen.o
199 bpf/varint.c 257 build/bpf--varint.o
So, varint is the size leader in those metrics. Does that matter? I
don't know, but I suppose the cost is clearly affordable in some cases,
while in other cases we will probably wish we cost less.
Here is a different proposal. How about if the leading bit is 0, then
the next 7 bits give the length. If the leading bit is 1, then the next
31 (or 63?) bits give the length. This optimizes well for the
short-string case yet is quite simple. The only down side is that it
gives up a few bytes in those cases where the accompanying strings are huge.
I can hold off reviewing the rest of this patch until we've discussed
this much.
On 6/2/21 1:48 AM, Kris Van Hees wrote:
> This patch provides an implementation of variable-length integers,
> both in libdtrace and as precompiled BPF code. It is based on the
> PrefixVarint algorithm. Unsigned integers are encoded as follows:
>
> 0x0 - 0x7f 1 byte: 0xxxxxxx
> 0x80 - 0x407f 2 bytes: 10xxxxxx xxxxxxxx
> 0x4080 - 0x20407f 3 bytes: 110xxxxx xxxxxxxx xxxxxxxx
>
> and so on. This algorithm ensures that there is exactly one
> representation for a given unsigned integers. It also ensures that
> the number of bytes in the variable length representation can be
> determined based on the first byte. This makes decoding simpler.
More information about the DTrace-devel
mailing list