Is there a way to know if two addresses, which are references to two objects are connected ? By connected I mean whether one of the objects holds a reference to the other object.
In most languages, the memory storing the object referencing the other will contain a pointer to the other object. The difficulty is then to determine where this memory starts and end.
If you are in .Net, there is a windbg extension named sosex that exposes a !refs command displaying the immediate references from and to a given object.
If you are in native code, you can use !heap -p -a to obtain the logical memory block containing an object and then check if this memory contains a pointer to the memory of the other object.
Related
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).
It is a common fact that it is better in a certain circumstances to pass a parameter by reference to avoid costly copying. But recently I watched a Handmade Hero series where Casey said that if the object is not too complex sometimes it's better to pass it by value. I'm not too familiar with low-level details, but I assume it's connected with a cache. Could someone give more solid explanation of what's going on?
If you pass by value you are likely passing via registers (assuming not too many arguments and each one is not too large). That means the callee doesn't need to do anything to use the values, they are already in registers. If passing by reference, the address of each value may be in a register, but that requires a dereference which needs to look in the CPU cache (if not main memory), which is slower.
On many popular systems you can pass-by-value roughly 5-10 values which are each as wide as an address.
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.
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
I'm developing an iPhone application and am new to Objective-C as well as SQLite. That being said, I have been struggling w/ designing a practical data management solution that is worthy of existing. Any help would be greatly appreciated.
Here's the deal:
The majority of the data my application interacts with is stored in five tables in the local SQLite database. Each table has a corresponding Class which handles initialization, hydration, dehydration, deletion, etc. for each object/row in the corresponding table. Whenever the application loads, it populates five NSMutableArrays (one for each type of object). In addition to a Primary Key, each object instance always has an ID attribute available, regardless of hydration state. In most cases it is a UUID which I can then easily reference.
Before a few days ago, I would simply access the objects via these arrays by tracking down their UUID. I would then proceed to hydrate/dehydrate them as I needed. However, some of the objects I have also maintain their own arrays which reference other object's UUIDs. In the event that I must track down one of these "child" objects via it's UUID, it becomes a bit more difficult.
In order to avoid having to enumerate through one of the previously mentioned arrays to find a "parent" object's UUID, and then proceed to find the "child's" UUID, I added a DataController w/ a singleton instance to simplify the process.
I had hoped that the DataController could provide a single access point to the local database and make things easier, but I'm not so certain that is the case. Basically, what I did is create multiple NSMutableDicationaries. Whenever the DataController is initialized, it enumerates through each of the previously mentioned NSMutableArrays maintained in the Application Delegate and creates a key/value pair in the corresponding dictionary, using the given object as the value and it's UUID as the key.
The DataController then exposes procedures that allow a client to call in w/ a desired object's UUID to retrieve a reference to the actual object. Whenever their is a request for an object, the DataController automatically hydrates the object in question and then returns it. I did this because I wanted to take control of hydration out of the client's hands to prevent dehydrating an object being referenced multiple times.
I realize that in most cases I could just make a mutable copy of the object and then if necessary replace the original object down the road, but I wanted to avoid that scenario if at all possible. I therefore added an additional dictionary to monitor what objects are hydrated at any given time using the object's UUID as the key and a fluctuating count representing the number of hydrations w/out an offset dehydration. My goal w/ this approach was to have the DataController automatically dehydrate any object once it's "hydration retainment count" hit zero, but this could easily lead to significant memory leaks as it currently relies on the caller to later call a procedure that decreases the hydration retainment count of the object. There are obviously many cases when this is just not obvious or maybe not even easily accomplished, and if only one calling object fails to do so properly I encounter the exact opposite scenario I was trying to prevent in the first place. Ironic, huh?
Anyway, I'm thinking that if I proceed w/ this approach that it will just end badly. I'm tempted to go back to the original plan but doing so makes me want to cringe and I'm sure there is a more elegant solution floating around out there. As I said before, any advice would be greatly appreciated. Thanks in advance.
I'd also be aware (as I'm sure you are) that CoreData is just around the corner, and make sure you make the right choice for the future.
Have you considered implementing this via the NSCoder interface? Not sure that it wouldn't be more trouble than it's worth, but if what you want is to extract all the data out into an in-memory object graph, and save it back later, that might be appropriate. If you're actually using SQL queries to limit the amount of in-memory data, then obviously, this wouldn't be the way to do it.
I decided to go w/ Core Data after all.