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
> > > [email protected]
> > > 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-users