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
304 return vfprintf(stream, format, args);304 return vfprintf(stream, format, args);
305}305}
306#else306#else
307static 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}
331 307
332static int mp_vfprintf(FILE *stream, const char *format, va_list args)308static int mp_vfprintf(FILE *stream, const char *format, va_list args)
333{309{
osdep/terminal-win.c+41−7
@@ -53,20 +53,16 @@ static void attempt_native_out_vt(HANDLE hOut, DWORD basemode) · 52 unmodified lines
53 SetConsoleMode(hOut, basemode);53 SetConsoleMode(hOut, basemode);
54}54}
55 55
56static 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}
63 56
57#define hSTDIN GetStdHandle(STD_INPUT_HANDLE)
64#define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE)58#define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE)
65#define hSTDERR GetStdHandle(STD_ERROR_HANDLE)59#define hSTDERR GetStdHandle(STD_ERROR_HANDLE)
66 60
67#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)61#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
68#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)62#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
69 63
64static bool is_console[STDERR_FILENO + 1];
65static bool is_vt[STDERR_FILENO + 1];
70static short stdoutAttrs = 0; // copied from the screen buffer on init66static short stdoutAttrs = 0; // copied from the screen buffer on init
71static const unsigned char ansi2win32[8] = {67static const unsigned char ansi2win32[8] = {
72 0,68 0,
@@ -94,6 +90,23 @@ static HANDLE death; · 21 unmodified lines
94static mp_thread input_thread;90static mp_thread input_thread;
95static struct input_ctx *input_ctx;91static struct input_ctx *input_ctx;
96 92
93static 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
101static 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
97void terminal_get_size(int *w, int *h)110void terminal_get_size(int *w, int *h)
98{111{
99 CONSOLE_SCREEN_BUFFER_INFO cinfo;112 CONSOLE_SCREEN_BUFFER_INFO cinfo;
@@ -360,6 +373,17 @@ static bool is_a_console(HANDLE h) · 260 unmodified lines
360 return GetConsoleMode(h, &(DWORD){0});373 return GetConsoleMode(h, &(DWORD){0});
361}374}
362 375
376bool 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
363static void reopen_console_handle(DWORD std, int fd, FILE *stream)387static void reopen_console_handle(DWORD std, int fd, FILE *stream)
364{388{
365 HANDLE handle = GetStdHandle(std);389 HANDLE handle = GetStdHandle(std);
@@ -419,6 +443,16 @@ void terminal_init(void) · 53 unmodified lines
419 cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);443 cmode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
420 attempt_native_out_vt(hSTDOUT, cmode);444 attempt_native_out_vt(hSTDOUT, cmode);
421 attempt_native_out_vt(hSTDERR, cmode);445 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
422 GetConsoleScreenBufferInfo(hSTDOUT, &cinfo);456 GetConsoleScreenBufferInfo(hSTDOUT, &cinfo);
423 stdoutAttrs = cinfo.wAttributes;457 stdoutAttrs = cinfo.wAttributes;
424}458}
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
53 53
54// Windows only.54// Windows only.
55void mp_write_console_ansi(void *wstream, char *buf);55void mp_write_console_ansi(void *wstream, char *buf);
56bool mp_check_console(void *handle);
56 57
57/* Windows-only function to attach to the parent process's console */58/* Windows-only function to attach to the parent process's console */
58bool terminal_try_attach(void);59bool terminal_try_attach(void);
test/test_utils.c+3−1
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#include "options/m_option.h"4#include "options/m_option.h"
5#include "options/path.h"5#include "options/path.h"
6#include "osdep/subprocess.h"6#include "osdep/subprocess.h"
7#include "osdep/terminal.h"
7#include "test_utils.h"8#include "test_utils.h"
8 9
9#ifdef NDEBUG10#ifdef NDEBUG
@@ -106,7 +107,8 @@ void mp_msg(struct mp_log *log, int lev, const char *format, ...) {}; · 96 unmodified lines
106int mp_msg_find_level(const char *s) {return 0;};107int mp_msg_find_level(const char *s) {return 0;};
107int mp_msg_level(struct mp_log *log) {return 0;};108int mp_msg_level(struct mp_log *log) {return 0;};
108void mp_msg_set_max_level(struct mp_log *log, int lev) {};109void mp_msg_set_max_level(struct mp_log *log, int lev) {};
109void mp_write_console_ansi(void) {};110void mp_write_console_ansi(void *wstream, char *buf) {};
111bool mp_check_console(void *handle) { return false; };
110void mp_set_avdict(AVDictionary **dict, char **kv) {};112void mp_set_avdict(AVDictionary **dict, char **kv) {};
111struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,113struct mp_log *mp_log_new(void *talloc_ctx, struct mp_log *parent,
112 const char *name) { return NULL; };114 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
52int mp_msg_find_level(const char *s);52int mp_msg_find_level(const char *s);
53int mp_msg_level(struct mp_log *log);53int mp_msg_level(struct mp_log *log);
54void mp_msg_set_max_level(struct mp_log *log, int lev);54void mp_msg_set_max_level(struct mp_log *log, int lev);
55void mp_write_console_ansi(void);
56typedef struct AVDictionary AVDictionary;55typedef struct AVDictionary AVDictionary;
57void mp_set_avdict(AVDictionary **dict, char **kv);56void 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