Mechanism of copying structures in Swift? - struct

What are the mechanism of copying structures in Swift?
Are structures stored in the same place in memory as classes and they are just immutable classes, or structures have their own place to live and die and have their own copy mechanism?
I have read this article, but it seems to be too advanced: https://www.mikeash.com/pyblog/friday-qa-2014-07-18-exploring-swift-memory-layout.html

Related

What is the difference between date transfer object (DTO) and representation object of domain driven design pattern?

I know DTO is returned by the server-side and received by the client-side, but I am confused by the representation object in DDD. I think they are almost the same. Can someone tell me their differences?
Can someone tell me their differences?
They solve different problems in different contexts
Data transfer is a boundary concern - how do we move information from here to there (across a remote interface)? Among the issues that you may run into: the transfer of information is slow, or expensive. One way of keeping this under control is to move information in a larger grain.
the main reason for using a Data Transfer Object is to batch up what would be multiple remote calls into a single call -- Martin Fowler, Patterns of Enterprise Application Architecture
In other words, a DTO is your programs representation of a fat message.
In DDD, the value object pattern is a modeling concern; it is used to couple immutable representations of information and related computations.
A DTO tends to look like a data structure, with methods that can be used to transform that data structure into a representation (for example: an array of bytes) that can be sent across a boundary.
A value object tends to look like a data structure, with methods that can be used to compute other information that is likely to be interesting in your domain.
DTO tend to be more stable (or at least backwards compatible) out of necessity -- because producer and consumer are remote from one another, coordinating a change to both requires more effort than a single local change.
Value objects, in contrast, are easier to change because they are a domain model concern. IF you want to change the model, that's just one thing, and correspondingly easier to coordinate.
(There's kind of a hedge - for system that need persistence, we need some way to get the information out of the object into a representation that can be stored and retrieved. That's not necessarily a value object concern, especially if you are willing to use general purpose data structures to move information in and out of "the model".)
In the kingdom of nouns, the lines can get blurry - partly because any information that isn't a general purpose data structure/primitive is "an object", and partly because you can often get away with using the same objects for your internal concerns and boundary cnocerns.

Managing complex state in FP

I want to write a simulation of a multi-entity system. I believe such systems motivated creation of Simula and OOP where each object would maintain its own state and the runtime would manage the the entire system (e.g. stop threads, serialize data).
On the other hand, I would like to have ability to rewind, change the simulation parameters and compare the results. Thus, immutability sounds great (at least up to almost certain garbage collection issues caused by keeping track of possibly redundant data).
However I don't know how to model this. Does this mean that I must put every interacting entity into a single, huge structure where each object update would require locating it first?
I'm worried that such approach would affect performance badly because of GC overhead and constant structure traversals as opposed to keeping one fixed address of entity in memory.
UPDATE
To clarify, this question asks if there is any other design option available other than creating a single structure that contains all possibly interacting entities as a root. Intuitively, such a structure would imply logarithmic single update penalty unless updates are "clustered" somehow to amortize.
Is there a known system where interactions could be modelled differently? For example, like in cold/hot data storage optimization?
After some research, there seems to be a connection with N-body simulation where systems can be clustered but I'm not familiar with it yet. Even so, would that also mean I need to have a single structure of clusters?
While I agree with the people commenting that this is a vague question, I'll still try to address some of the issues put forth.
It's true that there's some performance overhead from immutability, because when you use mutable state, you can update some values in-place, whereas with immutable state, some copying has to take place.
It is, however, a common misconception that this is causes problems with big 'object' graphs. It doesn't have to.
Consider a Haskell data structure:
data BigDataStructure = BigDataStructure {
bigChild1 :: AnotherBigDataStructure
, bigChild2 :: YetAnotherBigDataStructure
-- more elements go here...
, bigChildN :: Whatever }
deriving (Show, Eq)
Imagine that each of these child elements are big and complex themselves. If you want to change, say, bigChild2, you could write something like:
updatedValue = myValue { bigChild2 = updatedChild }
When you do that, some data copying takes place, but it's often less that most people think. This expression does create a new BigDataStructure record, but it doesn't 'deep copy' any of its values. It just reuses bigChild1, updatedChild, bigChildN, and all the other values, because they're immutable.
In theory (but we'll get back to that in a minute), the flatter your data structures are, the more data sharing should be enabled. If, on the other hand, you have some deeply nested data structures, and you need to update the leafs, you'll need to create a copy of the immediate parents of those leafs, plus the parents of those parents, and their parents as well, all the way to the root. That might be expensive.
That's the theory, though, but we've known for decades that it's impractical to try predict how software will perform. Instead, try to measure it.
While the OP suggest that significant data is involved, it doesn't state how much, and neither does it state the hardware specs of the system that's going to run the simulation. So, as Eric Lippert explains so well, the person who can best answer questions about performance is you.
P.S. It's my experience that when I start to encounter performance problems, I need to get creative with how I design my system. Efficient data structures can address many performance issues. This is just as much the case in OOP as it is in FP.

Is atomicity and immutability two distinct ways of solving the same problems in concurrent/parallel programming?

Is it correct to say that one can choose to design a concurrent/parallel system using atomic operations OR using immutable types? I.e. atomic operations leads to a designing a system of atomically shared state while immutable types leads to designing a system that avoids sharing all-together? Are these two designs essentially substitutes for each other (solving the same underlying problem) or do they address different problems (meaning it might be possible to have to use both atomic operations and immutable types to design a fully concurrency-safe system)?
While both concepts are relevant for concurrent systems, and both guarantee no intermediate state is ever read, they're very different and fit different scenarios. For example, iterating an immutable data structure guarantees correct and "safe" iteration, while mutable data structures are not safe for iteration even if mutating operations are atomic. On the other hand, atomically mutating a shared/central data store guarantees no incorrect data is ever read, while immutability is irrelevant since the store has to change.
Is it correct to say that one can choose to design a concurrent/parallel system using atomic operations OR using immutable types?
This seems somewhat like a forced argument to me. In the example you give, it seems like these two concepts are related but only tenuously. I'd say that these two different concepts both assist in implementing and optimizing concurrent/parallel architectures.
Are these two designs essentially substitutes for each other (solving the same underlying problem) or do they address different problems (meaning it might be possible to have to use both atomic operations and immutable types to design a fully concurrency-safe system)?
They are certainly not "substitutes". I would say that atomicity addresses a specific problem with concurrent systems but immutability is more of a "nice-to-have".
If you are locking between concurrent threads then you will need atomic operations to do (for example) test-and-set and unlock-and-wait operations which are required to share data and do signaling. There probably are other ways to accomplish this without atomicity but it probably gets a lot harder.
Immutable types are a hallmark of a concurrent/parallel architectures because threads can share data safely without worrying about modification. Immutability also helps with data visibility optimizations. But that said, immutability is not a requirement.
I.e. atomic operations leads to a designing a system of atomically shared state while immutable types leads to designing a system that avoids sharing all-together?
Not really. Atomicity is about avoiding race conditions when threads are updating the same state as mentioned above however sharing of state isn't necessarily atomic.
You can certainly share data between 2 threads without either atomicity nor immutable types. Thread #1 updating State1 which is shared by all threads and thread #2 updating State2 which is also shared.

Is it possible to use the Disruptor/Ringbuffer pattern without using a fixed-length array?

We have a Disruptor implementation that has a fixed-length array. Is it possible to implement a version of the pattern that does not rely on this array, but instead contains (possibly self-describing) lists of variable length objects. For example, a Ringbuffer of Protobuf objects?
I'm aware that the fixed-length array is for the "pre-allocation" step, but I consider it possible to approximate that step with one or more object pools.
The ringbuffer in the java version of the disruptor is any array of references to objects. You can put whatever objects you want in there through the EventFactory instance you create.
It's definitely possible to implement a version of the disruptor that isn't backed by an Object array but it won't be high performance. A lot of thought and mechanical sympathy has gone into the design and implementation of the LMAX Exchange Disruptor.
Essentially the ring buffer is an pre-allocated object pool. From my experience, I've never had to worry about managing the ring buffer's resources directly in any real world code. The disruptor will automatically apply back pressure when necessary.
The library provides a nice DSL to construct a dependency graph for your application and basically gives you parallelism for free.

How do I keep track of references in a distributed object graph?

I'm developing a distributed system, which must maintain a distributed object graph, where objects can point to other objects, some of which may be on remote computers. It must also be possible to move objects from one computer to another.
This raises two related problems:
How do we know when it is safe to garbage-collect objects?
If we move an object, how do we robustly ensure that all references to it are updated?
An initial thought is to maintain an exhaustive list of all inbound references.
Of course, this alone isn't sufficient for garbage-collection, as it won't catch cyclic references (same problem as with reference-counting garbage collections).
However this list can be used to ensure that any remote computer with references to the object can be notified if the object is moved.
Another thought is that if an object is moved, it leaves behind a "breadcrumb" on its original computer. If a computer receives a message intended for an object that is no-longer present, it can be forwarded to its new location.
However it is not scalable to keep such references around indefinitely, how do we know when its safe to delete them?
Can anyone provide pointers to existing solutions to this problem, particularly those that deal with replication and concurrency issues too?
The most known solution in Java is implemented as part of the RMI spec.
See Garbage Collection of Remote Objects & Distributed Garbage Collection

Resources