When playing a video, 55% of CPU used in strlen, callgraph flip_page: ta_talloc_strdup_append , ta_talloc_asprintf_append and ta_talloc_strndup_append . Before the fix: 2 fps when playing 1080p 24 fps video (--vo-kitty-use-shm=no), 24 fps after the fix. video/out/kitty: move bstr cmd to priv
Unified · Split
| @@ -48,7 +48,7 @@ · 47 unmodified lines | |||
| 48 | #define DEFAULT_WIDTH 80 | 48 | #define DEFAULT_WIDTH 80 |
| 49 | #define DEFAULT_HEIGHT 25 | 49 | #define DEFAULT_HEIGHT 25 |
| 50 | 50 | ||
| 51 | static inline void write_str(const char *s) | 51 | static inline void write_bstr(bstr bs) |
| 52 | { | 52 | { |
| 53 | // On POSIX platforms, write() is the fastest method. It also is the only | 53 | // On POSIX platforms, write() is the fastest method. It also is the only |
| 54 | // one that allows atomic writes so mpv’s output will not be interrupted | 54 | // one that allows atomic writes so mpv’s output will not be interrupted |
| @@ -57,25 +57,31 @@ static inline void write_str(const char *s) · 2 unmodified lines | |||
| 57 | // exceeding PIPE_BUF, but at least Linux does seem to implement it that | 57 | // exceeding PIPE_BUF, but at least Linux does seem to implement it that |
| 58 | // way. | 58 | // way. |
| 59 | #if HAVE_POSIX | 59 | #if HAVE_POSIX |
| 60 | int remain = strlen(s); | 60 | size_t remain = bs.len; |
| 61 | unsigned char *pos = bs.start; | ||
| 61 | while (remain > 0) { | 62 | while (remain > 0) { |
| 62 | ssize_t written = write(STDOUT_FILENO, s, remain); | 63 | ssize_t written = write(STDOUT_FILENO, pos, remain); |
| 63 | if (written < 0) | 64 | if (written < 0) |
| 64 | return; | 65 | return; |
| 65 | remain -= written; | 66 | remain -= written; |
| 66 | s += written; | 67 | pos += written; |
| 67 | } | 68 | } |
| 68 | #else | 69 | #else |
| 69 | printf("%s", s); | 70 | fwrite(bs.start, 1, bs.len, stdout); |
| 70 | fflush(stdout); | 71 | fflush(stdout); |
| 71 | #endif | 72 | #endif |
| 72 | } | 73 | } |
| 73 | 74 | ||
| 75 | static inline void write_str(unsigned char* s) | ||
| 76 | { | ||
| 77 | write_bstr(bstr0(s)); | ||
| 78 | } | ||
| 79 | |||
| 74 | #define KITTY_ESC_IMG "\033_Ga=T,f=24,s=%d,v=%d,C=1,q=2,m=1;" | 80 | #define KITTY_ESC_IMG "\033_Ga=T,f=24,s=%d,v=%d,C=1,q=2,m=1;" |
| 75 | #define KITTY_ESC_IMG_SHM "\033_Ga=T,t=s,f=24,s=%d,v=%d,C=1,q=2,m=1;%s\033\\" | 81 | #define KITTY_ESC_IMG_SHM "\033_Ga=T,t=s,f=24,s=%d,v=%d,C=1,q=2,m=1;%s\033\\" |
| 76 | #define KITTY_ESC_CONTINUE "\033_Gm=%d;" | 82 | #define KITTY_ESC_CONTINUE "\033_Gm=%d;" |
| 77 | #define KITTY_ESC_END "\033\\" | 83 | static const bstr KITTY_ESC_END = bstr0_lit("\033\\"); |
| 78 | #define KITTY_ESC_DELETE_ALL "\033_Ga=d;\033\\" | 84 | static const bstr KITTY_ESC_DELETE_ALL = bstr0_lit("\033_Ga=d;\033\\"); |
| 79 | 85 | ||
| 80 | struct vo_kitty_opts { | 86 | struct vo_kitty_opts { |
| 81 | int width, height, top, left, rows, cols; | 87 | int width, height, top, left, rows, cols; |
| @@ -91,6 +97,7 @@ struct priv { · 9 unmodified lines | |||
| 91 | char *shm_path, *shm_path_b64; | 97 | char *shm_path, *shm_path_b64; |
| 92 | int buffer_size, output_size; | 98 | int buffer_size, output_size; |
| 93 | int shm_fd; | 99 | int shm_fd; |
| 100 | bstr cmd; | ||
| 94 | 101 | ||
| 95 | int left, top, width, height, cols, rows; | 102 | int left, top, width, height, cols, rows; |
| 96 | 103 | ||
| @@ -126,6 +133,7 @@ static void free_bufs(struct vo* vo) · 29 unmodified lines | |||
| 126 | 133 | ||
| 127 | talloc_free(p->frame); | 134 | talloc_free(p->frame); |
| 128 | talloc_free(p->output); | 135 | talloc_free(p->output); |
| 136 | talloc_free(p->cmd.start); | ||
| 129 | 137 | ||
| 130 | if (p->opts.use_shm) { | 138 | if (p->opts.use_shm) { |
| 131 | close_shm(p); | 139 | close_shm(p); |
| @@ -177,7 +185,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) · 45 unmodified lines | |||
| 177 | struct priv *p = vo->priv; | 185 | struct priv *p = vo->priv; |
| 178 | 186 | ||
| 179 | vo->want_redraw = true; | 187 | vo->want_redraw = true; |
| 180 | write_str(KITTY_ESC_DELETE_ALL); | 188 | write_bstr(KITTY_ESC_DELETE_ALL); |
| 181 | if (p->opts.config_clear) | 189 | if (p->opts.config_clear) |
| 182 | write_str(TERM_ESC_CLEAR_SCREEN); | 190 | write_str(TERM_ESC_CLEAR_SCREEN); |
| 183 | 191 | ||
| @@ -292,36 +300,40 @@ done: · 108 unmodified lines | |||
| 292 | 300 | ||
| 293 | static void flip_page(struct vo *vo) | 301 | static void flip_page(struct vo *vo) |
| 294 | { | 302 | { |
| 295 | struct priv* p = vo->priv; | 303 | struct priv *p = vo->priv; |
| 296 | 304 | if (!p->buffer) | |
| 297 | if (p->buffer == NULL) | ||
| 298 | return; | 305 | return; |
| 299 | 306 | ||
| 300 | char *cmd = talloc_asprintf(NULL, TERM_ESC_GOTO_YX, p->top, p->left); | 307 | p->cmd.len = 0; |
| 308 | |||
| 309 | // Start with ESC to position the cursor | ||
| 310 | bstr_xappend_asprintf(NULL, &p->cmd, TERM_ESC_GOTO_YX, p->top, p->left); | ||
| 301 | 311 | ||
| 302 | if (p->opts.use_shm) { | 312 | if (p->opts.use_shm) { |
| 303 | cmd = talloc_asprintf_append(cmd, KITTY_ESC_IMG_SHM, p->width, p->height, p->shm_path_b64); | 313 | bstr_xappend_asprintf(NULL, &p->cmd, KITTY_ESC_IMG_SHM, |
| 314 | p->width, p->height, p->shm_path_b64); | ||
| 304 | } else { | 315 | } else { |
| 305 | if (p->output == NULL) { | 316 | if (!p->output) { |
| 306 | talloc_free(cmd); | ||
| 307 | return; | 317 | return; |
| 308 | } | 318 | } |
| 309 | 319 | ||
| 310 | cmd = talloc_asprintf_append(cmd, KITTY_ESC_IMG, p->width, p->height); | 320 | bstr_xappend_asprintf(NULL, &p->cmd, KITTY_ESC_IMG, p->width, p->height); |
| 311 | for (int offset = 0, noffset;; offset += noffset) { | 321 | |
| 312 | if (offset) | 322 | for (int offset = 0; offset < p->output_size; ) { |
| 313 | cmd = talloc_asprintf_append(cmd, KITTY_ESC_CONTINUE, offset < p->output_size); | 323 | int chunk = MPMIN(4096, p->output_size - offset); |
| 314 | noffset = MPMIN(4096, p->output_size - offset); | 324 | |
| 315 | cmd = talloc_strndup_append(cmd, p->output + offset, noffset); | 325 | if (offset > 0) |
| 316 | cmd = talloc_strdup_append(cmd, KITTY_ESC_END); | 326 | bstr_xappend_asprintf(NULL, &p->cmd, KITTY_ESC_CONTINUE, |
| 327 | offset + chunk < p->output_size); | ||
| 317 | 328 | ||
| 318 | if (offset >= p->output_size) | 329 | // Append at max chunk bytes |
| 319 | break; | 330 | bstr_xappend(NULL, &p->cmd, (bstr){p->output + offset, chunk}); |
| 331 | bstr_xappend(NULL, &p->cmd, KITTY_ESC_END); | ||
| 332 | offset += chunk; | ||
| 320 | } | 333 | } |
| 321 | } | 334 | } |
| 322 | 335 | ||
| 323 | write_str(cmd); | 336 | write_bstr(p->cmd); |
| 324 | talloc_free(cmd); | ||
| 325 | 337 | ||
| 326 | #if HAVE_POSIX | 338 | #if HAVE_POSIX |
| 327 | if (p->opts.use_shm) | 339 | if (p->opts.use_shm) |