The Observable module uses change method as a way of toggling when the observers should get updates of any change in state in the Subject. However, it seems redundant to me, as notify_observers(self) it is going to be called intentionally. Is there a situation where having change makes a difference?
It allows for a split in timing, and for multiple changes without side effects.
The state of an object may or may not change during a sub-process of an application. If it changes, then .change can be invoked without any side effects. It is also possible to call it multiple times.
Later, notifications can be sent. As long as they are sent before any dependent actions are taken, then anything that depends on updates due to the original change should be able to make its update correctly
You might do this for example if processing following a change had a high cost (I/O, CPU time, network bandwidth), but only needed to be done before a second section of code, not simply every time a change occurred.
You might also do this if updates are not strictly necessary in all code paths. I.e. sometimes you care about updating due to a change, but other times it is not necessary, and any change can be ignored.
An example might be if you need to re-generate an XML document every time a content object used by the XML creation code has a property change. You would place calls to .change in the important property setters of the content object, hiding them from the external caller. You don't want to generate a new XML document each time you call content.property= (it could be very slow), instead you wait until you are finished making updates and place a single call to content.notify_observers after all possible changes.
Related
I am building an app which list a set of files. When the user performs an action to one of the files, the action is process intensive (performs multiple ajax requests, updates an offline sqlite database, performs various checks on the file, etc). The user can trigger the said action on multiple files at a time.
The problem is that when the action is performed on more than one file, it blocks the UI. Digging down into the issue, removing certain part of the action (i.e. if I remove the section that performs a verification of the file size, type, and calculate the meta when missing, etc), it wears down the effect of UI lock, though it is still there.
From what I read so far, it is suggested to extract such logic out of the main process i.e. to have a separate process to handle those. The proposed solutions I've read are
use worker thread
create a child process
create a server
I've been struggling to understand and come up with a working example for each. I came across this module named piscina which says to generate workers (my understanding it is a wrapper to create worker thread?).
On the repo here I've setup an example which simulates the issue I have. So if I trigger multiple instances of the action by pressing the "Test" button at the bottom. And then try to increment the count at the top, I can experience the UI lock/lags. It takes approximately 10-15 clicks on the "Test" button to replicate. I can also hear the CPU fan increasing when performing this.
Are there any projects/examples around which gives a simplified implementation on how to mitigate or work around this problem?
EDIT
After #tromgy suggestions I've performed the following updates/test:
Adjusting the await run to a regular promise did seem to solve the issue.
But triggering multiple instances simultaneously, for example, 20, still causes UI lock. Attempting the same on my actual project causes memory heap errors.
I tried moving the Piscina instance outside, rather than creating a new instance on each event, it solves the memory leap, but not the UI lock/lag/freeze issue.
I've tried converting invoke to an actual event, the UI issue still persist.
According to following documentation, it is stated that if you don't explicitly specify a trigger you get behavior described below:
If unspecified, the default behavior is to trigger first when the
watermark passes the end of the window, and then trigger again every
time there is late arriving data.
Is this behavior true for FixedWindow as well? For example you would assume fixed window should have a default trigger of repeatedly firing after watermark passes end of window, and discard all late data unless late data is explicitly handled. Also where in the source code can I see definition of trigger for, example FixedWindow object?
The best doc to start with is the guide for triggers, and windows (and following the links from there). In particular, it says that, even though the default trigger fires every time late data arrives, in default configuration it still effectively only triggers once, discarding the late data:
if you are using both the default windowing configuration and the
default trigger, the default trigger emits exactly once, and late data
is discarded. This is because the default windowing configuration has
an allowed lateness value of 0. See the Handling Late Data section for
information about modifying this behavior.
Details
Windowing concept in Beam in general encompasses few things, including assigning windows, handling triggers, handling late data and few other things. However these things are assigned and handled separately. It gets confusing quickly from here.
How the elements are assigned to a window is handled by a WindowFn, see here. For example FixedWindows: link. It is basically the only thing that happens there (almost). Assigning a window is a special case of grouping the elements based on the event timestamps (kinda). You can think of the logic being similar to manually assigning custom keys to elements based on the timestamps, and then applying GroupByKey.
Triggering is a related but separate concept. Triggers are (roughly) just predicates to indicate when the runner is allowed to emit the data accumulated in the window so far (source). I think this is the closest thing to the original design doc for triggers: https://s.apache.org/beam-triggers
Lateness is another related part of the configuration which is also somewhat separate (link). Even though a trigger might allow the runner to emit all the late data forever, the pipeline can be set to not allow any late data (which is the default behavior), or only allow late data for some limited time. This leads to the default trigger behavior described above. Yes, this is confusing. Avoid using any complex triggering and lateness if you can, it likely won't work as you expect it to.
So the window classes only handle the grouping logic, i.e. what kind of elements have the same grouping key. These classes don't care about when you will want to emit the accumulated results. This depends on your business logic, e.g. you might want to handle newly arrived elements, or you might want to discard them, it's not part of the window. This means there's no special triggers for FixedWindows or other windows, you can use any trigger with any window (even if logically some specific trigger doesn't make sense in context of some window).
Default trigger is just that, something that is just set by default. You should assign your own trigger if it doesn't suit your needs. And it likely won't, except for some basic use cases.
Update
An example of how to use FixedWindows with triggers.
I have some code that needs to get called frequently, such as check what day it is, if it's the next day then move the day strings in the tableView.
Now I thought that the viewDidLoad would get called all the time and so it would be 'fine' to put it in there. However, I've left the simulator overnight, and I've pressed the home button and clicked again, changed VCs etc. and viewDidLoad hasn't been hit.
What are my options for doing sporadic checks such as, is it a new day? As x happened etc.
In this specific case, you can subscribe to NSCalendarDayChangedNotification to be notified when the date changes and respond accordingly in your view controller. In general, didBecomeActive or viewDidAppear would likely work.
What are my options for doing sporadic checks such as, is it a new day
It depends what the meaning of "is" is! In particular, "is" when? You say "sporadic", but that's just fluff. When do you need to know this? To what stimulus do you want to respond? When the user opens your app? Then put it in applicationDidBecomeActive. Every day at noon? Then run an NSTimer. Really, the problem here is that you don't seem to know, yourself, just when you need to perform these checks.
Whilst in your app, its quite easy to continually check for something. You simply create a background thread. However, what you describe is a thread that persists from outside the app's lifecycle.
Have a read on this documentation provided by Apple itself. You have to have good excuse to put a background thread. The scope of such thread is limited to only certain scenarios such as downloading background stuff, playing sounds etc.
For your scenario, I'd look at applicationDidBecomeActive(_:) found in your Application Delegate. There you can mimic such continual check. Beware however, don't put heavy word load on start up or your app might be killed automatically if it fails to become active in reasonable amount of time.
As part of my syncing solution, I use a sync status for all objects of a certain class. Whenever specific (not all) attributes of that object change, I want to update the status.
I am considering four approaches:
Manually setting the status in code wherever I change
something that needs to synced. This is the most obvious, but also
the most laborious and error-prone (I'll need to remember to also add the sync status update any time I add new functionality).
Track it using a core data notification (e.g. willSave or
NSManagedObjectContextObjectsDidChangeNotification). This seems the most appropriate at first glance -
I simply sign up for the notifications in my AppDelegate and update
the status each time. But will it be possible to examine the changes
and only update the sync status when an attribute I care about is
updated? Also, won't setting
the sync_status itself also fires this notification, leading me into an endless loop? How would I address this?
Custom setters on the attributes I care about. I have had
trouble trying to get this working before, and eventually decided
to try to leave the standard core data getters/setters alone. But I
would delve back in if it is the best fit.
KVO. I've not used this pattern before, but it might be easiest to
just sign up for notifications of attribute changes for those I care
about and set the flag there. But where would I do this? I need
to monitor every object of the class, so would it be possible to start observing an
attribute's KVO notifications in that same object's awakeFromInsert?
I.e., whenever an object is created, immediately have that same
object listen for changes to attributeA and set it's own sync_status
when it fires?
Which of these approaches will serve me best? Perhaps I am missing some other ideas?
Manually setting the status code
Probably a bad idea, for exactly the reason you describe. You'll need to do this in all kinds of cases. You might not always be the developer on the app. One day you or someone else will forget it. Even if you don't, you get extra code all over the place that could be centralized.
Track it using a core data notification [...] Also, won't setting the sync_status itself also fires this notification, leading me into an endless loop?
It depends how you do it. Listening for NSManagedObjectContextDidSaveNotification could work, if you use a secondary NSManagedObjectContext. That way you can set the sync flag, save changes, and avoid looping because you're saving on a different context that you're not observing.
Using NSManagedObjectContextObjectsDidChangeNotification could also work. That will be posted when object properties are changed but a save is not actually in progress yet. Inspect the userInfo dictionary to see if anything you care about has changed, and if so, set your sync_status flag. Setting the flag would trigger a new notification, but it will be one you don't care about, so you break the loop. Using a separate context would also prevent looping here.
Custom setters on the attributes I care about.
Definitely workable, though depending on how many attributes you care about, you could end up with a lot of accessors just to update sync status. Of the four you mention, this is the one I would use.
A related but simpler approach would be to override willSave on your managed object classes. That will get called just before a save. Implement it to
Look through [self changedValues] for attributes that trigger syncing.
Set the sync flag if you find any of them.
This way you only have one custom method per entity, no matter how many attributes end up triggering the sync flag.
KVO
Should work, but is probably less intuitive to get working right than custom setters.
When I had to do something like this, I put the sync information outside of my data store. I'd listen for NSManagedObjectContextDidSaveNotification, and in the observer method I would:
Look through userInfo to see what had changed
Get the NSManagedObjectID for each object that would need to sync
Convert the object IDs to NSStrings and add those to a list saved in a separate file.
On a successful sync I'd clear out the object ID list.
The thinking was mainly that a sync flag is more metadata than actual model data, so I kept it out of the model. If you prefer to keep it in the model, I'd go with overriding willSave.
I'd like to delay the handling for some captured events in ActionScript until a certain time. Right now, I stick them in an Array when captured and go through it when needed, but this seems inefficient. Is there a better way to do this?
Well, to me this seems a clean and efficient way of doing that.
What do you mean by delaying? you mean simply processing them later, or processing them after a given time?
You can always set a timout to the actual processing function in your event handler (using flash.utils.setTimeout), to process the event at a precise moment in time. But that can become inefficient, since you may have many timeouts dangeling about, that need to be handled by the runtime.
Maybe you could specify your needs a little more.
edit:
Ok, basically, flash player is single threaded - that is bytecode execution is single threaded. And any event, that is dispatched, is processed immediatly, i.e. dispatchEvent(someEvent) will directly call all registered handlers (thus AS bytecode).
Now there are events, which actually are generated in the background. These come either from I/O (network, userinput) or timers (TimerEvents). It may happen, that some of these events actually occur, while bytecode is executed. This usually happens in a background thread, which passes the event (in the abstract sense of the term) to the main thread through a (de)queue.
If the main thread is busy executing bytecode, then it will ignore these messages until it is done (notice: nearly any bytecode execution is always the implicit consequence of an event (be it enter frame, or input, or timer or load operation or whatever)). When it is idle, it will look in all queues, until it finds an available message, wraps the information into an ActionScript Event object, and dispatches it as previously described.
Thus this queueing is a very low level mechanism, that comes from thread-to-thread communication (and appears in many multi-threading scenarios), and is inaccessible to you.
But as I said before, your approach both is valid and makes sense.
Store them into Vector instead of Array :p
I think it's all about how you structure your program, maybe you can assign the captured event under the related instance? So that it's all natural to process the captured event with it instead of querying from a global vector