Is anyone else running with this? Does it help?
On Sat, Dec 24, 2011 at 08:15:54AM +0000, Nicholas Marriott wrote: > Hi > > Here is a new diff with a window option (rate-limit, 0 is off) and man > page bits. > > I'd like to be able to fix this in a way where we can turn it on by > default but I don't want to do it now. > > Even with rate-limit of 100K, running "top" is visibly slower than with > rate-limit disabled. I don't think that is acceptable. > > The lowest value before top seems to open with no delay is about 250000 > but this is on a relatively small (125x33) terminal - at work for > example my terminal is probably 20 times as big. This is on a LAN though > so I'm not sure what impact a slow link would have. > > Unfortunately, the only terminal I can test right now where this option > helps me with ssh and a rate-limit of 100K is gnome-terminal. In xterm > and rxvt it seems to make no difference (xterm remains slow, rxvt > remains fast). > > Also unfortunately, GNU screen behaviour matches that of tmux with > rate-limit 0 in all the terminals. So I can't reproduce and figure out > how screen is doing it. > > Anyway, can you give this a quick spin and make sure changing the option > still helps you. If so, I will commit it with default disabled and see > if over time some consensus about the best default appears, or I can see > better behaviour from screen, or a better approach occurs to me. > > The disadvantage of this method is it that if you have multiple panes, > they can all use the full bandwidth, so the total with 10 panes is 10 * > rate-limit. Having fast producers in multiple panes would be pretty > rare though. > > > Index: cmd-paste-buffer.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/cmd-paste-buffer.c,v > retrieving revision 1.16 > diff -u -p -r1.16 cmd-paste-buffer.c > --- cmd-paste-buffer.c 4 Jan 2011 00:42:47 -0000 1.16 > +++ cmd-paste-buffer.c 24 Dec 2011 07:59:45 -0000 > @@ -112,11 +112,11 @@ cmd_paste_buffer_filter( > seplen = strlen(sep); > while ((lf = memchr(data, '\n', end - data)) != NULL) { > if (lf != data) > - bufferevent_write(wp->event, data, lf - data); > - bufferevent_write(wp->event, sep, seplen); > + window_pane_write(wp, data, lf - data); > + window_pane_write(wp, sep, seplen); > data = lf + 1; > } > > if (end != data) > - bufferevent_write(wp->event, data, end - data); > + window_pane_write(wp, data, end - data); > } > Index: cmd-pipe-pane.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/cmd-pipe-pane.c,v > retrieving revision 1.21 > diff -u -p -r1.21 cmd-pipe-pane.c > --- cmd-pipe-pane.c 27 Oct 2011 22:41:03 -0000 1.21 > +++ cmd-pipe-pane.c 24 Dec 2011 07:59:45 -0000 > @@ -120,7 +120,7 @@ cmd_pipe_pane_exec(struct cmd *self, str > close(pipe_fd[1]); > > wp->pipe_fd = pipe_fd[0]; > - wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); > + wp->pipe_off = EVBUFFER_LENGTH(wp->read_buf); > > wp->pipe_event = bufferevent_new(wp->pipe_fd, > NULL, NULL, cmd_pipe_pane_error_callback, wp); > Index: input-keys.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/input-keys.c,v > retrieving revision 1.23 > diff -u -p -r1.23 input-keys.c > --- input-keys.c 30 Jul 2011 18:01:26 -0000 1.23 > +++ input-keys.c 24 Dec 2011 07:59:45 -0000 > @@ -151,9 +151,9 @@ input_key(struct window_pane *wp, int ke > */ > if (key != KEYC_NONE && (key & ~KEYC_ESCAPE) < 0x100) { > if (key & KEYC_ESCAPE) > - bufferevent_write(wp->event, "\033", 1); > + window_pane_write(wp, "\033", 1); > ch = key & ~KEYC_ESCAPE; > - bufferevent_write(wp->event, &ch, 1); > + window_pane_write(wp, &ch, 1); > return; > } > > @@ -163,7 +163,7 @@ input_key(struct window_pane *wp, int ke > */ > if (options_get_number(&wp->window->options, "xterm-keys")) { > if ((out = xterm_keys_lookup(key)) != NULL) { > - bufferevent_write(wp->event, out, strlen(out)); > + window_pane_write(wp, out, strlen(out)); > xfree(out); > return; > } > @@ -194,8 +194,8 @@ input_key(struct window_pane *wp, int ke > > /* Prefix a \033 for escape. */ > if (key & KEYC_ESCAPE) > - bufferevent_write(wp->event, "\033", 1); > - bufferevent_write(wp->event, ike->data, dlen); > + window_pane_write(wp, "\033", 1); > + window_pane_write(wp, ike->data, dlen); > } > > /* Translate mouse and output. */ > @@ -220,7 +220,7 @@ input_mouse(struct window_pane *wp, stru > buf[len++] = m->x + 33; > buf[len++] = m->y + 33; > } > - bufferevent_write(wp->event, buf, len); > + window_pane_write(wp, buf, len); > } else if ((m->b & MOUSE_BUTTON) != MOUSE_2) { > value = options_get_number(&wp->window->options, "mode-mouse"); > if (value == 1 && > Index: input.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/input.c,v > retrieving revision 1.41 > diff -u -p -r1.41 input.c > --- input.c 23 Oct 2011 10:16:14 -0000 1.41 > +++ input.c 24 Dec 2011 07:59:46 -0000 > @@ -696,7 +696,7 @@ input_parse(struct window_pane *wp) > { > struct input_ctx *ictx = &wp->ictx; > const struct input_transition *itr; > - struct evbuffer *evb = wp->event->input; > + struct evbuffer *evb = wp->read_buf; > u_char *buf; > size_t len, off; > > @@ -819,7 +819,7 @@ input_reply(struct input_ctx *ictx, cons > vasprintf(&reply, fmt, ap); > va_end(ap); > > - bufferevent_write(ictx->wp->event, reply, strlen(reply)); > + window_pane_write(ictx->wp, reply, strlen(reply)); > xfree(reply); > } > > Index: options-table.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/options-table.c,v > retrieving revision 1.16 > diff -u -p -r1.16 options-table.c > --- options-table.c 15 Nov 2011 23:24:04 -0000 1.16 > +++ options-table.c 24 Dec 2011 07:59:46 -0000 > @@ -550,6 +550,13 @@ const struct options_table_entry window_ > .default_num = 0 > }, > > + { .name = "rate-limit", > + .type = OPTIONS_TABLE_NUMBER, > + .minimum = 0, > + .maximum = UINT_MAX, > + .default_num = 0 > + }, > + > { .name = "remain-on-exit", > .type = OPTIONS_TABLE_FLAG, > .default_num = 0 > Index: server-fn.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/server-fn.c,v > retrieving revision 1.52 > diff -u -p -r1.52 server-fn.c > --- server-fn.c 23 Oct 2011 10:16:14 -0000 1.52 > +++ server-fn.c 24 Dec 2011 07:59:47 -0000 > @@ -337,8 +337,10 @@ server_destroy_pane(struct window_pane * > > old_fd = wp->fd; > if (wp->fd != -1) { > + event_del(&wp->read_ev); > + if (wp->flags & PANE_WRITING) > + event_del(&wp->write_ev); > close(wp->fd); > - bufferevent_free(wp->event); > wp->fd = -1; > } > > Index: tmux.1 > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/tmux.1,v > retrieving revision 1.257 > diff -u -p -r1.257 tmux.1 > --- tmux.1 9 Dec 2011 16:28:18 -0000 1.257 > +++ tmux.1 24 Dec 2011 07:59:48 -0000 > @@ -2473,6 +2473,12 @@ Like > .Ic base-index , > but set the starting index for pane numbers. > .Pp > +.It Ic rate-limit Ar bytes > +Limit output rate from any single pane to > +.Ar bytes . > +This option can be used to attempt to prevent excessive buffering of > +fast output when the producer can be faster than the consuming terminal. > +.Pp > .It Xo Ic remain-on-exit > .Op Ic on | off > .Xc > Index: tmux.h > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/tmux.h,v > retrieving revision 1.301 > diff -u -p -r1.301 tmux.h > --- tmux.h 9 Dec 2011 16:28:18 -0000 1.301 > +++ tmux.h 24 Dec 2011 07:59:49 -0000 > @@ -814,6 +814,7 @@ struct window_pane { > > int flags; > #define PANE_REDRAW 0x1 > +#define PANE_WRITING 0x2 > > char *cmd; > char *shell; > @@ -823,7 +824,11 @@ struct window_pane { > char tty[TTY_NAME_MAX]; > > int fd; > - struct bufferevent *event; > + struct event read_ev; > + struct evbuffer* read_buf; > + struct timeval read_last; > + struct event write_ev; > + struct evbuffer* write_buf; > > struct input_ctx ictx; > > @@ -1933,6 +1938,8 @@ void window_set_active_pane(struct win > struct window_pane *window_add_pane(struct window *, u_int); > void window_resize(struct window *, u_int, u_int); > void window_remove_pane(struct window *, struct window_pane *); > +void window_pane_queue_write(struct window_pane *); > +void window_pane_write(struct window_pane *, const void *, size_t); > struct window_pane *window_pane_at_index(struct window *, u_int); > struct window_pane *window_pane_next_by_number(struct window *, > struct window_pane *, u_int); > Index: window-copy.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/window-copy.c,v > retrieving revision 1.76 > diff -u -p -r1.76 window-copy.c > --- window-copy.c 4 Dec 2011 16:18:01 -0000 1.76 > +++ window-copy.c 24 Dec 2011 07:59:50 -0000 > @@ -174,8 +174,11 @@ window_copy_init(struct window_pane *wp) > data->searchtype = WINDOW_COPY_OFF; > data->searchstr = NULL; > > - if (wp->fd != -1) > - bufferevent_disable(wp->event, EV_READ|EV_WRITE); > + if (wp->fd != -1) { > + event_del(&wp->read_ev); > + if (wp->flags & PANE_WRITING) > + event_del(&wp->write_ev); > + } > > data->jumptype = WINDOW_COPY_OFF; > data->jumpchar = '\0'; > @@ -237,8 +240,11 @@ window_copy_free(struct window_pane *wp) > { > struct window_copy_mode_data *data = wp->modedata; > > - if (wp->fd != -1) > - bufferevent_enable(wp->event, EV_READ|EV_WRITE); > + if (wp->fd != -1) { > + event_add(&wp->read_ev, NULL); > + if (wp->flags & PANE_WRITING) > + event_add(&wp->write_ev, NULL); > + } > > if (data->searchstr != NULL) > xfree(data->searchstr); > Index: window.c > =================================================================== > RCS file: /cvs/src/usr.bin/tmux/window.c,v > retrieving revision 1.69 > diff -u -p -r1.69 window.c > --- window.c 15 Nov 2011 23:19:51 -0000 1.69 > +++ window.c 24 Dec 2011 07:59:50 -0000 > @@ -60,8 +60,8 @@ struct windows windows; > struct window_pane_tree all_window_panes; > u_int next_window_pane; > > -void window_pane_read_callback(struct bufferevent *, void *); > -void window_pane_error_callback(struct bufferevent *, short, void *); > +void window_pane_read_callback(int, short, void *); > +void window_pane_write_callback(int, short, void *); > > RB_GENERATE(winlinks, winlink, entry, winlink_cmp); > > @@ -579,7 +579,6 @@ window_pane_create(struct window *w, u_i > wp->cwd = NULL; > > wp->fd = -1; > - wp->event = NULL; > > wp->mode = NULL; > > @@ -611,8 +610,10 @@ window_pane_destroy(struct window_pane * > window_pane_reset_mode(wp); > > if (wp->fd != -1) { > + event_del(&wp->read_ev); > + if (wp->flags & PANE_WRITING) > + event_del(&wp->write_ev); > close(wp->fd); > - bufferevent_free(wp->event); > } > > input_free(wp); > @@ -647,8 +648,10 @@ window_pane_spawn(struct window_pane *wp > struct termios tio2; > > if (wp->fd != -1) { > + event_del(&wp->read_ev); > + if (wp->flags & PANE_WRITING) > + event_del(&wp->write_ev); > close(wp->fd); > - bufferevent_free(wp->event); > } > if (cmd != NULL) { > if (wp->cmd != NULL) > @@ -719,30 +722,82 @@ window_pane_spawn(struct window_pane *wp > > setblocking(wp->fd, 0); > > - wp->event = bufferevent_new(wp->fd, > - window_pane_read_callback, NULL, window_pane_error_callback, wp); > - bufferevent_enable(wp->event, EV_READ|EV_WRITE); > + event_set(&wp->read_ev, > + wp->fd, EV_READ|EV_PERSIST, window_pane_read_callback, wp); > + if ((wp->read_buf = evbuffer_new ()) == NULL) > + fatalx("evbuffer_new failed"); > + > + event_set(&wp->write_ev, > + wp->fd, EV_WRITE|EV_PERSIST, window_pane_write_callback, wp); > + if ((wp->write_buf = evbuffer_new ()) == NULL) > + fatalx("evbuffer_new failed"); > + > + if (gettimeofday (&wp->read_last, NULL) != 0) > + fatal("gettimeofday failed"); > + event_add(&wp->read_ev, NULL); > > return (0); > } > > +void > +window_pane_write(struct window_pane *wp, const void *buf, size_t len) > +{ > + evbuffer_add(wp->write_buf, buf, len); > + window_pane_queue_write(wp); > +} > + > +void > +window_pane_queue_write(struct window_pane *wp) > +{ > + if (wp->flags & PANE_WRITING) > + return; > + event_add(&wp->write_ev, NULL); > + wp->flags |= PANE_WRITING; > +} > + > /* ARGSUSED */ > void > -window_pane_read_callback(unused struct bufferevent *bufev, void *data) > +window_pane_read_callback(unused int fd, unused short events, void* data) > { > struct window_pane *wp = data; > + u_int limit; > + struct timeval tv; > + struct timeval tvdiff; > + double last; > + size_t size; > char *new_data; > size_t new_size; > > - new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off; > + if (gettimeofday(&tv, NULL) != 0) > + fatal("gettimeofday failed"); > + > + limit = options_get_number (&wp->window->options, "rate-limit"); > + if (limit != 0) { > + timersub(&tv, &wp->read_last, &tvdiff); > + last = tvdiff.tv_sec + (tvdiff.tv_usec / 1e6); > + > + size = limit * last; > + if (size > limit) > + size = limit; > + if (size == 0) > + return; > + } else > + size = SIZE_MAX; > + memcpy(&wp->read_last, &tv, sizeof wp->read_last); > + if (evbuffer_read(wp->read_buf, wp->fd, size) <= 0) { > + server_destroy_pane(wp); > + return; > + } > + > + new_size = EVBUFFER_LENGTH(wp->read_buf) - wp->pipe_off; > if (wp->pipe_fd != -1 && new_size > 0) { > - new_data = EVBUFFER_DATA(wp->event->input); > + new_data = EVBUFFER_DATA(wp->read_buf); > bufferevent_write(wp->pipe_event, new_data, new_size); > } > > input_parse(wp); > > - wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); > + wp->pipe_off = EVBUFFER_LENGTH(wp->read_buf); > > /* > * If we get here, we're not outputting anymore, so set the silence > @@ -755,12 +810,19 @@ window_pane_read_callback(unused struct > > /* ARGSUSED */ > void > -window_pane_error_callback( > - unused struct bufferevent *bufev, unused short what, void *data) > +window_pane_write_callback(unused int fd, unused short events, void* data) > { > struct window_pane *wp = data; > > - server_destroy_pane(wp); > + if (evbuffer_write(wp->write_buf, wp->fd) <= 0) { > + server_destroy_pane(wp); > + return; > + } > + > + if (EVBUFFER_LENGTH(wp->write_buf) == 0) { > + event_del(&wp->write_ev); > + wp->flags &= ~PANE_WRITING; > + } > } > > void > > > On Fri, Dec 23, 2011 at 01:37:00PM -0800, Robin Lee Powell wrote: > > That works wonderfully! > > > > I've only done basic testing with "yes $(seq 1 1000)". The highest > > value I found where the response to ctrl-c was instant was > > > > #define BYTES_MAX 100000 > > > > That happens to be about the total on-screen characters of my > > terminal times 5. If it was me, I'd set it to that or some similar > > multiple at run time. > > > > I'll see about testing interactive use shortly, with that 100000 > > number. > > > > -Robin > > > > On Tue, Dec 20, 2011 at 07:21:49AM +0000, Nicholas Marriott wrote: > > > Ok ssh changes the game quite a lot. Can you try the diff I sent > > > and see if that helps and if so what value for BYTES_MAX is > > > acceptable? > > > > > > If it doesn't help let me know, I have another diff to rate limit > > > outgoing data that might help instead. Or if not that, there is > > > other stuff we can try. > > > > > > > > > On Mon, Dec 19, 2011 at 04:47:12PM -0800, Robin Lee Powell wrote: > > > > On Tue, Dec 20, 2011 at 12:04:28AM +0000, Nicholas Marriott wrote: > > > > > On Mon, Dec 19, 2011 at 03:59:39PM -0800, Robin Lee Powell wrote: > > > > > > I've never had this level of problem with screen, at all, and I > > > > > > used it for many many years for everything. > > > > > > > > > > > > On Mon, Dec 19, 2011 at 11:43:04PM +0000, Nicholas Marriott > > > > > > wrote: > > > > > > > screen does not successfully rate limit either or if it does > > > > > > > nobody has yet to clearly demonstrate a case where it does. > > > > > > > It's response times for running eg "yes" and hitting ^C or > > > > > > > creating a new window are roughly the same as tmux, give or > > > > > > > take a few seconds. > > > > > > > > > > > > 0____o > > > > > > > > > > > > We're seeing *very* different behaviour, then. > > > > > > > > > > > > In a bare terminal or in a fresh screen, after running "yes" for > > > > > > 30 seconds, I get my prompt back as close to instantly as makes > > > > > > no difference. > > > > > > > > > > > > In tmux it takes 8 seconds. > > > > > > > > > > For me it takes 3-5 seconds for both and always has... > > > > > > > > Huh. > > > > > > > > > What terminal are you using? What size is it? What platform? > > > > > > > > > > Are you using tmux remotely? > > > > > > > > As I mentioned, I'm running PuTTY on Windows, sshing out to a Linux > > > > box in the same house (over wifi). > > > > > > > > TERM before I run screen is "xterm". TERM in screen is "screen". > > > > TERM in tmux is "screen". > > > > > > > > In all cases it's 132 wide and 85 high. > > > > > > > > -Robin > > > > > > > > -- > > > > http://singinst.org/ : Our last, best hope for a fantastic future. > > > > Lojban (http://www.lojban.org/): The language in which "this parrot > > > > is dead" is "ti poi spitaki cu morsi", but "this sentence is false" > > > > is "na nei". My personal page: http://www.digitalkingdom.org/rlp/ > > > > > > ------------------------------------------------------------------------------ > > > Write once. Port to many. > > > Get the SDK and tools to simplify cross-platform app development. Create > > > new or port existing apps to sell to consumers worldwide. Explore the > > > Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join > > > http://p.sf.net/sfu/intel-appdev > > > _______________________________________________ > > > tmux-users mailing list > > > tmux-users@lists.sourceforge.net > > > https://lists.sourceforge.net/lists/listinfo/tmux-users > > > > > > > -- > > http://singinst.org/ : Our last, best hope for a fantastic future. > > Lojban (http://www.lojban.org/): The language in which "this parrot > > is dead" is "ti poi spitaki cu morsi", but "this sentence is false" > > is "na nei". My personal page: http://www.digitalkingdom.org/rlp/ ------------------------------------------------------------------------------ Try before you buy = See our experts in action! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-dev2 _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users