commit 6ed4f0c790fa295897ff53ec7ae684e84602d373
parent 372d23022f0eb854716e8abf9aaa182ab5ecf9e6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 12 Jan 2026 16:50:39 +0100
shtr: measures line access performance
Add the -a option, which activates the linear/random line access test
bench. As expected, decompression dominates access time, and random
access is three orders of magnitude slower than linear access.
Diffstat:
2 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/doc/shtr.1 b/doc/shtr.1
@@ -15,7 +15,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
-.Dd January 9, 2026
+.Dd January 12, 2026
.Dt SHTR 1
.Os
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@@ -25,7 +25,7 @@
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh SYNOPSIS
.Nm
-.Op Fl hsv
+.Op Fl ahsv
.Op Fl l Ar lines
.Op Fl m Ar molparam
.Op Fl o Ar output
@@ -75,6 +75,9 @@ The total memory used is finally printed.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl a
+Measure line access performance.
+Both linear and random access are tested.
.It Fl h
Use suffixes to make memory usage easier to read: the number of
consecutive digits is then three or less, using powers of 2 for sizes
diff --git a/src/shtr_main.c b/src/shtr_main.c
@@ -20,6 +20,7 @@
#include "shtr.h"
+#include <rsys/clock_time.h>
#include <rsys/cstr.h>
#include <rsys/mem_allocator.h>
#include <rsys/rsys.h>
@@ -35,13 +36,14 @@ struct args {
char* lines;
char* output;
+ int bench_line_access;
int internal_format;
int verbose; /* Verbosity level */
int compression; /* Compression level */
int human_readable;
};
static const struct args ARGS_DEFAULT = {
- NULL, NULL, NULL, 0, 0, SHTR_DEFAULT_COMPRESSION, 0
+ NULL, NULL, NULL, 0, 0, 0, SHTR_DEFAULT_COMPRESSION, 0
};
struct cmd {
@@ -59,7 +61,7 @@ static INLINE void
usage(FILE* stream)
{
fprintf(stream,
-"usage: shtr [-hsv] [-l lines] [-m molparam] [-o output] [-z compression_level]\n");
+"usage: shtr [-ahsv] [-l lines] [-m molparam] [-o output] [-z compression_level]\n");
}
static res_T
@@ -72,8 +74,9 @@ args_init(struct args* args, int argc, char** argv)
*args = ARGS_DEFAULT;
- while((opt = getopt(argc, argv, "hl:m:o:svz:")) != -1) {
+ while((opt = getopt(argc, argv, "ahl:m:o:svz:")) != -1) {
switch(opt) {
+ case 'a': args->bench_line_access = 1; break;
case 'h': args->human_readable = 1; break;
case 'l': args->lines = optarg; break;
case 'm': args->molparam = optarg; break;
@@ -250,6 +253,41 @@ error:
goto exit;
}
+static void
+bench_line_access(struct shtr_line_list* lines)
+{
+ struct shtr_line line;
+ struct time t0, t1;
+ const size_t random_read_count = 10000;
+ double lines_per_second = 0;
+ int64_t usec = 0;
+ size_t i, n;
+
+ ASSERT(lines);
+
+ SHTR(line_list_get_size(lines, &n));
+
+ /* Linear access */
+ time_current(&t0);
+ FOR_EACH(i, 0, n) {
+ SHTR(line_list_at(lines, i, &line));
+ }
+ usec = time_val(time_sub(&t0, time_current(&t1), &t0), TIME_USEC);
+ lines_per_second = 1.e9 * (double)n / (double)usec;
+ printf("linear access: %g lines per second\n", lines_per_second);
+
+ /* Random access */
+ time_current(&t0);
+ FOR_EACH(i, 0, random_read_count) {
+ const double r = (double)rand() / (double)(RAND_MAX-1);
+ const size_t iline = (size_t)(r * (double)n);
+ SHTR(line_list_at(lines, iline, &line));
+ }
+ usec = time_val(time_sub(&t0, time_current(&t1), &t0), TIME_USEC);
+ lines_per_second = 1.e9 * (double)random_read_count / (double)usec;
+ printf("random access: %g lines per second\n", lines_per_second);
+}
+
static res_T
cmd_run(const struct cmd* cmd)
{
@@ -266,6 +304,7 @@ cmd_run(const struct cmd* cmd)
if(cmd->args.lines) {
if((res = load_lines(cmd, &lines)) != RES_OK) goto error;
if((res = process_lines(cmd, lines)) != RES_OK) goto error;
+ if(cmd->args.bench_line_access) bench_line_access(lines);
}
sz = MEM_ALLOCATED_SIZE(&cmd->allocator);