When is my struct too large? - swift

We're encouraged to use struct over class in Swift.
This is because
The compiler can do a lot of optimizations
Instances are created on the stack which is a lot more performant than malloc/free calls
The downside to struct variables is that they are copied each time when returning from or assigned to a function. Obviously, this can become a bottleneck too.
E.g. imagine a 4x4 matrix. 16 Float values would have to be copied on every assign/return which would be 1'024 bits on a 64 bit system.
One way you can avoid this is using inout when passing variables to functions, which is basically Swifts way of creating a pointer. But then we're also discouraged from using inout.
So to my question:
How should I handle large, immutable data structures in Swift?
Do I have to worry creating a large struct with many members?
If yes, when am I crossing the line?

This accepted answer is not entirely answering the question you had: Swift always copies structs. The trick that Array/Dictionary/String/etc do is that they are just wrappers around classes (which contain the actual stored properties). That way sizeof(Array) is just the size of the pointer to that class (MemoryLayout<Array<String>>.stride == MemoryLayout<UnsafeRawPointer>.stride)
If you have a really big struct, you might want to consider wrapping its stored properties in a class for efficient passing around as arguments, and checking isUniquelyReferenced before mutating to give COW semantics.
Structs have other efficiency benefits: they don't need reference-counting and can be decomposed by the optimiser.
In Swift, values keep a unique copy of their data. There are several
advantages to using value-types, like ensuring that values have
independent state. When we copy values (the effect of assignment,
initialization, and argument passing) the program will create a new
copy of the value. For some large values these copies could be time
consuming and hurt the performance of the program.
https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#the-cost-of-large-swift-values
Also the section on container types:
Keep in mind that there is a trade-off between using large value types
and using reference types. In certain cases, the overhead of copying
and moving around large value types will outweigh the cost of removing
the bridging and retain/release overhead.

From the very bottom of this page from the Swift Reference:
NOTE
The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.
I hope this answers your question, also if you want to be sure that an array doesn't get copied, you can always declare the parameter as inout, and pass it with &array into the function.
Also classes add a lot of overhead and should only be used if you really must have a reference to the same object.
Examples for structs:
Timezone
Latitude/Longitude
Size/Weight
Examples for classes:
Person
A View

Related

How does Automatic Reference Counting work for Value Types in Swift?

I learnt that Swift uses Automatic Reference Counting (ARC) for Memory Management. I want to know how it works for Value Types (struct) in Swift.
From the Swift Language Guide on ARC:
Reference counting applies only to instances of classes. Structures and enumerations are value types, not reference types, and aren’t stored and passed by reference.
Automatic Reference Counting only applies to reference types because those types are:
Always allocated on the heap, because
They must exist in a stable location in memory so that you can be sure that multiple references to the same object are really all pointing to the same exact place (this is part of the concept of identity for objects)
This does mean that some system must keep track of when an instance of a type like this (object) is no longer referenced so the allocation can be cleaned up.
In contrast, value types don't have the same concept of identity that objects do:
They don't require a stable location in memory, and every copy of a value is indistinguishable from another which has the same properties, so
Every time you refer to a value type, you get a copy of it by value (conceptually; there are optimizations to avoid needless copying all over the place)
Value types don't need to be allocated, and don't maintain state that requires cleanup via something like a deinitializer. The net result is that nothing needs to keep track of when a value is last used (since no deallocation is strictly necessary), so no reference counting for cleanup is required.
Advanced note: value types may be allocated on the heap (esp. if they are large enough), but this is an implementation detail of Swift. If a struct is allocated, Swift itself will maintain the allocation and deallocation on your behalf, while still passing it around transparently by value. It's still not possible to have multiple references to this struct, so reference counting is still irrelevant for it (e.g. the reference count could only ever be 0 or 1, so it doesn't make sense to track).

Memory usage: global variables

I am writing an app that requires access to a set of information from all classes and methods.
My query is, what's the most efficient way of doing this, so as to minimise memory usage?
I have taught myself coding and have, of course, come across numerous different methods to solve this whilst trawling the internet. For example:
I could create a global variable such as var info = ..., which I'd place above a class definition, thus giving access from anywhere in the app.
Or I could create a singleton, GameData and have the data stored there, e.g. GameData.shared.info, similarly available from anywhere in the app.
Or I could load the information in the first ViewController and then pass it around as a parameter.
There are no doubt more methods that I haven't come across, but I wonder which is the most memory-efficient method, if indeed there is such a thing. In my case, I won't need access to a huge amount of data - no more than say sixty or seventy records each with half a dozen fields of text or numbers.
Many thanks
Using dependency injection, that is, passing it as a parameter to any object that requires it, would be the more memory conscious method, since the variable will stop existing "automatically" if you were to replace the whole hierarchy (as long as it's done correctly).
By using a singleton or a global variable, you would have to clear the value yourself.
If the value is not going to disappear during the lifetime of the application, then memory usage doesn't matter, but I would still advice against global variables and suggest using dependency injection.

Where is a value type object stored in swift?

I declared an object of Array, like:
let data = ["foo", "bar"]
Array type in swift is value type, where is it stored? heap or stack?
I guess it is stored in heap, but how to access it?
And does it follow ARC rule, when will it release?
Can you give me the graphic of the object's memory?
Given the empty array:
let data = Array<Any>()
Array type in swift is value type, where is it stored? heap or stack?
This is a constant, empty array, so it is stored nowhere. Literally nowhere. If it had some elements in it, the boxes for them would be stored on the stack. The contents of those boxes might be stored on the stack or heap depending on the size. If it had more elements, the boxes would also be stored on the heap.
And does it follow ARC rule, when will it release?
Value types are destroyed when their referent goes out of scope, so whenever data leaves scope. ARC is not relevant here. That said, if there are other reference of the backing (heap) storage, then that storage may not be destroyed until later and ARC is totally relevant (but completely internal, so not related to data).
Can you give me the graphic of the object's memory?
In the case given, the graphic of object memory is:
That's it. There is no memory. But if you put things in it, then it would wildly depend on what you put it in it.
I know I'm being incredibly flippant here. That's on purpose. The answer is "it depends, and also, in most cases, you shouldn't care, and in all cases, it's an internal implementation detail that is not promised and can change from release to release."
The time where you do care is when there's a performance concern, and then you care a lot. Unfortunately, Swift gives almost no promises about that. Even so, we do have a lot of specific information from the Swift team. The best resource is Understanding Swift Performance from WWDC 2016 which explains the internal memory layout. It is likely nothing like you're expecting, and it is incredibly dependent on the specifics of the array. Given the array you've asked about, the answer is "nowhere; it's empty."
In Swift or other language, by default, Value type is stored in Stack and Reference Type is stored in Heap.
If the value is part of a reference type, then, it's stored in Heap.
So we don't need a reference counting and the value will be clean after the end of its scope, or in the other case, when the container is released.
In your example: the data of Array instance will be stored in Stack of the Application while its elements can be stored in Heap, depend on the element is reference type or value typed.

Is there a possibility to create a memory-efficient sequence of bits in the JVM?

I've got a piece of code that takes into account a given amount of features, where each feature is Boolean. I'm looking for the most efficient way to store a set of such features. My initial thought was to try and store these as a BitSet. But then, I realized that this implementation is meant to be used to store numbers in bit format rather than manipulate each bit, which is something I'd like to do (see the effect of switching any feature on and off). I then thought of using a Boolean array, but apparently the JVM uses much more memory for each Boolean element than the one bit it actually needs.
I'm therefore left with the question: What is the most efficient way to store a set of bits that I'd like to treat as independent bits rather than the building blocks of some number?
Please refer to this question: boolean[] vs. BitSet: Which is more efficient?
According to the answer of Peter Lawrey, boolean[] (not Boolean[]) is your way to go since its values can be manipulated and it takes only one byte of memory per bit to store. Consider that there is no way for a JVM application to store one bit in only one bit of memory and let it be directly (array-like) manipulated because it needs a pointer to find the address of the bit and the smallest addressable unit is a byte.
The site you referenced already states that the mutable BitSet is the same as the java.util.BitSet. There is nothing you can do in Java that you can't do in Scala. But since you are using Scala, you probably want a safe implementation which is probably meant to be even multithreaded. Mutable datatypes are not suitable for that. Therefore, I would simply use an immutable BitSet and accept the memory cost.
However, BitSets have their limits (deriving from the maximum number of int). If you need larger data sizes, you may use LongBitSets, which are basically Map<Long, BitSet>. If you need even more space, you may nest them in another map Map<Long, LongBitSet>, but in that case you need to use two or more identifiers (longs).

Objective-C sparse array redux

First off, I've seen this, but it doesn't quite seem to suit my needs.
I've got a situation where I need a sparse array. Some situations where I could have, say 3000 potential entries with only 20 allocated, other situations where I could have most or all of the 3000 allocated. Using an NSMutableDictionary (with NSString representations of the integer index values) would appear to work well for the first case, but would seemingly be inefficient for the second, both in storage and lookup speed. Using an NSMutableArray with NSNull objects for the empty entries would work fairly well for the second case, but it seems a bit wasteful (and it could produce an annoying delay at the UI) to insert most of 3000 NSNull entries for the first case.
The referenced article mentions using an NSMapTable, since it supposedly allows integer keys, but apparently that class is not available on iPhone (and I'm not sure I like having an object that doesn't retain, either).
So, is there another option?
Added 9/22
I've been looking at a custom class that embeds an NSMutableSet, with set entries consisting of a custom class with integer (ie, element#) and element pointer, and written to mimic an NSMutableArray in terms of adds/updates/finds (but not inserts/removals). This seems to be the most reasonable approach.
A NSMutableDictionary probably will not be slow, dictionaries generally use hashing and are rather fast, bench mark.
Another option is a C array of pointers. Allocation a large array only allocates virtual memory until the real memory is accessed (cure calloc, not malloc, memset). The downside is that memory is allocated in 4KB pages which can be wasteful for small numbers of entries, for large numbers of entries many may fall in the same page.
What about CFDictionary (or actually CFMutableDictionary)? In the documentation, it says that you can use any C data type as a key, so perhaps that would be closer to what you need?
I've got the custom class going and it works pretty well so far. It's 322 lines of code in the h+m files, including the inner class stuff, a lot of blank lines, comments, description formatter (currently giving me more trouble than anything else) and some LRU management code unrelated to the basic concept. Performance-wise it seems to be working faster than another scheme I had that only allowed "sparseness" on the tail end, presumably because I was able to eliminate a lot of special-case logic.
One nice thing about the approach was that I could make much of the API identical to NSMutableArray, so I only needed to change maybe 25% of the lines that somehow reference the class.
I also needed a sparse array and have put mine on git hub.
If you need a sparse array feel free to grab https://github.com/LavaSlider/DSSparseArray