When i try to use the ParseObject to store the local data, i find that the performance is very bad, when i execute below codes at IOS 5, will take about 1 - 2 secs for every loop. But seems that the performance is ok at emulator and iphone 5s.
for(int i = 0; i < 20; i++){
PFObject *pfObj = [PFObject objectWithClassName:#"TestStore"];
pfObj[#"TestStore_ID"] = userId;
pfObj[#"TestStore_URL"] = avatarUrl;
[pfObj pinWithName:#"TestStore"];
}
The pinWithName: method is synchronous and pinning executes SQLite statements under the hood, which can be quite slow. You should try using pinInBackgroundWithName: to execute this outside of the main thread.
Related
I'm using XCode's XCTestCase for automated UI testing in order to measure performance of my application. I currently have a UITable with 25 000 elements in it and when trying to run tests that is supposed to swipe this list it takes for ever and crashes before finishing the test. The App targets CPU usage is at 100% at this point.
The last output in the console is:
Snapshot accessibility hierarchy for
When limiting the list down to a few hundred elements(not acceptable) the automated test is able to scroll the list at least but with around a 3-4 seconds wait between each scroll.
Test scenario:
let app = XCUIApplication();
app.buttons["Long list"].tap();
let table = app.tables.element;
table.swipeUp();
table.swipeUp();
So is there any way of speeding up the testing? Perhaps disabling the accessibility hierarchy(not using accessibility labels for the tests any ways).
maybe you can use api like - (double)pressAtPoint:(struct CGPoint)arg1 forDuration:(double)arg2 liftAtPoint:(struct CGPoint)arg3 velocity:(double)arg4 orientation:(long long)arg5 name:(id)arg6 handler:(CDUnknownBlockType)arg7;
#ifndef XCEventGenerator_h
#define XCEventGenerator_h
typedef void (^CDUnknownBlockType)(void);
#interface XCEventGenerator : NSObject
+ (id)sharedGenerator;
// iOS 10.3 specific
- (double)forcePressAtPoint:(struct CGPoint)arg1 orientation:(long long)arg2 handler:(CDUnknownBlockType)arg3;
- (double)pressAtPoint:(struct CGPoint)arg1 forDuration:(double)arg2 orientation:(long long)arg3 handler:(CDUnknownBlockType)arg4;
- (double)pressAtPoint:(struct CGPoint)arg1 forDuration:(double)arg2 liftAtPoint:(struct CGPoint)arg3 velocity:(double)arg4 orientation:(long long)arg5 name:(id)arg6 handler:(CDUnknownBlockType)arg7;
#end
#endif /* XCEventGenerator_h */
- (void)testExample {
XCUIApplication* app = [[XCUIApplication alloc] init];
XCUICoordinate* start_coord = [app coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.3)];
XCUICoordinate* end_coord = [app coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.7)];
NSLog(#"Start sleeping");
[NSThread sleepForTimeInterval:4];
NSLog(#"end sleeping");
for(int i = 0; i < 100; i++)
{
[[XCEventGenerator sharedGenerator] pressAtPoint:start_coord.screenPoint
forDuration:0
liftAtPoint:end_coord.screenPoint
velocity:1000
orientation:0
name:#"drag"
handler:^{}];
[NSThread sleepForTimeInterval:1];
}
}
I am using a Bluno microcontroller to send / receive data from an iPhone, and everything is working as it should, but I would like to update the text of a UILabel with the real time data that is being printed from the Serial.print(numTicks); statement. If I stop the flowmeter the UILabel gets updated with the most current value, but I would like to update this label in realtime. I am not sure if this is a C / Arduino question or more of a iOS / Objective-C question. The sketch I'm loading on my Bluno looks like the following, https://github.com/ipatch/KegCop/blob/master/KegCop-Bluno-sketch.c
And the method in question inside that sketch looks like the following,
// flowmeter stuff
bool getFlow4() {
// call the countdown function for pouring beer
// Serial.println(flowmeterPin);
flowmeterPinState = digitalRead(flowmeterPin);
// Serial.println(flowmeterPinStatePinState);
volatile unsigned long currentMillis = millis();
// if the predefined interval has passed
if (millis() - lastmillis >= 250) { // Update every 1/4 second
// disconnect flow meter from interrupt
detachInterrupt(0); // Disable interrupt when calculating
// Serial.print("Ticks:");
Serial.print(numTicks);
// numTicks = 0; // Restart the counter.
lastmillis = millis(); // Update lastmillis
attachInterrupt(0, count, FALLING); // enable interrupt
}
if(numTicks >= 475 || valveClosed == 1) {
close_valve();
numTicks = 0; // Restart the counter.
valveClosed = 0;
return 0;
}
}
On the iOS / Objective-C side of things I'm doing the following,
- (void)didReceiveData:(NSData *)data Device:(DFBlunoDevice *)dev {
// setup label to update
_ticks = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[_tickAmount setText:[NSString stringWithFormat:#"Ticks:%#",_ticks]];
[_tickAmount setNeedsDisplay];
NSLog(#"ticks = %#",_ticks);
}
Basically I would like to update the value of the UILabel while the flowmeter is working.
UPDATE
I just tested the functionality again with the serial monitor within the Arduino IDE, and I got the same if not similar results as to what I got via Xcode and the NSLog statements. So this leads me to believe something in the sketch is preventing the label from updating in real time. :/ Sorry for the confusion.
I am sure this has already occured to someone but I could not find a trusted source (on Stackoverflow or elsewhere) to solve this.
I have to download a (finite) number of files. I don't know their size prior to downloading them. Their size can greatly change and I don't know it before beginning the download.
It can often happen that I have 9 really small files and 1 really big file.
If I use NSProgress with its "children" feature, I will very quickly show a completion of 90%, then the UI will appear to be stuck (even though it is not the case) since the last file is much bigger.
Here is an example code where I simulate a large file.
- (void)viewDidLoad
{
[super viewDidLoad];
nbTasks = 10;
mainProgress = [NSProgress progressWithTotalUnitCount:nbTasks];
[self launch];
}
- (void)launch {
for (int i = 0; i < nbTasks; ++i) {
[mainProgress becomeCurrentWithPendingUnitCount:1];
[self launchWithNumber:i];
[mainProgress resignCurrent];
}
}
- (void)launchWithNumber:(int)count {
int max = count == 0 ? 100 : 10;
NSProgress *localProgress = [NSProgress progressWithTotalUnitCount:max];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
for (int i = 0; i < max; ++i) {
localProgress.completedUnitCount++;
[NSThread sleepForTimeInterval:1];
}
});
}
How would you handle this case where you cannot change the becomeCurrentWithPendingUnitCount since you don't know its weight prior to begin downloading ?
EDIT: This is what I do for now:
First of all: I lied. I don't download files but data from a database, but it's the same problem in the end.
Before creating my root NSProgress, I download the number of objects from my backend (SELECT count(*) FROM ...). With this I can call becomeCurrentWithPendingUnitCount with the correct "weight" and the progress appears more "smooth".
Of course, this is far from ideal for me since I have to wait some time before showing the first NSProgress, and it makes me do more queries to the backend, but at least the experience is a bit better.
If I could remove this it would be much better. Any ideas?
I'm seeing an issue wherein CFReadStreamRead, as part of a streamed file upload, never returns.
This seems to happen only on iOS7 — and far more often when debugging against a physical device than in the simulator — or at least, it's far more evident there.
We have an HTTP (or HTTPS, the problem occurs either way, with a locally-hosted or remote server) POST of a file, via straight-line, blocking (non-event-driven) CFNetwork calls. It's a necessity of the C code calling this handler; there's no provision for callbacks.
That's well and good, the network calls are happening in background threads and/or via async dispatch.
The network code in question boils down to (removing error handling for brevity):
CFReadStreamRef upload = CFReadStreamCreateWithFile(
kCFAllocatorDefault, upload_file_url);
CFRelease(upload_file_url);
CFReadStreamOpen(upload);
CFReadStreamRef myReadStream = CFReadStreamCreateForStreamedHTTPRequest(
kCFAllocatorDefault, myRequest, upload);
CFReadStreamOpen(myReadStream);
CFIndex numBytesRead = CFReadStreamRead(myReadStream, buf, sizeof(buf));
// etc.
On its own, this code wants to hang immediately under iOS7. If I add a loop with some calls to usleep before it (checking CFReadStreamHasBytesAvailable along the way), it will almost always succeed. Every few hundred tries, it will still fail, never returning. Again, the main thread is unaffected.
I'd hoped the GM would clear up this behavior, but it's still present.
Adding a runloop/callback method to watch for bytes-available events has no effect - when the call hangs, no events are seen, either.
Any suggestions as to why this is happening, or how it can be prevented? Anyone else seeing different CFReadStream behavior under iOS 7?
I've try such nasty workaround and it works for me, problem is that I'm requesting delta values from server, so if something goes wrong I'm just fetching new delta value with, in general case it will not work (in logs I see that timeout kicks in sometimes). At least this prevents form permanent thread blocking and gives a chance to handle somehow this problem:
NSInteger readStreamReadWorkaround(CFReadStreamRef readStrem, UInt8 *buffer, CFIndex bufferLength) {
static dispatch_once_t onceToken;
static BOOL isProblematicOs = YES;
dispatch_once(&onceToken, ^{
isProblematicOs = [[UIDevice currentDevice].systemName compare: #"7.0" options: NSNumericSearch]!=NSOrderedAscending;
});
NSInteger readBytesCount = -2;
if (isProblematicOs) {
CFStreamStatus sStatus = CFReadStreamGetStatus(readStrem);
NSDate *date = [NSDate date];
while (YES) {
if(CFReadStreamHasBytesAvailable(readStrem)) {
readBytesCount = CFReadStreamRead(readStrem, buffer, bufferLength);
break;
}
sStatus = CFReadStreamGetStatus(readStrem);
if (sStatus!=kCFStreamStatusOpen && sStatus !=kCFStreamStatusAtEnd
|| [date timeIntervalSinceNow]<-15.0) {
break;
}
usleep(50000);
}
} else {
readBytesCount = CFReadStreamRead(readStrem, buffer, sizeof(buffer));
}
return readBytesCount;
}
I don't like this solution but so far I don't see an alternative.
I'm trying to debug my games code. I'm developing a game for iOS and my code uses a lot of IF statements. I would like to know if there is even a very small performance hit when using these.
Thanks
Of course there is a performance hit when branching.
But you can't make a reasonable program without branch.
So use the if, and if by profiling your program you detect a problem on a specific location in your code, try to see if you can reduce the numbers of branchings or to put them out of the loops. But don't pay too much attention to it as long as the code remains clear.
Most of the time, the first impact of numerous if is on readability and maintainability. But premature optimization is often a greater hit on those topics.
It depends on where you used your if statements, there are some performance regarding using if in the right way
I will state some of them
Always use the if that is most likely to happen before the else, use the cases that are more common before then use the ones that are less likely
try to use if before the loops,
For example
instead of this
BOOL isCase1 = [self isCase1];
for (int i = 0 ; i < 10000 ; i ++)
{
if(isCase1)
{
//do something
}
else
{
//do some other thing
}
}
use this
BOOL isCase1 = [self isCase1];
if(isCase1)
{
for (int i = 0 ; i < 10000 ; i ++)
{
}
}
else
{
for (int i = 0 ; i < 10000 ; i ++)
{
}
}
Dont assume that you will need to improve performance before you are sure, most of the time your performance is doing good, if you are sure that some code is causing performance issues improve it (dont premature optimize your code)
These are some of the cases, there are much more
UPDATE:
Some other helpful things you could do, cache your boolean checking statments
for example
Instead of
for (int i = 0 ; i < 10000 ; i ++)
{
if([self isCase1]) //Do some thing
}
use
//Cache the result inside a variable
BOOL isCase = [self isCase1];
for (int i = 0 ; i < 10000 ; i ++)
{
if(isCase) //Do some thing
}