How many timers can be created with CreateWaitableTimer and SetWaitableTimer which are going to work at the same time?
I was able to create 3, but only 2 worked.
Related
I'm trying to run a task periodically every 12 hours, I'v used Work Manager and followed their documentation. The task is running periodically well as long as the user is actually using the app.
But if i close the app, or even just let my phone be idle for a while, it seems like the task stops working.
I searched for this problem on google, and came across posts such as this post, which i think explains the behaviour on my phone.
From my understanding, this problem is not related to work manager, but to all frameworks who will try to run background tasks?
Is there a way to still periodically run tasks on most devices or is WorkManager is still the way to go?
Thanks!
Please check this:
https://developer.android.com/topic/libraries/architecture/workmanager/how-to/debugging#use-alb-shell0dumpsys-jobscheduler
Required constraints: TIMING_DELAY CONNECTIVITY [0x90000000]
Satisfied constraints: DEVICE_NOT_DOZING BACKGROUND_NOT_RESTRICTED WITHIN_QUOTA [0x3400000]
Unsatisfied constraints: TIMING_DELAY CONNECTIVITY [0x90000000]
Minimum latency: +1h29m59s687ms
Run time: earliest=+38m29s834ms, latest=none, original latest=none
The periodic work is not exactly Periodic. You have different Constraints:
Explicit - you set them.
Implicit - set by the system related to Battery optimization. You should save the battery and also Internet usage.
When you have a "periodic work" you actually have an explicit constraint called:
TIMING_DELAY. But when the time is passed it does not mean that the work will start. It means that this constraint is satisfied and if and only all the other constraints are Satisfied - then the work will start.
And for example, you have your work with a "period" of 12 hours, but you wait an extra 4 hours for the other Constraints - you will have a period of 16 hours.
And after the work is finished - WorkManager will create a completely new job in the JobScheduler with TIMING_DELAY again - 12 hours. It will not account for the extra 4 hours. So you can't imagine something like:
I have 5 days so it means - 10 executions. It might be only 4 or 5 executions.
You can improve this by asking the user to exempt you from battery optimization:
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
If you need to be really exact - you need to use AlarmManager, but mostly the idea of all of this is for the battery to be saved so it is not only about what the devs need, but also what the user needs.
I have a process which uses the concurrent-ruby gem to handle a large number of API calls concurrently using Concurrent::Future.execute, and, after some time, it dies:
ERROR -- : can't create Thread (11) (ThreadError)
/current/vendor/bundler_gems/ruby/2.0.0/bundler/gems/concurrent-ruby-cba3702c4e1e/lib/concurrent/executor/ruby_thread_pool_executor.rb:280:in `initialize'
Is there a simple way I can tell Concurrent to limit the number of threads it spawns, given I have no way of knowing in advance just how many API calls it's going to need to make?
Or is this something I need to code for explicitly in my app?
I am using Ruby 2.0.0 (alas don't currently have the option to change that)
After some reading and some trial and error I have worked out the following solution. Posting here in case it helps others.
You control the way Concurrent uses threads by specifying a RubyThreadPoolExecutor1
So, in my case the code looks like:
threadPool = Concurrent::ThreadPoolExecutor.new(
min_threads: [2, Concurrent.processor_count].min,
max_threads: [2, Concurrent.processor_count].max,
max_queue: [2, Concurrent.processor_count].max * 5,
overflow_policy: :caller_runs
)
result_things = massive_list_of_things.map do |thing|
(Concurrent::Future.new executor: threadPool do
expensive_api_call using: thing
end).execute
end
So on my laptop I have 4 processors so this way it will use between 2 and 4 threads and allow up to 20 threads in the queue before forcing the execution to use the calling thread. As threads free up the Concurrency library will reallocate them.
Choosing the right multiplier for the max_queue value looks like being a matter of trial and error however; but 5 is a reasonable guess.
1 The actual docs describe a different way to do this but the actual code disagrees with the docs, so the code I have presented here is based on what actually works.
The typical answer to this is to create a Thread pool.
Create a finite number of threads, have a way of recording which are active and which aren't. When a thread finishes an API call, mark it as inactive, so the next call can be handled by it.
The gem you're using already has thread pools.
I need a server to perform lots of timing operations and trigger code accordingly.
So I'll break my wonderings into simple questions:
How are timeout and timeout callback usually work in terms of OS resources and threads?
(say the nodejs setTimeout(callback, delay))
Should I refrain from that and maybe have a timer worker to check every second for timeouts?
e.i. if i need 10 timeouts, keep a collection of all timeout timestamps and check every second if any of them is due.
What would be a good framework / platform to implement this kind of behaviour?
Please comment if you think I'm being unclear,
Thanks in advance.
"Depends"
Most timer implementations are extremely lightweight (i.e. having zillions of timers going at once). A timer core is little more than a priority queue of "things soon to expire", and then expiring them every second.
Things are different when lots of them fire all at once, that is NOT lightweight (as all the real work starts).
I have created a test plan with multiple thread groups that I want to execute simultaneously.
One group (A) involves tagging a folder with 1000 images in it, so it takes approx 10 seconds to respond.
The other group (B) is real quick.
What I've found is that group B seems to "stick" and wait for thread A to complete. Now all the reading I've done says that thread groups should be totally independant, but this doesn't seem to be the case in my test plan.
I have an HTTP defaults manager, cookie manager and user defined variables that are shared between groups (but have tried adding them in the separate thread groups).
Anyone got any idea why this should be?
Script is here: https://www.dropbox.com/sh/fhdof4ynjt73s2p/mkrphWcfHK
(likely will not run or stick though as this uses internal URL's)
This issue is not in JMeter, it is the application that is locking.
Looking at your test, you seem to use one user to do your load test, this clearly explains your issue and makes your test unrealistic as you have around 20 Users logged with the same user/password.
I'm trying to learn about threading and I'm thoroughly confused. I'm sure all the answers are there in the apple docs but I just found it really hard to breakdown and digest. Maybe somebody could clear a thing or 2 up for me.
1)performSelectorOnMainThread
Does the above simply register an event in the main run loop or is it somehow a new thread even though the method says "mainThread"? If the purpose of threads is to relieve processing on the main thread how does this help?
2) RunLoops
Is it true that if I want to create a completely seperate thread I use
"detachNewThreadSelector"? Does calling start on this initiate a default run loop for the thread that has been created? If so where do run loops come into it?
3) And Finally , I've seen examples using NSOperationQueue. Is it true to say that If you use performSelectorOnMainThread the threads are in a queue anyway so NSOperation is not needed?
4) Should I forget about all of this and just use the Grand Central Dispatch instead?
Run Loops
You can think of a Run Loop to be an event processing for-loop associated to a thread. This is provided by the system for every thread, but it's only run automatically for the main thread.
Note that running run loops and executing a thread are two distinct concepts. You can execute a thread without running a run loop, when you're just performing long calculations and you don't have to respond to various events.
If you want to respond to various events from a secondary thread, you retrieve the run loop associated to the thread by
[NSRunLoop currentRunLoop]
and run it. The events run loops can handle is called input sources. You can add input sources to a run-loop.
PerformSelector
performSelectorOnMainThread: adds the target and the selector to a special input source called performSelector input source. The run loop of the main thread dequeues that input source and handles the method call one by one, as part of its event processing loop.
NSOperation/NSOperationQueue
I think of NSOperation as a way to explicitly declare various tasks inside an app which takes some time but can be run mostly independently. It's easier to use than to detach the new thread yourself and maintain various things yourself, too. The main NSOperationQueue automatically maintains a set of background threads which it reuses, and run NSOperations in parallel.
So yes, if you just need to queue up operations in the main thread, you can do away with NSOperationQueue and just use performSelectorOnMainThread:, but that's not the main point of NSOperation.
GCD
GCD is a new infrastructure introduced in Snow Leopard. NSOperationQueue is now implemented on top of it.
It works at the level of functions / blocks. Feeding blocks to dispatch_async is extremely handy, but for a larger chunk of operations I prefer to use NSOperation, especially when that chunk is used from various places in an app.
Summary
You need to read Official Apple Doc! There are many informative blog posts on this point, too.
1)performSelectorOnMainThread
Does the above simply register an event in the main run loop …
You're asking about implementation details. Don't worry about how it works.
What it does is perform that selector on the main thread.
… or is it somehow a new thread even though the method says "mainThread"?
No.
If the purpose of threads is to relieve processing on the main thread how does this help?
It helps you when you need to do something on the main thread. A common example is updating your UI, which you should always do on the main thread.
There are other methods for doing things on new secondary threads, although NSOperationQueue and GCD are generally easier ways to do it.
2) RunLoops
Is it true that if I want to create a completely seperate thread I use "detachNewThreadSelector"?
That has nothing to do with run loops.
Yes, that is one way to start a new thread.
Does calling start on this initiate a default run loop for the thread that has been created?
No.
I don't know what you're “calling start on” here, anyway. detachNewThreadSelector: doesn't return anything, and it starts the thread immediately. I think you mixed this up with NSOperations (which you also don't start yourself—that's the queue's job).
If so where do run loops come into it?
Run loops just exist, one per thread. On the implementation side, they're probably lazily created upon demand.
3) And Finally , I've seen examples using NSOperationQueue. Is it true to say that If you use performSelectorOnMainThread the threads are in a queue anyway so NSOperation is not needed?
These two things are unrelated.
performSelectorOnMainThread: does exactly that: Performs the selector on the main thread.
NSOperations run on secondary threads, one per operation.
An operation queue determines the order in which the operations (and their threads) are started.
Threads themselves are not queued (except maybe by the scheduler, but that's part of the kernel, not your application). The operations are queued, and they are started in that order. Once started, their threads run in parallel.
4) Should I forget about all of this and just use the Grand Central Dispatch instead?
GCD is more or less the same set of concepts as operation queues. You won't understand one as long as you don't understand the other.
So what are all these things good for?
Run loops
Within a thread, a way to schedule things to happen. Some may be scheduled at a specific date (timers), others simply “whenever you get around to it” (sources). Most of these are zero-cost when idle, only consuming any CPU time when the thing happens (timer fires or source is signaled), which makes run loops a very efficient way to have several things going on at once without any threads.
You generally don't handle a run loop yourself when you create a scheduled timer; the timer adds itself to the run loop for you.
Threads
Threads enable multiple things to happen at the exact same time on different processors. Thing 1 can happen on thread A (on processor 1) while thing 2 happens on thread B (on processor 0).
This can be a problem. Multithreaded programming is a dance, and when two threads try to step in the same place, pain ensues. This is called contention, and most discussion of threaded programming is on the topic of how to avoid it.
NSOperationQueue and GCD
You have a thing you need done. That's an operation. You can't have it done on the main thread, or you'd simply send a message like normal; you need to run it in the background, on a secondary thread.
To achieve this, express it as either an NSOperation object (you create a subclass of NSOperation and instantiate it) or a block (or both), then add it to either an NSOperationQueue (NSOperations, including NSBlockOperation) or a dispatch queue (bare block).
GCD can be used to make things happen on the main thread, as well; you can create serial queues and add blocks to them. A serial queue, as its name suggests, will run exactly one block at a time, rather than running a bunch of them in parallel.
So what should I do?
I would not recommend creating threads directly. Use NSOperationQueue or GCD instead; they force you into better thinking habits that will reduce the risk of your threaded code inducing headaches.
For things that run periodically, not fitting into the “thing I need done” model of NSOperations and GCD blocks, consider just using the run loop on the main thread. Chances are, you don't need to put it on a thread after all. A rendering loop in a 3D game, for example, can be a simple timer.