Future of LessTif - Motif

This is a discussion on Future of LessTif - Motif ; Because of various problems people were having building and using an application of mine with LessTif, I stopped claiming that it worked with LessTif early last year and have been recommending people to use OpenMotif instead. I would much prefer ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: Future of LessTif

  1. Future of LessTif

    Because of various problems people were having building and using an
    application of mine with LessTif, I stopped claiming that it worked with
    LessTif early last year and have been recommending people to use OpenMotif
    instead. I would much prefer to have something that works with both, but
    that was not feasible at that time - it just seemed that my application
    exposed too many bugs in LessTif.

    The position looks better now, but is still far from perfect. My application
    (xpp - the X Windows interface for the ProofPower system) compiles fine
    with LessTif 0.93.94 and apart from an easily-fixed problem that makes it
    crash the first time you run it, it seems to be functionally correct. I
    don't actually know how to assess whether my app ought to work with LessTif
    or not (since I am compiling against OpenMotif 2.1.X or 2.2.X, I don't know
    whether I'm using features supported in LessTif).

    Unfortunately, there are non-functional issues that still make me
    disinclined to recommend people to try LessTif. xpp acts as a terminal
    emulator for another process, and when that process is producing a lot of
    output, xpp needs to keep up with it. Users also don't expect the user
    interface to hog the CPU or to flicker badly under load. The test code I've
    attached demonstrates that the LessTif text widget has both these failings.
    The test sets up a text widget and uses it to display text lines output by
    a child process (using POSIX system calls that should work on Linux,
    Cygwin, Mac OS X ...). The test has a parameter which is the number of
    lines of text the child is to output.

    Under OpenMotif 2.1.30 on a Linux PC, the text widget redisplays cleanly and
    the performance over test runs ranging from 10,000 lines up to 200,000
    lines is a fairly steady 16,500 lines/second when the test is run iconified
    and about 7,500 lines/second when the test is run mapped. (Similar results
    apply to OpenMotif 2.2.2 and 2.2.3 on a variety of hardware and O/S
    combinations).

    Under OpenMotif, top shows that the parent process and the X server are
    consuming about 20% of an otherwise idle CPU while the child process is
    running.

    Under LessTif 0.93.94 on the same system, the text widget flickers badly
    whenever the child is producing output. The performance is much worse and
    degrades from 3,300 lines/second on a 10,000 line run to 700 lines per
    second on a 50,000 line run. (I guess the code is making the common mistake
    of using realloc to add a constant amount of space rather than to enlarge
    the space by a constant multiple.)

    Under LessTif, the combined X server and parent process CPU usage go up to
    95% or more. This is disastrous for my application, since the process the
    user is interested gets completely squeezed out by the user interface.
    [Aside: in the application, the text widget doesn't grow indefinitely, it
    gets truncated once it grows beyond a user-defined limit, however this
    does't have much mitigating effect on the problems I'm seeing.]

    So here are my big questions for the LessTif developers:

    1) Do I have to rely on trial and error to know whether the range of Motif
    facilities I'm using is supported by LessTif? Is there a concise list of
    which 2.X facilities are fully supported?

    2) I think my test shows that LessTif is not 100% industrial-strength yet.
    Is it likely that these scalability problems will be fixed.

    I would very much like to be able to offer users the choice of building with
    LessTif - that would also allow me to port to Cygwin where OpenMotif is not
    allowed to go. But I can't do that yet!

    Regards,

    Rob.


    /* **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****
    * xmsoak.c: a soak test for the Motif text widget.
    * To compile, use, e.g.:
    * gcc -g -o xmsoak -L/usr/X11R6/lib -lXm xmsoak.c
    * To run:
    * xmsoak [count]
    *
    * or, to avoid timing the time taken to update the display
    *
    * xmsoak -iconic [count]
    *
    * Rob Arthan (rda AT lemma-one.com) Lemma 1 Ltd. 29/1/2005.
    * **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****
    * N.b., this needs the following POSIX interfaces:
    * fcntl, fork, pipe, read, time, usleep, write
    * **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****/
    #include
    #include
    #include
    #include
    #define DEFAULT_NUM_LINES 50000
    /* **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****
    * Listener process: displays a text widget monitoring output from talker
    process
    * **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****/
    XtAppContext app;
    Widget root, text;
    XtInputId input_id;
    int read_fd;
    Boolean eof = False;
    #define XFER_SIZE 1000
    static void display_text(char *buf, int ct)
    {
    char *p;
    buf[ct] = 0;
    for(p = buf; *p != 0; ++p) {
    if(*p == '\a') { /* last char */
    XBell(XtDisplay(root), 100);
    *p = 0;
    eof = True;
    if(p == buf) {
    return;
    } else {
    break;
    }
    }
    }
    XmTextInsert(text, XmTextGetLastPosition(text), buf);
    }
    Boolean input_wp(XtPointer);
    void input_cb(
    XtPointer unused_p,
    int *unused_source,
    XtInputId *unused_id)
    {
    int ct;
    char buf[XFER_SIZE + 1]; /* allow for null-termination in display_text */
    if((ct = read(read_fd, buf, XFER_SIZE)) > 0) {
    display_text(buf, ct);
    }
    if(eof) {
    XtRemoveInput(input_id);
    return;
    }
    if(ct == XFER_SIZE) {
    /* Probably more to do for this burst of input */
    /* stop listening to give X a chance */
    XtRemoveInput(input_id);
    /* Schedule work proc to deal with rest of this burst of input */
    XtAppAddWorkProc(app, input_wp, 0);
    }
    }
    Boolean input_wp(XtPointer continue_flag)
    {
    int ct;
    char buf[XFER_SIZE+1]; /* allow for null-termination in display_text */
    if((ct = read(read_fd, buf, XFER_SIZE)) > 0) {
    display_text(buf, ct);
    }
    if(eof) {
    return True;
    }
    if(ct == XFER_SIZE) { /* Probably more to do */
    return False;
    } else { /* Done with this burst of input */
    /* schedule input callback proc to deal with next burst */
    input_id = XtAppAddInput(
    app, read_fd, (XtPointer) XtInputReadMask, input_cb, 0);
    return True;
    }
    }
    void listener(void)
    {
    XtAppMainLoop(app);
    }
    /* **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****
    * Talker process: repeatedly output a line of text to the pipe:
    * **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****/
    int write_fd;
    #define LINE ("%07d: The flowers that bloom in the spring, tra-la!\n")
    #define LAST_LINE1 ("[That took no more than 1 second.]\n")
    #define LAST_LINE2 ("[That took approximately %ld seconds.]\n")
    void talker (int num_lines)
    {
    char buf[200];
    int i;
    long int start_time, elapsed;
    start_time = (long int) time(0);
    for(i = 1; i <= num_lines; ++i) {
    sprintf(buf, LINE, i);
    (void) write(write_fd, buf, strlen(buf));
    }
    elapsed = ((long int) time(0)) - start_time;
    if(elapsed <= 1) {
    (void) write(write_fd, LAST_LINE1, strlen(LAST_LINE1));
    } else {
    sprintf(buf, LAST_LINE2, elapsed);
    (void) write(write_fd, buf, strlen(buf));
    }
    buf[0] = '\a';
    write(write_fd, buf, 1);
    }
    /* **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****
    * main: set up scrolled text widget for the listener process; fork with
    * parent becoming listener and child talker.
    * **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****/
    int main(int argc, char **argv)
    {
    int num_lines, success, fds[2], i;
    Arg args[12];
    root = XtVaAppInitialize(
    &app, "XmSoak", NULL, 0, &argc, argv, NULL, NULL);
    if(argc > 1) {
    num_lines = atoi(argv[1]);
    } else {
    num_lines = DEFAULT_NUM_LINES;
    }
    (void) pipe(fds);
    read_fd = fds[0];
    write_fd = fds[1];
    fcntl(read_fd, F_SETFL, O_NONBLOCK);
    i = 0;
    XtSetArg(args[i], XmNeditable, False); ++i;
    XtSetArg(args[i], XmNeditMode, XmMULTI_LINE_EDIT); ++i;
    XtSetArg(args[i], XmNwordWrap, True); ++i;
    XtSetArg(args[i], XmNscrollHorizontal, False); ++i;
    XtSetArg(args[i], XmNscrollVertical, True); ++i;
    XtSetArg(args[i], XmNcolumns, 80); ++i;
    XtSetArg(args[i], XmNrows, 24); ++i;
    text = XmCreateScrolledText(root, "text", args, i);
    /* register read_fd as an input source: */
    input_id = XtAppAddInput(
    app, read_fd, (XtPointer) XtInputReadMask, input_cb, 0);
    XtManageChild(text);
    XtRealizeWidget(root);
    if(fork()) { /* parent: the listener process */
    close(write_fd);
    listener();
    } else { /* child: the talker process */
    close(read_fd);
    talker(num_lines);
    }
    return 0;
    }
    /* **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****
    * end of xmsoak.c
    * **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    **** ****/

  2. Re: Future of LessTif

    Rob Arthan wrote:

    > Under OpenMotif 2.1.30 on a Linux PC, the text widget redisplays cleanly and
    > the performance over test runs ranging from 10,000 lines up to 200,000
    > lines is a fairly steady 16,500 lines/second when the test is run iconified
    > and about 7,500 lines/second when the test is run mapped. (Similar results
    > apply to OpenMotif 2.2.2 and 2.2.3 on a variety of hardware and O/S
    > combinations).
    >
    > Under OpenMotif, top shows that the parent process and the X server are
    > consuming about 20% of an otherwise idle CPU while the child process is
    > running.


    That's strange. There is nothing in the code itself which would suggest
    a low CPU usage. If the number is correct, the only explanation I have
    is that the X rendering pipeline is slow (I mean _hardware_ part of the
    rendering) so most of the time talker() is idle waiting for its output
    to get consumed. On my reasonably descent Linux box (dual-opteron etc)
    with OpenMotif-2.1.30, your test consumes 130% of CPU (100 for the
    process itself and 30 being taken by X on another CPU). I get
    several-times-higher rates than yours, though ;-).

    But what's the reason to _continously_ output that huge amount of text?!
    Unless you're creating ascii-art movies ;-). Wouldn't it be smarter to
    buffer the output internally in your app and chunk it out every second
    or so (or once at the end)? Mind you, if the ability to grok thousands
    of lines of output a second could be a bottlneck for your app, it will
    be completely unusable on low-end hardware OR when displayed remotely
    over a slow link.

    Regards,

    Evgeny

  3. Re: Future of LessTif

    Evgeny Stambulchik wrote:

    > Rob Arthan wrote:
    >
    >> Under OpenMotif 2.1.30 on a Linux PC, the text widget redisplays cleanly
    >> and the performance over test runs ranging from 10,000 lines up to
    >> 200,000 lines is a fairly steady 16,500 lines/second when the test is run
    >> iconified and about 7,500 lines/second when the test is run mapped.
    >> (Similar results apply to OpenMotif 2.2.2 and 2.2.3 on a variety of
    >> hardware and O/S combinations).
    >>
    >> Under OpenMotif, top shows that the parent process and the X server are
    >> consuming about 20% of an otherwise idle CPU while the child process is
    >> running.

    >
    > That's strange. There is nothing in the code itself which would suggest
    > a low CPU usage. If the number is correct, the only explanation I have
    > is that the X rendering pipeline is slow (I mean _hardware_ part of the
    > rendering) so most of the time talker() is idle waiting for its output
    > to get consumed. On my reasonably descent Linux box (dual-opteron etc)
    > with OpenMotif-2.1.30, your test consumes 130% of CPU (100 for the
    > process itself and 30 being taken by X on another CPU). I get
    > several-times-higher rates than yours, though ;-).


    The only other thing going on would have been me moving windows around.
    Trying the test with top more carefully and leaving everything alone, the
    test processes together taking about 20% of the CPU and the X server is
    getting most of the rest. Moving windows around was obviously making a
    significant difference.

    >
    > But what's the reason to _continously_ output that huge amount of text?!
    > Unless you're creating ascii-art movies ;-). Wouldn't it be smarter to
    > buffer the output internally in your app and chunk it out every second
    > or so (or once at the end)?
    > Mind you, if the ability to grok thousands
    > of lines of output a second could be a bottlneck for your app, it will
    > be completely unusable on low-end hardware OR when displayed remotely
    > over a slow link.


    The usage pattern for the actual application, xpp, is very like that of a
    terminal emulator - the user types in a command, the other process
    processes it and xpp displays the results, typically no more than a screen
    or two of output. Occasionally the user will want to run a script which
    could produce an arbitrarily large amount of output. I noticed the problem
    when running an initialisation script that used to take a few seconds, but
    took forever on a system where I'd compiled against LessTif without
    realising it.

    Yes, I could optimise xpp to do additional buffering to reduce the number of
    XmTextInsert calls, but it doesn't feel right if it's only to work around a
    problem in the Motif library and would make life rather more complicated
    (I'd need to have a timeout to flush the buffer). I have just tried
    introducing a layer of buffering into my test. It does make things go
    faster, but it still doesn't cure the screen flicker or enable LessTif to
    handle more than about 50,000 lines in the text widget.

    Regards,

    Rob.


  4. Re: Future of LessTif

    Do you have Makefile for this please?

    Zach


  5. Re: Future of LessTif

    Can you send me Makefile?

    Zach


  6. Re: Future of LessTif

    Do you have Makefile for this please?

    Zach


  7. Re: Future of LessTif

    Rob,

    Looks like you uncovered not just a performance problem but a bug.
    I've been single stepping your application, and saw that some of
    the redraws are basically wrong. I would guess that this explains
    at least the odd flickering.

    I'll look into this further.

    Note that I only saw your message today - several weeks after your
    post. It might be interesting to enter problems you know about in
    the LessTif bug database
    http://sourceforge.net/tracker/?grou...96&atid=108596
    or to send a message to lesstif-discuss@lists.sourceforge.net .

    Thanks,

    Danny

    Rob Arthan wrote:
    > Under LessTif 0.93.94 on the same system, the text widget flickers badly
    > whenever the child is producing output. The performance is much worse and


    --
    Danny Backx - danny.backx-at-scarlet.be

+ Reply to Thread