Ich muss die Leistung einer mit Parse verbundenen iOS-App verbessern. Bisher habe ich überprüft, dass einige findObject-Abfragen zu lange dauern, einige sogar 10 Sekunden!Abfragen analysieren, die zu lange dauern
Ich werde den Code von einer der schlimmsten Fälle setzen und was ich bisher versucht:
+ (void) getAllEvents
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PFQuery *timestampsQuery = [PFQuery queryWithClassName:@"TimeStamp"];
[timestampsQuery fromLocalDatastore];
[timestampsQuery whereKey:@"type" equalTo:@"event"];
// This query very often (not always) takes a couple of seconds
NSArray *timeStampObjects = [timestampsQuery findObjects];
NSArray *timeStamps = [self TransformPFObjectIntoTimeStamp:timeStampObjects];
PFQuery *query = [PFQuery queryWithClassName:@"Event"];
if ([self noNetworkConnection])
{
[query fromLocalDatastore];
}
else
{
[query whereKey:@"user" equalTo:[PFUser currentUser]];
}
[query includeKey:@"admin"];
// This query very often (not always) takes several seconds, 6, 7…even 10 seconds!
NSArray *objects = [query findObjects];
NSMutableArray *eventArray = [NSMutableArray arrayWithArray:[self TransformPFObjectIntoEvents:objects]];
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:eventArray,@"events",timeStamps,@"timestamps", nil];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:GET_ALL_MY_EVENTS object:dict];
});
});
}
+ (NSArray *)TransformPFObjectIntoTimeStamp:(NSArray *)objects
{
NSMutableArray* timestamps = [[NSMutableArray alloc]init];
for (PFObject* object in objects)
{
TimeStamp* timeStamp = [[TimeStamp alloc] init];
timeStamp.parseObject = object;
[timestamps addObject:timeStamp];
}
return timestamps;
}
+ (NSMutableArray *)TransformPFObjectIntoEvents:(NSArray *)objects
{
[PFObject pinAllInBackground:objects withName:PFObjectDefaultPin];
NSMutableArray* eventArray = [[NSMutableArray alloc]init];
for (PFObject* object in objects)
{
Event* event = [[Event alloc] init];
event.parseObject = object;
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation addUniqueObject:object[@"channel"] forKey:@"channels"];
[currentInstallation saveInBackground];
if(event.parseObject[@"imageFile"] != [NSNull null])
{
PFFile *userImageFile = event.parseObject[@"imageFile"];
if (userImageFile != NULL)
{
UIImage *image = [UIImage imageWithData:[userImageFile getData]];
[event setAttributeImage:image];
}
}
[eventArray addObject:event];
}
return eventArray;
}
ich hinzufügen muss, dass der zweite Aufruf von findObjects manchmal gibt mir ein „CFNetwork gescheitert sslhandshake (-9824)“, die mir fremd ist, weil die App die info.plist mit diesen Tasten hat (aber ich denke, das in einer anderen Frage sein sollte):
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Und eine andere Sache, Tabelle‚Ereignis‘hat über 1000 Register.
Was ich habe versucht:
1) Kommentar [timestampsQuery fromLocalDatastore]; Gleiche Ergebnisse, diese Abfragen dauern zu lange.
2) Benutzer findObjectInBackground:
+ (void) getAllMyEvents{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_calls = 0;
PFQuery *timestampsQuery = [PFQuery queryWithClassName:@"TimeStamp"];
[timestampsQuery fromLocalDatastore];
[timestampsQuery whereKey:@"type" equalTo:@"event"];
[timestampsQuery findObjectsInBackgroundWithBlock:^(NSArray * _Nullable objects, NSError * _Nullable error) {
[self completeQueriesWithType:1 andObjects:objects];
}];
PFQuery *query = [PFQuery queryWithClassName:@"Event"];
if ([self noNetworkConnection])
{
[query fromLocalDatastore];
}
else
{
[query whereKey:@"user" equalTo:[PFUser currentUser]];
}
[query includeKey:@"admin"];
[query findObjectsInBackgroundWithBlock:^(NSArray * _Nullable objects, NSError * _Nullable error) {
[self completeQueriesWithType:2 andObjects:objects];
}] ;
});
}
+ (void) completeQueriesWithType:(int)type andObjects:(NSArray *)objs
{
_calls++;
NSArray *timeStamps = nil;
NSMutableArray *eventArray = nil;
if(type == 1)
{
timeStamps = [TimeStamp TransformPFObjectIntoTimeStamp:objs];
}
else if(type == 2)
{
eventArray = [NSMutableArray arrayWithArray:[self TransformPFObjectIntoEvents:objs]];
}
if(_calls == 2)
{
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:eventArray,@"events",timeStamps,@"timestamps", nil];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:GET_ALL_MY_EVENTS object:dict];
});
}
}
Aber es ist immer noch Sekunden dauern, und ich habe diesen Fehler bekommt auch: „Warnung: Eine lang andauernde Operation auf dem Haupt-Thread ausgeführt wird. break on warnBlockingOperationOnMainThread() zu debuggen. "Warum? Wenn ich das im Hintergrund laufen lasse.
Da ich weiß, Parse lokale Datenbank hat einige Auswirkungen auf die Leistung Ich habe zwar auf überhaupt nicht verwenden, entfernen Sie alle seine Erscheinungen, aber ich möchte das Problem mit Parse lokale Datenbank reparieren, wenn es möglich ist.
Also ... warum brauchen diese Abfragen so viel Zeit?
EDIT: Nach @Wain Vorschlag, den ich mit diesem Test beendet haben:
+ (void) getAllEvents
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Running only second of findObjects");
PFQuery *query = [PFQuery queryWithClassName:@"Event"];
if ([self noNetworkConnection])
{
NSLog(@"Reading from local datastore");
[query fromLocalDatastore];
}
else
{
[query whereKey:@"user" equalTo:[PFUser currentUser]];
}
[query includeKey:@"admin"];
// This query very often (not always) takes several seconds, 6, 7…even 10 seconds!
NSLog(@"Just before findObjects");
NSArray *objects = [query findObjects];
NSLog(@"End of running only second of findObjects");
});
}
Mit diesen Ergebnissen:
2016-03-31 11:15:29.295 MyApp[...] Running only second of findObjects
2016-03-31 11:15:29.318 MyApp[...] Just before findObjects
2016-03-31 11:15:38.025 MyApp[...] End of running only second of findObjects
Nur diese Methode NSArray * Objekte = [Abfrage findObjects] ; dauert 9 Sekunden!
EDIT 2 Ich bin mir nicht sicher, ob dies wichtig ist, aber eines der Felder in der „Event“ Tabelle ist eine PFFile (ein Bild). Könnte das die Suchabfrage verlangsamen?
Wenn Sie sagen "nicht die ersten Downloads seriell ausführen", meinen Sie, dass ich so etwas wie meinen 2. Test mit findObjectsInBackground tun und die Ergebnisse mischen sollte? – Wonton
ja, aber das scheint nicht die Hauptursache für den Zeitaufwand zu sein, schauen Sie sich zuerst die Bilddownloads an ... – Wain