Okay, so what it appears you have is over 100 timers being fired whose only purpose is to transfer a single value from one variable to another so that bindings will hear that change and update your UI.
A better approach is to remove bindings completely, make a single timer on the main queue that fires every quarter-second (I believe that was your interval from another email), which is associated with the view/window controller that manages all your text fields and instrument objects, have that timer use a single cached formatter and loops through all your 100+ objects, getting their values, formatting them, and setting each appropriate text field's string value. -- Gary L. Wade (Sent from my iPad) http://www.garywade.com/ On Sep 17, 2015, at 4:02 AM, Jean Suisse <jean.li...@gmail.com> wrote: >> What makes you think that: >> >> (a) this is a lot of activity? > > > It is not a lot of activity. I am not trying to do performance optimization. > Right now, the app is taking 3 % CPU on the latest 13” MBP Retina. > I am trying to find why my app can’t run for two days without exhausting the > 16 GB RAM it has. > >> (b) your monolithic replacement runs faster than this? > > I don’t know, but as long as it runs reasonably I am not sure I care. The MAC > is dedicated to the project. There is no user to complain. All I can tell is > that there is no visible jump in CPU consumption. > >> In design terms, you have two instances of the MVC pattern, not one. You >> have inputs (V-1) updating a model (M), and you have UI elements (V-2) >> tracking the same model (M). So you have two design problems: input to >> model, and model to UI. It’s much harder to try to solve inputs-to-UI in a >> single coordinated step — nor do I think you need to. >> >> I know nothing of the details of your app, of course, but if, for example, >> only 20% of the inputs change every second, then suppressing input-to-model >> updates entirely, at the source, seems like a good approach to performance >> problems, without involving the UI. Separately, if the overall rate of UI >> updates is very high (in particular if it’s over 100% per second), then >> using a timer to limit the model-to-UI update rate sounds like a simple >> approach, without involving the inputs. > > Well, at this point it is better for me to say more. > > It is a scientific data acquisition app. Basically, I mad many electronic > boards performing various tasks (actuation & measurements mainly). These > electronic boards have been incorporated in nice boxes to build what I will > call hereafter “instruments”. > These instruments either communicate wirelessly or not, depending on their > physical location, and use different protocol (buses, interfaces) according > to their nature. All these instruments together allow me to cover a large > area and monitor around 150 parameters every second. > > The application does that. Of these 150 variables, a little above 100 are > displayed on a UI that is refreshed every second. > This in itself is a challenge and I had to add some piece of electronics, > work on the (custom) protocol and on the firmware of the boards to get it to > work reliably. Especially for the wireless part. One solution was to have > distinct data buses (distinct communication interfaces). > > Now, this job is done and the design of the app reflects some of these > constraints. > > First, I have a communication interface server which ensures that there is > only one instance representing each data bus connection. Same for the > electronic board server. It ensures that that there is only one object for > each physical board and communication interface (so dealing with concurrency > is dead simple). Then I have actuator objects, sensor objects, instruments > objects all requesting their electronic board on their bus to these object > servers. I manipulate the instruments objects. Communication follows. > Communication is slow. It is expected. > > Then, I have one dispatch source that takes care of synchronization & > timestamps. Four that trigger data collection from the devices through the 4 > buses (1 wireless, 2 RS-485, one GPIB), one that collects measured values > during the last cycle, takes care of the processing & on the disk storage. > And now, one extra that sync the UI. > > Everything works fine with no leaks, except for that last part. This is where > the issue lies. The timer dispatch source that syncs the UI is dead simple. > It only sends updateUI to each object representing an instruments. > > These objects are declared as: > > @interface MyInstrument : JSScientificInstrument > { > double aMeasuredValue; > } > > @property (readwrite) double theMeasured Value; // IB binding > NSTextField with NSFormatter > > @end > > And implemented as : > > - (void)updateUI > { > assert([NSThread isMainThread]); > self.theMeasuredValue = self->aMeasuredValue; > } > > Somewhere in those lines is the issue. If I only comment > "self.theMeasuredValue = ... “, the issue disappears, despite the fact that I > am only transferring a double through a setter bound to the UI. > > I believe it is somewhere in the way GCD, appkit, Core Animation, cocoa > bindings are implemented. So at this stage I am looking to pinpoint the issue > and find a workaround. > >> On 16 sept. 2015, at 23:54, Quincey Morris >> <quinceymor...@rivergatesoftware.com> wrote: >> >> On Sep 16, 2015, at 14:28 , Jean Suisse <jean.li...@gmail.com> wrote: >>> >>> I thought of that at first, to solve the uncommitted CA transactions >>> issues. But the syntax is ugly. >> >> Sure, but in modern Cocoa programming it’s a standard pattern, so it’s not >> unreasonable to grin and bear it. >> >> (It’s about a million times less ugly in Swift. Just sayin'.) >> >>> And I didn’t want to post blocks from all over the place to the main thread >>> (I have 100+ NSTextfields with number formatters updated every second… >>> meaning as many blocks…). >> >> What makes you think that: >> >> (a) this is a lot of activity? >> >> (b) your monolithic replacement runs faster than this? >> >> Indeed, if the “obvious” approach leads to your app using 100% of a single >> CPU for days on end, is that a consideration? If so, then what is the >> allowable threshold? 50% of a CPU? 10%? >> >> That’s what I mean about premature optimization. You don’t really know yet >> what problem you need to solve. >> >>> The issue, to me, is to get my app to run for a few days without crashing. >>> The only way I have to make it work, currently, is by not updating the UI. >> >> Sorry, I was pontificating a bit in my previous post. I guess I still am. >> >> In design terms, you have two instances of the MVC pattern, not one. You >> have inputs (V-1) updating a model (M), and you have UI elements (V-2) >> tracking the same model (M). So you have two design problems: input to >> model, and model to UI. It’s much harder to try to solve inputs-to-UI in a >> single coordinated step — nor do I think you need to. >> >> I know nothing of the details of your app, of course, but if, for example, >> only 20% of the inputs change every second, then suppressing input-to-model >> updates entirely, at the source, seems like a good approach to performance >> problems, without involving the UI. Separately, if the overall rate of UI >> updates is very high (in particular if it’s over 100% per second), then >> using a timer to limit the model-to-UI update rate sounds like a simple >> approach, without involving the inputs. _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com