From 7bc4c9674bb24f09e0b7af89442f700864217327 Mon Sep 17 00:00:00 2001 From: Fabian Boehm Date: Wed, 21 Sep 2022 17:54:55 +0200 Subject: [PATCH] builtins: Reduce streams.out.append/push_back calls This basically immediately issues a "write()" if it's to a pipe or the terminal. That means we can reduce syscalls and improve performance, even by doing something like ```c++ streams.out.append(somewcstring + L"\n"); ``` instead of ```c++ streams.out.append(somewcstring); streams.out.push_back(L'\n'); ``` Some benchmarks of the ```fish for i in (string repeat -n 2000 \n) $thing end ``` variety: 1. `set` (printing variables) sped up 1.75x 2. `builtin -n` 1.60x 3. `jobs` 1.25x (with 3 jobs) 4. `functions` 1.20x 5. `math 1 + 1` 1.1x 6. `pwd` 1.1x Piping yields similar results, there is no real difference when outputting to a command substitution. --- src/builtins/builtin.cpp | 7 ++----- src/builtins/functions.cpp | 5 ++--- src/builtins/jobs.cpp | 35 ++++++++++++++++++++--------------- src/builtins/math.cpp | 3 +-- src/builtins/path.cpp | 3 +-- src/builtins/pwd.cpp | 3 +-- src/builtins/set.cpp | 12 +++++++----- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/builtins/builtin.cpp b/src/builtins/builtin.cpp index 2ee135b0a..f58d0462a 100644 --- a/src/builtins/builtin.cpp +++ b/src/builtins/builtin.cpp @@ -101,11 +101,8 @@ maybe_t builtin_builtin(parser_t &parser, io_streams_t &streams, const wcha wcstring_list_t names = builtin_get_names(); std::sort(names.begin(), names.end()); - for (const auto &name : names) { - auto el = name.c_str(); - - streams.out.append(el); - streams.out.append(L"\n"); + for (auto &name : names) { + streams.out.append(name + L"\n"); } } diff --git a/src/builtins/functions.cpp b/src/builtins/functions.cpp index 8e8011408..cf3896cdf 100644 --- a/src/builtins/functions.cpp +++ b/src/builtins/functions.cpp @@ -286,9 +286,8 @@ maybe_t builtin_functions(parser_t &parser, io_streams_t &streams, const wc streams.out.append(reformat_for_screen(buff, termsize_last())); } else { - for (const auto &name : names) { - streams.out.append(name.c_str()); - streams.out.append(L"\n"); + for (auto &name : names) { + streams.out.append(name + L"\n"); } } diff --git a/src/builtins/jobs.cpp b/src/builtins/jobs.cpp index 2ba866148..3940ba728 100644 --- a/src/builtins/jobs.cpp +++ b/src/builtins/jobs.cpp @@ -46,6 +46,7 @@ static void builtin_jobs_print(const job_t *j, int mode, int header, io_streams_ pgid = *job_pgid; } + wcstring out; switch (mode) { case JOBS_PRINT_NOTHING: { break; @@ -53,53 +54,57 @@ static void builtin_jobs_print(const job_t *j, int mode, int header, io_streams_ case JOBS_DEFAULT: { if (header) { // Print table header before first job. - streams.out.append(_(L"Job\tGroup\t")); + out.append(_(L"Job\tGroup\t")); if (have_proc_stat()) { - streams.out.append(_(L"CPU\t")); + out.append(_(L"CPU\t")); } - streams.out.append(_(L"State\tCommand\n")); + out.append(_(L"State\tCommand\n")); } - streams.out.append_format(L"%d\t%d\t", j->job_id(), pgid); + append_format(out, L"%d\t%d\t", j->job_id(), pgid); if (have_proc_stat()) { - streams.out.append_format(L"%.0f%%\t", 100. * cpu_use(j)); + append_format(out, L"%.0f%%\t", 100. * cpu_use(j)); } - streams.out.append(j->is_stopped() ? _(L"stopped") : _(L"running")); - streams.out.append(L"\t"); - streams.out.append(j->command_wcstr()); - streams.out.append(L"\n"); + out.append(j->is_stopped() ? _(L"stopped") : _(L"running")); + out.append(L"\t"); + out.append(j->command_wcstr()); + out.append(L"\n"); + streams.out.append(out); break; } case JOBS_PRINT_GROUP: { if (header) { // Print table header before first job. - streams.out.append(_(L"Group\n")); + out.append(_(L"Group\n")); } - streams.out.append_format(L"%d\n", pgid); + append_format(out, L"%d\n", pgid); + streams.out.append(out); break; } case JOBS_PRINT_PID: { if (header) { // Print table header before first job. - streams.out.append(_(L"Process\n")); + out.append(_(L"Process\n")); } for (const process_ptr_t &p : j->processes) { - streams.out.append_format(L"%d\n", p->pid); + append_format(out, L"%d\n", p->pid); } + streams.out.append(out); break; } case JOBS_PRINT_COMMAND: { if (header) { // Print table header before first job. - streams.out.append(_(L"Command\n")); + out.append(_(L"Command\n")); } for (const process_ptr_t &p : j->processes) { - streams.out.append_format(L"%ls\n", p->argv0()); + append_format(out, L"%ls\n", p->argv0()); } + streams.out.append(out); break; } default: { diff --git a/src/builtins/math.cpp b/src/builtins/math.cpp index 979e13435..232ba2f6f 100644 --- a/src/builtins/math.cpp +++ b/src/builtins/math.cpp @@ -252,8 +252,7 @@ static int evaluate_expression(const wchar_t *cmd, const parser_t &parser, io_st streams.err.append_format(L"'%ls'\n", expression.c_str()); retval = STATUS_CMD_ERROR; } else { - streams.out.append(format_double(v, opts)); - streams.out.push_back(L'\n'); + streams.out.append(format_double(v, opts) + L"\n"); } } else { streams.err.append_format(L"%ls: Error: %ls\n", cmd, math_describe_error(error)); diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index 6a41a02a9..2c19a2bc6 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -201,8 +201,7 @@ static void path_out(io_streams_t &streams, const options_t &opts, const wcstrin if (!opts.null_out) { streams.out.append_with_separation(str, separation_type_t::explicitly); } else { - streams.out.append(str); - streams.out.push_back(L'\0'); + streams.out.append(str + L"\0"); } } } diff --git a/src/builtins/pwd.cpp b/src/builtins/pwd.cpp index d83811e29..a48ef09d2 100644 --- a/src/builtins/pwd.cpp +++ b/src/builtins/pwd.cpp @@ -73,7 +73,6 @@ maybe_t builtin_pwd(parser_t &parser, io_streams_t &streams, const wchar_t if (pwd.empty()) { return STATUS_CMD_ERROR; } - streams.out.append(pwd); - streams.out.push_back(L'\n'); + streams.out.append(pwd + L"\n"); return STATUS_CMD_OK; } diff --git a/src/builtins/set.cpp b/src/builtins/set.cpp index 49787642a..69993d7a6 100644 --- a/src/builtins/set.cpp +++ b/src/builtins/set.cpp @@ -437,7 +437,8 @@ static int builtin_set_list(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, sort(names.begin(), names.end()); for (const auto &key : names) { - streams.out.append(key); + wcstring out; + out.append(key); if (!names_only) { wcstring val; @@ -460,14 +461,15 @@ static int builtin_set_list(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, shorten = true; val.resize(60); } - streams.out.append(L" "); - streams.out.append(val); + out.push_back(L' '); + out.append(val); - if (shorten) streams.out.push_back(get_ellipsis_char()); + if (shorten) out.push_back(get_ellipsis_char()); } } - streams.out.append(L"\n"); + out.push_back(L'\n'); + streams.out.append(out); } return STATUS_CMD_OK;