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

Reply via email to