From 0f3b2c2ae7f8f9354c19412d61bd483616be72c0 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 30 May 2022 19:15:05 +0300 Subject: [PATCH] builtin: use C.fwrite (buffered) for _write_buf_to_fd (#14558) --- cmd/tools/modules/scripting/scripting.v | 4 ++++ cmd/tools/modules/testing/common.v | 1 + cmd/tools/repeat.v | 19 ++++++++++------ cmd/tools/vfmt.v | 2 ++ vlib/builtin/builtin.c.v | 29 +++++++++++++++++++------ vlib/term/control.v | 8 +++++++ vlib/term/term_nix.c.v | 3 +++ vlib/term/ui/input_nix.c.v | 2 ++ vlib/term/ui/input_windows.c.v | 5 +++++ vlib/term/ui/termios_nix.c.v | 9 ++++++++ vlib/term/ui/ui.v | 1 + 11 files changed, 69 insertions(+), 14 deletions(-) diff --git a/cmd/tools/modules/scripting/scripting.v b/cmd/tools/modules/scripting/scripting.v index 342b9b7778..ce936e7827 100644 --- a/cmd/tools/modules/scripting/scripting.v +++ b/cmd/tools/modules/scripting/scripting.v @@ -24,6 +24,7 @@ pub fn cprint(omessage string) { message = term.cyan(message) } print(message) + flush_stdout() } pub fn cprint_strong(omessage string) { @@ -32,16 +33,19 @@ pub fn cprint_strong(omessage string) { message = term.bright_green(message) } print(message) + flush_stdout() } pub fn cprintln(omessage string) { cprint(omessage) println('') + flush_stdout() } pub fn cprintln_strong(omessage string) { cprint_strong(omessage) println('') + flush_stdout() } pub fn verbose_trace(label string, message string) { diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 2287e48be6..fe68567fc5 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -123,6 +123,7 @@ pub fn (mut ts TestSession) print_messages() { // progress mode, the last line is rewritten many times: if is_ok && !ts.silent_mode { print('\r$empty\r$msg') + flush_stdout() } else { // the last \n is needed, so SKIP/FAIL messages // will not get overwritten by the OK ones diff --git a/cmd/tools/repeat.v b/cmd/tools/repeat.v index d93bcc30d8..1438ee2fe6 100644 --- a/cmd/tools/repeat.v +++ b/cmd/tools/repeat.v @@ -200,8 +200,13 @@ fn (mut context Context) parse_options() ? { } } +fn flushed_print(s string) { + print(s) + flush_stdout() +} + fn (mut context Context) clear_line() { - print(context.cline) + flushed_print(context.cline) } fn (mut context Context) expand_all_commands(commands []string) []string { @@ -247,7 +252,7 @@ fn (mut context Context) run() { println('Series: ${si:4}/${context.series:-4}, command: $cmd') if context.warmup > 0 && run_warmups < context.commands.len { for i in 1 .. context.warmup + 1 { - print('${context.cgoback}warming up run: ${i:4}/${context.warmup:-4} for ${cmd:-50s} took ${duration:6} ms ...') + flushed_print('${context.cgoback}warming up run: ${i:4}/${context.warmup:-4} for ${cmd:-50s} took ${duration:6} ms ...') mut sw := time.new_stopwatch() res := os.execute(cmd) if res.exit_code != 0 { @@ -260,9 +265,9 @@ fn (mut context Context) run() { context.clear_line() for i in 1 .. (context.count + 1) { avg := f64(sum) / f64(i) - print('${context.cgoback}Average: ${avg:9.3f}ms | run: ${i:4}/${context.count:-4} | took ${duration:6} ms') + flushed_print('${context.cgoback}Average: ${avg:9.3f}ms | run: ${i:4}/${context.count:-4} | took ${duration:6} ms') if context.show_output { - print(' | result: ${oldres:s}') + flushed_print(' | result: ${oldres:s}') } mut sw := time.new_stopwatch() res := scripting.exec(cmd) or { continue } @@ -288,7 +293,7 @@ fn (mut context Context) run() { context.results[icmd].atiming = new_aints(context.results[icmd].timings, context.nmins, context.nmaxs) context.clear_line() - print(context.cgoback) + flushed_print(context.cgoback) mut m := map[string][]int{} ioutputs := context.results[icmd].outputs for o in ioutputs { @@ -358,7 +363,7 @@ fn (mut context Context) show_diff_summary() { println('context: $context') } if int(base) > context.fail_on_maxtime { - print(performance_regression_label) + flushed_print(performance_regression_label) println('average time: ${base:6.1f} ms > $context.fail_on_maxtime ms threshold.') exit(2) } @@ -367,7 +372,7 @@ fn (mut context Context) show_diff_summary() { } fail_threshold_max := f64(context.fail_on_regress_percent) if first_cmd_percentage > fail_threshold_max { - print(performance_regression_label) + flushed_print(performance_regression_label) println('${first_cmd_percentage:5.1f}% > ${fail_threshold_max:5.1f}% threshold.') exit(3) } diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index c1dd8c6a70..eced1ea280 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -183,6 +183,7 @@ fn (foptions &FormatOptions) format_pipe() { // checker.new_checker(table, prefs).check(file_ast) formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug) print(formatted_content) + flush_stdout() foptions.vlog('fmt.fmt worked and $formatted_content.len bytes were written to stdout.') } @@ -279,6 +280,7 @@ fn (mut foptions FormatOptions) post_process_file(file string, formatted_file_pa return } print(formatted_fc) + flush_stdout() } fn (f FormatOptions) str() string { diff --git a/vlib/builtin/builtin.c.v b/vlib/builtin/builtin.c.v index 5b585fa9e5..1864cb61cd 100644 --- a/vlib/builtin/builtin.c.v +++ b/vlib/builtin/builtin.c.v @@ -268,13 +268,28 @@ fn _write_buf_to_fd(fd int, buf &u8, buf_len int) { if buf_len <= 0 { return } - unsafe { - mut ptr := buf - mut remaining_bytes := buf_len - for remaining_bytes > 0 { - x := C.write(fd, ptr, remaining_bytes) - ptr += x - remaining_bytes -= x + mut ptr := unsafe { buf } + mut remaining_bytes := isize(buf_len) + mut x := isize(0) + $if freestanding || vinix { + unsafe { + for remaining_bytes > 0 { + x = C.write(fd, ptr, remaining_bytes) + ptr += x + remaining_bytes -= x + } + } + } $else { + mut stream := voidptr(C.stdout) + if fd == 2 { + stream = voidptr(C.stderr) + } + unsafe { + for remaining_bytes > 0 { + x = isize(C.fwrite(ptr, 1, remaining_bytes, stream)) + ptr += x + remaining_bytes -= x + } } } } diff --git a/vlib/term/control.v b/vlib/term/control.v index e5f410771d..35760e947d 100644 --- a/vlib/term/control.v +++ b/vlib/term/control.v @@ -16,6 +16,7 @@ module term // y is the y coordinate pub fn set_cursor_position(c Coord) { print('\x1b[$c.y;$c.x' + 'H') + flush_stdout() } // n is number of cells @@ -25,6 +26,7 @@ pub fn set_cursor_position(c Coord) { // direction: D is backward / West pub fn move(n int, direction string) { print('\x1b[$n$direction') + flush_stdout() } pub fn cursor_up(n int) { @@ -50,6 +52,7 @@ pub fn cursor_back(n int) { pub fn erase_display(t string) { print('\x1b[' + t + 'J') + flush_stdout() } pub fn erase_toend() { @@ -63,6 +66,7 @@ pub fn erase_tobeg() { // clears entire screen and returns cursor to top left-corner pub fn erase_clear() { print('\033[H\033[J') + flush_stdout() } pub fn erase_del_clear() { @@ -75,6 +79,7 @@ pub fn erase_del_clear() { // Note: Cursor position does not change pub fn erase_line(t string) { print('\x1b[' + t + 'K') + flush_stdout() } pub fn erase_line_toend() { @@ -92,11 +97,13 @@ pub fn erase_line_clear() { // Will make cursor appear if not visible pub fn show_cursor() { print('\x1b[?25h') + flush_stdout() } // Will make cursor invisible pub fn hide_cursor() { print('\x1b[?25l') + flush_stdout() } // clear_previous_line - useful for progressbars. @@ -105,4 +112,5 @@ pub fn hide_cursor() { // the previous content. pub fn clear_previous_line() { print('\r\x1b[1A\x1b[2K') + flush_stdout() } diff --git a/vlib/term/term_nix.c.v b/vlib/term/term_nix.c.v index 9008e5248a..3da5fa2741 100644 --- a/vlib/term/term_nix.c.v +++ b/vlib/term/term_nix.c.v @@ -52,6 +52,7 @@ pub fn get_cursor_position() ?Coord { unsafe { C.tcsetattr(0, C.TCSANOW, &state) } print('\e[6n') + flush_stdout() mut x := 0 mut y := 0 @@ -87,6 +88,7 @@ pub fn set_terminal_title(title string) bool { print('\033]0') print(title) print('\007') + flush_stdout() return true } @@ -94,4 +96,5 @@ pub fn set_terminal_title(title string) bool { pub fn clear() { print('\x1b[2J') print('\x1b[H') + flush_stdout() } diff --git a/vlib/term/ui/input_nix.c.v b/vlib/term/ui/input_nix.c.v index f2f50724d8..c4461d078b 100644 --- a/vlib/term/ui/input_nix.c.v +++ b/vlib/term/ui/input_nix.c.v @@ -32,12 +32,14 @@ pub fn init(cfg Config) &Context { fn save_title() { // restore the previously saved terminal title print('\x1b[22;0t') + flush_stdout() } [inline] fn load_title() { // restore the previously saved terminal title print('\x1b[23;0t') + flush_stdout() } pub fn (mut ctx Context) run() ? { diff --git a/vlib/term/ui/input_windows.c.v b/vlib/term/ui/input_windows.c.v index 751fb94104..cafb62fbba 100644 --- a/vlib/term/ui/input_windows.c.v +++ b/vlib/term/ui/input_windows.c.v @@ -26,6 +26,7 @@ fn restore_terminal_state() { // clear the terminal and set the cursor to the origin print('\x1b[2J\x1b[3J') print('\x1b[?1049l') + flush_stdout() } C.SetConsoleMode(ui.ctx_ptr.stdin_handle, ui.stdin_at_startup) } @@ -65,6 +66,7 @@ pub fn init(cfg Config) &Context { print('\x1b[?1049h') // clear the terminal and set the cursor to the origin print('\x1b[2J\x1b[3J\x1b[1;1H') + flush_stdout() } if ctx.cfg.hide_cursor { @@ -74,6 +76,7 @@ pub fn init(cfg Config) &Context { if ctx.cfg.window_title != '' { print('\x1b]0;$ctx.cfg.window_title\x07') + flush_stdout() } unsafe { @@ -317,10 +320,12 @@ fn (mut ctx Context) parse_events() { fn save_title() { // restore the previously saved terminal title print('\x1b[22;0t') + flush_stdout() } [inline] fn load_title() { // restore the previously saved terminal title print('\x1b[23;0t') + flush_stdout() } diff --git a/vlib/term/ui/termios_nix.c.v b/vlib/term/ui/termios_nix.c.v index 024dd8de67..67fc714180 100644 --- a/vlib/term/ui/termios_nix.c.v +++ b/vlib/term/ui/termios_nix.c.v @@ -79,6 +79,7 @@ fn (mut ctx Context) termios_setup() ? { if ctx.cfg.window_title != '' { print('\x1b]0;$ctx.cfg.window_title\x07') + flush_stdout() } if !ctx.cfg.skip_init_checks { @@ -90,6 +91,7 @@ fn (mut ctx Context) termios_setup() ? { // feature-test the SU spec sx, sy := get_cursor_position() print('$bsu$esu') + flush_stdout() ex, ey := get_cursor_position() if sx == ex && sy == ey { // the terminal either ignored or handled the sequence properly, enable SU @@ -108,11 +110,14 @@ fn (mut ctx Context) termios_setup() ? { C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &termios) // enable mouse input print('\x1b[?1003h\x1b[?1006h') + flush_stdout() if ctx.cfg.use_alternate_buffer { // switch to the alternate buffer print('\x1b[?1049h') + flush_stdout() // clear the terminal and set the cursor to the origin print('\x1b[2J\x1b[3J\x1b[1;1H') + flush_stdout() } ctx.window_height, ctx.window_width = get_terminal_size() @@ -162,6 +167,7 @@ fn (mut ctx Context) termios_setup() ? { fn get_cursor_position() (int, int) { print('\033[6n') + flush_stdout() mut s := '' unsafe { buf := malloc_noscan(25) @@ -183,8 +189,10 @@ fn supports_truecolor() bool { } // set the bg color to some arbirtrary value (#010203), assumed not to be the default print('\x1b[48:2:1:2:3m') + flush_stdout() // andquery the current color print('\x1bP\$qm\x1b\\') + flush_stdout() mut s := '' unsafe { buf := malloc_noscan(25) @@ -199,6 +207,7 @@ fn termios_reset() { // C.TCSANOW ?? C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup) print('\x1b[?1003l\x1b[?1006l\x1b[?25h') + flush_stdout() c := ctx_ptr if unsafe { c != 0 } && c.cfg.use_alternate_buffer { print('\x1b[?1049l') diff --git a/vlib/term/ui/ui.v b/vlib/term/ui/ui.v index 512bc2c23b..bfe8aa8080 100644 --- a/vlib/term/ui/ui.v +++ b/vlib/term/ui/ui.v @@ -116,6 +116,7 @@ pub fn (mut ctx Context) clear() { [inline] pub fn (mut ctx Context) set_window_title(s string) { print('\x1b]0;$s\x07') + flush_stdout() } // draw_point draws a point at position `x`,`y`.