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

Reply via email to