In short: is it fast/cheap? Does it make sense to store a value from NSUserDefaults in memory for faster access?
Longer: say, i have significant number of values to be stored and read from NSUserDefaults; with the need to access(read) those values frequently.
In the snippet below, i initialize a private stored property, and keep it synced with corresponding NSUserDefaults value - so when i need to read it, i read the property.
If reading from the defaults directly is in fact fast, i'd remove the private property, obviously. But i'm unsure of that. Is it fast?
private var _loggedIn = NSUserDefaults.standardUserDefaults().boolForKey("loggedIn")
public var loggedIn: Bool {
get {
return _loggedIn
}
set {
_loggedIn = newValue
NSUserDefaults.standardUserDefaults().setBool(newValue, forKey: "loggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
Clarification for future readers: the question is about reading, not writing/synchronizing, which is (as pointed in the answers) not fast nor cheap.
.synchronize() is called in the setter for a valid reason - in my specific case it is important to have it synched right away, so i sacrifice performance for logic integrity. In general cases, you should consider whether you need to call it - or let the system pick appropriate time for writing.
..In fact, now that i look at it, i see keeping the stored property as it is in the snippet, will provide logic integrity (as long as access from other places happens via the getter, and not directly from userDefaults). So i can avoid synchronizing here as well.
Reading is cheap. There is a generous caching in place and everything happens in RAM. Mutating is relatively cheap, but the system will still have to store the contents to non-volatile memory (a .plist file on the flash) at regular intervals.
Explicit synchronising isn't cheap. It eats time and more energy.
So for reads it is fine, but with a lot of writes I would still do it in a separate container and serialise only as needed.
It's unlikely to have a significant performance impact, but you can profile that yourself using Instruments to ensure the performance impact is negligible.
I made some performance tests with Instruments as #mipadi has suggested the past year and my conclusion was there is no substantial difference.
As I pointed out in a comment above, it's very important to detect which of those NSUserDefaults writes we want to be done straightaway. Just in those particular cases use synchronize method, otherwise leave iOS to handle that work to obtain better performance.
It's all fine unless you use NSUserDefaults as a database. synchronize () will write the complete plist file, so if you store megabytes of data, and then synchronize a lot, performance and/or battery life will suffer.
But check out this question as well: How often are NSUserDefaults synchronised?
An interesting detail is that user defaults will be written when your application terminates. Someone might experiment what happens if your program crashes right after changing NSUserdefaults; if that counts as "termination".
Related
Since Apple's API is not opened source nor it is mentioned in the documentation, when writing in Swift, we have no way, to know whether the returned object is an autorelease objective-c object.
Hence, it becomes unclear when we should use autoreleasepool
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-1041876
If you write a loop that creates many temporary objects.
You may use an autorelease pool block inside the loop to dispose of
those objects before the next iteration. Using an autorelease pool
block in the loop helps to reduce the maximum memory footprint of the
application.
Without autoreleasepool
for ... {
FileManager.default.copyItem
CGImageSourceCreateWithURL
CGImageSourceCopyPropertiesAtIndex
CGImageSourceCreateThumbnailAtIndex
CGImageDestinationCreateWithURL
CGImageDestinationFinalize
}
With autoreleasepool
for ... {
autoreleasepool {
FileManager.default.copyItem
CGImageSourceCreateWithURL
CGImageSourceCopyPropertiesAtIndex
CGImageSourceCreateThumbnailAtIndex
CGImageDestinationCreateWithURL
CGImageDestinationFinalize
}
}
I try to run an intensive loop over the above 2 code for comparison purpose.
I found no significant difference in their memory usage pattern, based on XCode memory report.
I was wondering, what are some good guideline/ thought process, to decide whether we should apply autoreleasepool throughout our code?
I have such concern, as recently I saw autoreleasepool is required in code which involves FileHandle.read - https://stackoverflow.com/a/42935601/72437
Use FileManager to copy item doesn't have a huge payload. And Image I/O you're using will save a lot of memory during the I/O process. In addition, apple's image api will have caches for the same file.
That's why your code won't have a significant difference. Because you didn't make any memory payload.
You could try another way to validate the usage of autoreleasepool. And I can assure that it will have a tremendous difference.
Use for-loop(10000 times) to generate random strings (longer is better), and use each string to transform an UTF-8 data in each loop. Then see different memory growth from the with or without autoreleasepool case.
Try it out.
My company finishing up a new game engine which (like most engines) is very CPU intensive. It is written in Objective-C and most of the core game items which get accessed frequently are stored in object properties. Most of these are automatically synthesized and are simply stored and read.
How much speed, if any, would we gain by changing properties in the core game engine items to be public instance variables?
So whereas it would be declared and accessed like this with a property
#property (nonatomic) CMLocation location;
node.location.x;
It would now be:
#public:
CMLocation location
node->location->x
Logically speaking, I think ivars would be much faster as it should be an almost single clock tick operation (assuming no cache miss), but perhaps the compiler tunes that sort of thing out now and synthesized properties are just as fast.
Can't answer in numbers, but try to describe mechanics "under the hood"
When we access property via node->location->x - it the fastest way, just address lookup in memory, pure c-style.
When we access via node.location.x, obj-c calls getter method for the property, and it's not just classic function call - obj-c performs objc_msgSend( node, #selector( location)), which performs selector look-up by string name. You can find pretty clear description of this process here: https://www.mulle-kybernetik.com/artikel/Optimization/opti-3.html
So, if your code is executed pretty often and it's a bottleneck for performance - yes, you should rewrite it to c-style. Also, keep in mind that struct properties are accessed directly, and when rewriting pay attention to safety - you don't have nil check anymore.
P.S. You can measure performance to find bottlenecks with Instruments and optimize just important code blocks - it's wise approach for optimization.
I am trying to improve our code security. We use a static code analysis tool named CheckMarx. The tool is new at the company, in particular we are the only team to work on iOS with objective C.
I have a parameter class to connect to a server, it contains server address, port, few parameters, login and password
The password should not be taped by user but. It is retrieved as a token from another strong authentication service each time needed. It should not be saved as persistant value (because it change every time), so keychain do not looks to answer my need.
For the demo project, the user will tap it in a textField. That demo projet is under security validation.
When running the analysis, I get a 'heap inspection' vulnerability :
https://cwe.mitre.org/data/definitions/244.html about the password. In theory i understand the problem I should clear the memory space where the password was stored, but I have no idea to achieve this, in objective C.
The password is an NSString, which is immutable, so if i try to overwrite the NSString, I will only create a new string and let the old one somewhere in the heap. (And if I overwrite it anyway in dealloc method, i get another warning saying that hardcoded string is a bad practice for password).
renaming the variable into another dummy variable name like MyDummyPropThatContainsData
1) ARC will clear the pointer but i do not think it will clean up the heap. So i believe this is not a false positive. Am i wrong ?
2) I have try using a NSMutableString allocated with MAX_SIZE_PASSWORD. I use the setString method to set the variable (at the same place). I erase it in the dealloc method by calling setString method with a dummy value of exactly MAX_SIZE_PASSWORD. It removed the warning, is it a good practice ?
I am quite sure that this should be another warning saying that hardcoded string is a bad practice for password, but it is not detected. I suppose the bad practice remains ...
3) I have thought to use a char* so i would be able to memset it later, but it sounds bad to me. I am afraid that it could be a reliability and maintenance issue. Is this could solve my problem ? is it recommanded with ARC to manage myself allocation of char * everywhere I need to manage passwords ?
I have found nothing in objective C to prevent Heap Inspection vulnerabilities. Is there some common way to prevent that in objective C ?
Do you know some good points where to start ?
Any help appreciated !
One comment and also a recipe. In a system that supports either no swap or an encrypted swap, nil-ling out the data is mostly moot. The main remaining attack to discovering the password is directly attaching to the running app. I use the keychain modes to defend against this attack.
The goal is to erase the secret on the heap.
As I keep passwords in my keychain, they are returned as an NSData BLOB. This is key. You can then initialize an NSString with the BLOB's bytes and disallow the string from owning them (freeWhenDone: NO). While I cannot guarantee that NSString does not copy the data, it appears to be the case. (Make sure you do not specify an encoding that causes the NSString to have to recast the data. UTF-8 generally works fine.)
When you are done with the password NSString, release it. (Using ARC, set it to nil.)
Now the key to cleaning up the heap is to use the NSData routine to enumerate through each of its byte arrays, typically there is only one, and then set the bytes to NULL. If you prefer, you can bang in random bytes. You can now release the NSData BLOB.
Yes, this breaks all of the rules of mutability preservation. That is what unsafe pointer operations are for. They are unsafe. But you are also doing something in a specific place for a very good reason.
As this is a rather delicate operation, I hesitate to share code that implements the above algorithm. IMO, you need to be responsible for your own security hygiene.
If the above isn't clear, I'm happy to refine the answer further.
I have been looking at Swift the last couple of days and it looks good, I am confused on a point though even after review of the guide Apple published.
I understand that memory management in Swift uses ARC and therefore quite safe, however in situations where I'd like more fine grained control of object creation and destruction I'm slightly confused.
Take these two simple examples:
In ObjC, when you'd (for example) like a UIViewController you intend to push to stay around for the lifetime of your app and only be created once (say because it's expensive to create), you'd make it a property and then wrap it's Alloc Init like this:
if (!self.myProperty)
{
self.myProperty = [[MyObj alloc] init];
}
This way it only creates once, keeps state and the same object instance can be reused indefinitely, yielding known object references, and good performance not having to recreate each time the viewController goes out of scope.
Another example of this is with NSMutableString, vs Swifts String.
You can set an NSMutableString's string many times and it will keep the same object reference, however this doesn't seem to be the case with a Swift String when changing it.
This may just be 'deprecated thinking in Objective C' but is there a best practice with regard to keeping around expensive objects or to keep state (same object) for certain objects during the lifetime of their usage.
I think what you're looking for is a "Lazy stored property":
The example in the swift docs is:
class DataManager {
#lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
and it says about #lazy:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the #lazy attribute before its declaration.
The comment about NSMutableString is a little different, you can continue to use NSMutableString in your swift code, but Apple are encouraging developers to use the Swift built-in types whenever possible :)
see the "String Mutability" section in the swift docs
What happens to an object when it's dealloced? Is all the memory nulled out, or do traces still remain?
If I understand it correctly, an app's memory is saved to flash storage if it resigns active. Assume a resourceful hacker that is able to read out this memory. Will he theoretically sometimes be able to read out the contents of a dealloced NSString if that memory hasn't been overwritten with something?
Don't store secure data in Objective C data types. They are opaque data types, and could be making and/or leaving lots of copies of your data in memory every time you try to even clear some portion.
Added: The same appears to be true about Swift data types, including structs, arrays and strings. They are opaque, thus who knows how many copies of data might be left around in DRAM.
Use non-opaque plain C data types (array of chars, etc.), which you can bzero as soon as you are finished using them, and whenever the app resigns being active. You could also obfuscate the array elements to make string searching through memory dumps a little more difficult.
Even with a jailbroken iDevice, that would be unlikely, as the location for the memory is probably so deep. If you are really concerned about that, here is a solution, if you are not worried about overhead of NSMutableString (dealloc of your class):
-(void) dealloc
{
for (int i = 0; i < [myString length]; i++)
{
[myString replaceCharactersInRange:NSMakeRange(i, 1) withString:#"*"];
}
[myString release]; // or dealloc
// clean up rest
[super dealloc]; // dont forget this :)
}
So you also raised the issue about writing off to Flash. If your app goes into background, it will not necessarily release the objects - and give you the opportunity to erase them (as discussed in the other answer).
IF you're really concerned about this - I'd disable Fast App Switching on your app to make sure this never happens, in addition to implementing some sort of object over-erase code on dealloc, as discussed above.