many messages between threads

  • I have a tree-like data structure which is displayed in an NSBrowser
    and gets operated upon.
    As these operations can take some time, they are done in another thread.

    In order to test the message speed I created a simpler case:
    One object - called Main - lives in the main thread and another -
    called Worker - lives in another thread.
    Main has a method:
    - (void)add: (NSNumber *)n { myInt += [ n intValue]; }

    Worker has:
    mainProxy    an NSProxy for Main
    mainDirect    = Main (not a proxy)

    If Worker does (in some loop)
    [mainProxy add: [NSNumber numberWithInt: someInt ]];
    this takes about 20 msec (iBook G4 800 MHz) per operation.

    If it does:
    [mainDirect performSelectorOnMainThread: @selector(add:) withObject:
    [NSNumber numberWithInt: someInt ] waitUntilDone: NO];
    it takes 250 µsec - but the user interface becomes unusable.

    If Worker does the same, but with waitUntilDone: YES, the user
    interface is responsive again, but it takes 20 msec - same as the
    proxy call.

    If Worker does:
    [mainDirect add: [NSNumber numberWithInt: someInt ]];
    it takes 450 µsec - but this looks somehow dangerous. Could possibly
    made save with the use of NSLocks.

    If Main does:
    [self add: [NSNumber numberWithInt: someInt ]];
    it takes 150 µsec, but, of course, the user interface is blocked for
    the duration of the loop.

    So: how to get messages between threads safely and fast?

    Kind regards,

    Gerriet.
  • On Sep 1, 2007, at 05:36, Gerriet M. Denkmann wrote:

    > I have a tree-like data structure which is displayed in an NSBrowser
    > and gets operated upon.
    > As these operations can take some time, they are done in another
    > thread.
    >
    > In order to test the message speed I created a simpler case:
    > One object - called Main - lives in the main thread and another -
    > called Worker - lives in another thread.
    > Main has a method:
    > - (void)add: (NSNumber *)n { myInt += [ n intValue]; }
    >
    > Worker has:
    > mainProxy    an NSProxy for Main
    > mainDirect    = Main (not a proxy)
    >
    > If Worker does (in some loop)
    > [mainProxy add: [NSNumber numberWithInt: someInt ]];
    > this takes about 20 msec (iBook G4 800 MHz) per operation.

    Make sure to use setProtocolForProxy: on mainProxy, if you haven't
    already.  You could also declare add: as (oneway void) if your worker
    thread doesn't depend on the result of that operation.  You could also
    just use the primitive value as -(void)add:(int)n { mInt += n; } if
    you're using DO.

    > If it does:
    > [mainDirect performSelectorOnMainThread: @selector(add:)
    > withObject: [NSNumber numberWithInt: someInt ] waitUntilDone: NO];
    > it takes 250 µsec - but the user interface becomes unusable.

    If you're calling it on every pass through the loop, you likely need
    to batch your results or have the main object retrieve them at
    intervals.

    > So: how to get messages between threads safely and fast?

    For my applications, DO has been fast enough.  Without seeing your
    code or knowing what you're trying to do outside of a contrived
    example, I doubt that anyone can make a reasonable assessment of your
    problem.  Are you sure that messaging is what you need to optimize?

    regards,
    Adam
  • On 1 Sep 2007, at 18:08, Adam R. Maxwell wrote:

    >
    > On Sep 1, 2007, at 05:36, Gerriet M. Denkmann wrote:
    >
    >> I have a tree-like data structure which is displayed in an
    >> NSBrowser and gets operated upon.
    >> As these operations can take some time, they are done in another
    >> thread.
    >>
    >> In order to test the message speed I created a simpler case:
    >> One object - called Main - lives in the main thread and another -
    >> called Worker - lives in another thread.
    >> Main has a method:
    >> - (void)add: (NSNumber *)n { myInt += [ n intValue]; }
    >>
    >> Worker has:
    >> mainProxy    an NSProxy for Main
    >> mainDirect    = Main (not a proxy)
    >>
    >> If Worker does (in some loop)
    >> [mainProxy add: [NSNumber numberWithInt: someInt ]];
    >> this takes about 20 msec (iBook G4 800 MHz) per operation.
    >
    > Make sure to use setProtocolForProxy: on mainProxy, if you haven't
    > already.
    I have, but it makes no visible difference either way.
    > You could also declare add: as (oneway void) if your worker thread
    > doesn't depend on the result of that operation.
    No. When I do this, I can no longer send messages to the worker
    thread (like "terminate") while it is looping. And again, it doesn't
    get faster.

    Kind regards,

    Gerriet.
previous month september 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Go to today