0

I have to do some complex calculations which lasts about 30 seconds (decoding some keys). I added and run simple animation (in lottie but I think it doesn't matter) so that the user don't need to get impatient. Because of calculations and processor usage my animation falters.

I tried put [animation play] method into main queue but it doesn't help. Can I guarantee in any way 10% of processor resource for my animation? Or slow down other operations (so that not using all available resources)?

Project example: https://github.com/Redysz/Lottie-Pi-Issue

After start on my iPhone SE "clock" animation can stop for a while somewhere in few first circuits.

Piotr Wasilewicz
  • 1,751
  • 2
  • 15
  • 26

2 Answers2

2

This is your problem:

for(int i = 0; i < 1000; i++) {
    [self performSelectorInBackground:@selector(someHardComputations) withObject:nil];
    [self performSelectorInBackground:@selector(someHardComputations) withObject:nil];
}

(While I realize someHardComputations is just an example, I'm assuming your actual code still uses performSelectorInBackground:.)

This is creating an unreasonable number of background threads (2000). It's not making things faster (you still only have a certain number of cores). It's just dramatically increasing thread contention and interfering with the main thread. There are no good reasons in a modern program to use performSelectorInBackground:.

GCD (dispatch_queue) is the tool you want here. In particular, you want to put this work on a queue with the QoS class UTILITY (also called LOW priority), so that it doesn't compete with your main queue.

See the Concurrency Programming Guide for an introduction to how to use GCD. I can't give you an exact solution, since exactly how to implement this depends heavily on the nature of someHardComputations.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks. What I do here is get some coded hashes from keychain, decode (more... crack) it with math operations and one external framework, create new controller with view based on decoded informations and after all push new controller and stop animation. The most expensive operations are stuff in external framework (animation is smooth without it). I don't have code for it. – Piotr Wasilewicz Nov 28 '17 at 19:27
  • When I tried use `dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAUL` with different priorities I didn't get results from framework methods (application freeze). I think there is many `dispatch_get_main_queue()` in that framework because mine nothing changes. So I started wondering if there is possibility to assign resources for `someHardComputations` which is not my code mostly. – Piotr Wasilewicz Nov 28 '17 at 19:31
  • How many calls are you making to `dispatch_async` in parallel? If you flood the default concurrent queue with 1000s of tasks, that's still going to overwhelm the system. (Also, you don't want DEFAULT here; you want LOW.) That queue is a concurrent queue, so everything is going to run in parallel (and you probably only have two cores). – Rob Napier Nov 28 '17 at 20:00
  • Also, reading from keychain is extremely expensive. If you're doing a lot of that on the main thread, you're going to block the UI. Make sure to run this through Instruments to get a feel for where your problem really is (sometimes it's not where you think it is). If a tight-loop hashing function is dispatching itself to the main thread, that's pretty bizarre; it's hard to imagine why someone would write it that way. Basically breaks the whole point. (So I'd make sure it really does that; seems kind of unlikely; you're probably just swamping the system). – Rob Napier Nov 28 '17 at 20:05
0

I was check you demo app and resolve your issue you should doing change on LOTAnimationView library on this code _animationSpeed = 0.5;Or below code

Update remove your 1000 time call for loop and using timer it's be work very well!

NSTimer *timer =  [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(someHardComputations) userInfo:nil repeats:YES];
[timer fire];


- (void)_commonInit {
   // _animationSpeed = 1;
   _animationSpeed = 0.7;
   _animationProgress = 0;
   _loopAnimation = NO;
   _autoReverseAnimation = NO;
   _playRangeEndFrame = nil;
   _playRangeStartFrame = nil;
   _playRangeEndProgress = 0;
   _playRangeStartProgress = 0;
} 
BuLB JoBs
  • 841
  • 4
  • 20
  • Unfortunatelly it didn't help. – Piotr Wasilewicz Nov 28 '17 at 10:15
  • can you please share your code snippet? so i will identified your issue! – BuLB JoBs Nov 28 '17 at 10:18
  • I wasn't so easy to create example. I edited my first post. I couldn't share original code. – Piotr Wasilewicz Nov 28 '17 at 11:57
  • I don't want gif. I need to use lottie. – Piotr Wasilewicz Nov 28 '17 at 13:02
  • You have only changed animationSpeed. I didn't want that. The speed is good and animation is fine general. Please run this program many times and check that this clock stops for a while (one or two times) in random place. You should run application on phone to see that. It is example animation from here: https://www.lottiefiles.com It is not my animation and it neverminds. It should behave on this site. – Piotr Wasilewicz Nov 28 '17 at 13:43