mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Swap watermarks from high (4096) to low (128) when we get full buffers
into the read callback several times in succession; swap back when we see empty buffers several times. This hopefully limits how much programs that print a lot for a long period can monopolize tmux (like large, fast compiling), without penalizing programs that print a lot briefly (like most curses applications). Helps a lot for me, the actual numbers may need tweaking later.
This commit is contained in:
		
							
								
								
									
										17
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -59,8 +59,18 @@ struct tmuxproc; | ||||
| /* Automatic name refresh interval, in microseconds. Must be < 1 second. */ | ||||
| #define NAME_INTERVAL 500000 | ||||
|  | ||||
| /* The maximum amount of data to hold from a pty (the event high watermark). */ | ||||
| #define READ_SIZE 4096 | ||||
| /* | ||||
|  * Event watermarks. We start with FAST then if we hit full size for HITS reads | ||||
|  * in succession switch to SLOW, and return when we hit EMPTY the same number | ||||
|  * of times. | ||||
|  */ | ||||
| #define READ_FAST_SIZE 4096 | ||||
| #define READ_SLOW_SIZE 128 | ||||
|  | ||||
| #define READ_FULL_SIZE (4096 - 16) | ||||
| #define READ_EMPTY_SIZE 16 | ||||
|  | ||||
| #define READ_CHANGE_HITS 3 | ||||
|  | ||||
| /* Attribute to make gcc check printf-like arguments. */ | ||||
| #define printflike(a, b) __attribute__ ((format (printf, a, b))) | ||||
| @@ -884,6 +894,9 @@ struct window_pane { | ||||
| 	int		 fd; | ||||
| 	struct bufferevent *event; | ||||
|  | ||||
| 	u_int		 wmark_size; | ||||
| 	u_int		 wmark_hits; | ||||
|  | ||||
| 	struct input_ctx *ictx; | ||||
|  | ||||
| 	struct grid_cell colgc; | ||||
|   | ||||
							
								
								
									
										52
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								window.c
									
									
									
									
									
								
							| @@ -56,15 +56,17 @@ struct windows windows; | ||||
|  | ||||
| /* Global panes tree. */ | ||||
| struct window_pane_tree all_window_panes; | ||||
| u_int	next_window_pane_id; | ||||
| u_int	next_window_id; | ||||
| u_int	next_active_point; | ||||
| static u_int	next_window_pane_id; | ||||
| static u_int	next_window_id; | ||||
| static u_int	next_active_point; | ||||
|  | ||||
| void	window_pane_timer_callback(int, short, void *); | ||||
| void	window_pane_read_callback(struct bufferevent *, void *); | ||||
| void	window_pane_error_callback(struct bufferevent *, short, void *); | ||||
| static void	window_pane_set_watermark(struct window_pane *, size_t); | ||||
|  | ||||
| struct window_pane *window_pane_choose_best(struct window_pane **, u_int); | ||||
| static void	window_pane_read_callback(struct bufferevent *, void *); | ||||
| static void	window_pane_error_callback(struct bufferevent *, short, void *); | ||||
|  | ||||
| static struct window_pane *window_pane_choose_best(struct window_pane **, | ||||
| 		    u_int); | ||||
|  | ||||
| RB_GENERATE(windows, window, entry, window_cmp); | ||||
|  | ||||
| @@ -809,6 +811,14 @@ window_pane_destroy(struct window_pane *wp) | ||||
| 	free(wp); | ||||
| } | ||||
|  | ||||
| static void | ||||
| window_pane_set_watermark(struct window_pane *wp, size_t size) | ||||
| { | ||||
| 	wp->wmark_hits = 0; | ||||
| 	wp->wmark_size = size; | ||||
| 	bufferevent_setwatermark(wp->event, EV_READ, 0, size); | ||||
| } | ||||
|  | ||||
| int | ||||
| window_pane_spawn(struct window_pane *wp, int argc, char **argv, | ||||
|     const char *path, const char *shell, const char *cwd, struct environ *env, | ||||
| @@ -915,25 +925,37 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv, | ||||
| 	wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL, | ||||
| 	    window_pane_error_callback, wp); | ||||
|  | ||||
| 	bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE); | ||||
| 	window_pane_set_watermark(wp, READ_FAST_SIZE); | ||||
| 	bufferevent_enable(wp->event, EV_READ|EV_WRITE); | ||||
|  | ||||
| 	free(cmd); | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| void | ||||
| static void | ||||
| window_pane_read_callback(__unused struct bufferevent *bufev, void *data) | ||||
| { | ||||
| 	struct window_pane	*wp = data; | ||||
| 	struct evbuffer		*evb = wp->event->input; | ||||
| 	size_t			 size = EVBUFFER_LENGTH(evb); | ||||
| 	char			*new_data; | ||||
| 	size_t			 new_size; | ||||
|  | ||||
| 	log_debug("%%%u has %zu bytes (of %zu)", wp->id, EVBUFFER_LENGTH(evb), | ||||
| 	    (size_t)READ_SIZE); | ||||
| 	if (wp->wmark_size == READ_FAST_SIZE) { | ||||
| 		if (size > READ_FULL_SIZE) | ||||
| 			wp->wmark_hits++; | ||||
| 		if (wp->wmark_hits == READ_CHANGE_HITS) | ||||
| 			window_pane_set_watermark(wp, READ_SLOW_SIZE); | ||||
| 	} else if (wp->wmark_size == READ_SLOW_SIZE) { | ||||
| 		if (size < READ_EMPTY_SIZE) | ||||
| 			wp->wmark_hits++; | ||||
| 		if (wp->wmark_hits == READ_CHANGE_HITS) | ||||
| 			window_pane_set_watermark(wp, READ_FAST_SIZE); | ||||
| 	} | ||||
| 	log_debug("%%%u has %zu bytes (of %u, %u hits)", wp->id, size, | ||||
| 	    wp->wmark_size, wp->wmark_hits); | ||||
|  | ||||
| 	new_size = EVBUFFER_LENGTH(evb) - wp->pipe_off; | ||||
| 	new_size = size - wp->pipe_off; | ||||
| 	if (wp->pipe_fd != -1 && new_size > 0) { | ||||
| 		new_data = EVBUFFER_DATA(evb) + wp->pipe_off; | ||||
| 		bufferevent_write(wp->pipe_event, new_data, new_size); | ||||
| @@ -941,10 +963,10 @@ window_pane_read_callback(__unused struct bufferevent *bufev, void *data) | ||||
|  | ||||
| 	input_parse(wp); | ||||
|  | ||||
| 	wp->pipe_off = EVBUFFER_LENGTH(evb); | ||||
| 	wp->pipe_off = size; | ||||
| } | ||||
|  | ||||
| void | ||||
| static void | ||||
| window_pane_error_callback(__unused struct bufferevent *bufev, | ||||
|     __unused short what, void *data) | ||||
| { | ||||
| @@ -1182,7 +1204,7 @@ window_pane_search(struct window_pane *wp, const char *searchstr, | ||||
| } | ||||
|  | ||||
| /* Get MRU pane from a list. */ | ||||
| struct window_pane * | ||||
| static struct window_pane * | ||||
| window_pane_choose_best(struct window_pane **list, u_int size) | ||||
| { | ||||
| 	struct window_pane	*next, *best; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm