History

win32: cache GetConsoleMode state for stdout/stderr

GetConsoleMode() can be quite slow and in mpv the mode never changes, so we can just check it once. Fixes performance when writing lots of logs to terminal.

Kacper Michajłow committed 2 years ago

Commit 8ee25db1 parent 7bdd6735 files · +45 −33Browse files

Unified · Split

5 files
  1. osdep/io.c +0 −24
  2. osdep/terminal-win.c +41 −7
  3. osdep/terminal.h +1 −0
  4. test/test_utils.c +3 −1
  5. test/test_utils.h +0 −1
osdep/io.c+0−24
@@ -304,30 +304,6 @@ static int mp_vfprintf(FILE *stream, const char *format, va_list args) · 303 unmodified lines
304304 return vfprintf(stream, format, args);
305305 }
306306 #else
307−static int mp_check_console(HANDLE wstream)
308−{
309− if (wstream != INVALID_HANDLE_VALUE) {
310− unsigned int filetype = GetFileType(wstream);
311−
312− if (!((filetype == FILE_TYPE_UNKNOWN) &&
313− (GetLastError() != ERROR_SUCCESS)))
314− {
315− filetype &= ~(FILE_TYPE_REMOTE);
316−
317− if (filetype == FILE_TYPE_CHAR) {
318− DWORD ConsoleMode;
319− int ret = GetConsoleMode(wstream, &ConsoleMode);
320−
321− if (!(!ret && (GetLastError() == ERROR_INVALID_HANDLE))) {
322− // This seems to be a console
323− return 1;
324− }
325− }
326− }
327− }
328−
329− return 0;
330−}
331307
332308 static int mp_vfprintf(FILE *stream, const char *format, va_list args)
333309 {
osdep/terminal-win.c+41−7
@@ -53,20 +53,16 @@ static void attempt_native_out_vt(HANDLE hOut, DWORD basemode) · 52 unmodified lines
5353 SetConsoleMode(hOut, basemode);
5454 }
5555
56−static bool is_native_out_vt(HANDLE hOut)
57−{
58− DWORD cmode;
59− return GetConsoleMode(hOut, &cmode) &&
60− (cmode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) &&
61− !(cmode & DISABLE_NEWLINE_AUTO_RETURN);
62−}
6356
57+#define hSTDIN GetStdHandle(STD_INPUT_HANDLE)
6458 #define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE)
6559 #define hSTDERR GetStdHandle(STD_ERROR_HANDLE)
6660
6761 #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
6862 #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
6963
64+static bool is_console[STDERR_FILENO + 1];
65+static bool is_vt[STDERR_FILENO + 1];
7066 static short stdoutAttrs = 0; // copied from the screen buffer on init
7167 static const unsigned char ansi2win32[8] = {
7268 0,
@@ -94,6 +90,23 @@ static HANDLE death; · 21 unmodified lines
9490 static mp_thread input_thread;
9591 static struct input_ctx *input_ctx;
9692
93+static bool is_native_out_vt_internal(HANDLE hOut)
94+{
95+ DWORD cmode;
96+ return GetConsoleMode(hOut, &cmode) &&
97+ (cmode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) &&
98+ !(cmode & DISABLE_NEWLINE_AUTO_RETURN);
99+}
100+
101+static bool is_native_out_vt(HANDLE hOut)
102+{
103+ if (hOut == hSTDOUT)
104+ return is_vt[STDOUT_FILENO];
105+ if (hOut == hSTDERR)
106+ return is_vt[STDERR_FILENO];
107+ return is_native_out_vt_internal(hOut);
108+}
109+
97110 void terminal_get_size(int *w, int *h)
98111 {
99112 CONSOLE_SCREEN_BUFFER_INFO cinfo;
@@ -360,6 +373,17 @@ static bool is_a_console(HANDLE h) · 260 unmodified lines
360373 return GetConsoleMode(h, &(DWORD){0});
361374 }
362375
376+bool mp_check_console(void *handle)
377+{
378+ if (handle == hSTDIN)
379+ return is_console[STDIN_FILENO];
380+ if (handle == hSTDOUT)
381+ return is_console[STDOUT_FILENO];
382+ if (handle == hSTDERR)
383+ return is_console[STDERR_FILENO];
384+ return is_a_console(handle);
385+}
386+
363387 static void reopen_console_handle(DWORD std, int fd, FILE *stream)
364388 {
365389 HANDLE handle = GetStdHandle(std);
@@ -419,6 +443,16 @@ void terminal_init(void) · 53 unmodified lines
419443 cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
420444 attempt_native_out_vt(hSTDOUT, cmode);
421445 attempt_native_out_vt(hSTDERR, cmode);
446+
447+ // Init for mp_check_console(), this never changes during runtime
448+ is_console[STDIN_FILENO] = is_a_console(hSTDIN);
449+ is_console[STDOUT_FILENO] = is_a_console(hSTDOUT);
450+ is_console[STDERR_FILENO] = is_a_console(hSTDERR);
451+
452+ // Init for is_native_out_vt(), this is never disabled/changed during runtime
453+ is_vt[STDOUT_FILENO] = is_native_out_vt_internal(hSTDOUT);
454+ is_vt[STDERR_FILENO] = is_native_out_vt_internal(hSTDERR);
455+
422456 GetConsoleScreenBufferInfo(hSTDOUT, &cinfo);
423457 stdoutAttrs = cinfo.wAttributes;
424458 }
osdep/terminal.h+1−0
@@ -53,6 +53,7 @@ void terminal_get_size2(int *rows, int *cols, int *px_width, int *px_height); · 52 unmodified lines
5353
5454 // Windows only.
5555 void mp_write_console_ansi(void *wstream, char *buf);
56+bool mp_check_console(void *handle);
5657
5758 /* Windows-only function to attach to the parent process's console */
5859 bool terminal_try_attach(void);
test/test_utils.c+3−1
@@ -4,6 +4,7 @@ · 3 unmodified lines
44 #include "options/m_option.h"
55 #include "options/path.h"
66 #include "osdep/subprocess.h"
7+#include "osdep/terminal.h"
78 #include "test_utils.h"
89
910 #ifdef NDEBUG
@@ -106,7 +107,8 @@ void mp_msg(struct mp_log *log, int lev, const char *format, ...) {}; · 96 unmodified lines
106107 int mp_msg_find_level(const char *s) {return 0;};
107108 int mp_msg_level(struct mp_log *log) {return 0;};
108109 void mp_msg_set_max_level(struct mp_log *log, int lev) {};
109−void mp_write_console_ansi(void) {};
110+void mp_write_console_ansi(void *wstream, char *buf) {};
111+bool mp_check_console(void *handle) { return false; };
110112 void mp_set_avdict(AVDictionary **dict, char **kv) {};
111113 struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,
112114 const char *name) { return NULL; };
test/test_utils.h+0−1
@@ -52,6 +52,5 @@ void mp_msg(struct mp_log *log, int lev, const char *format, ...) · 51 unmodified lines
5252 int mp_msg_find_level(const char *s);
5353 int mp_msg_level(struct mp_log *log);
5454 void mp_msg_set_max_level(struct mp_log *log, int lev);
55−void mp_write_console_ansi(void);
5655 typedef struct AVDictionary AVDictionary;
5756 void mp_set_avdict(AVDictionary **dict, char **kv);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t