Added manual memory management "swift unsafe" and C version:
Swift ARC
class StrongNode {
var next: StrongNode? = nil
}
print("start")
var allocTime = 0.0
var deallocTime = 0.0
for _ in 0 ..< 10_000 {
let start = CFAbsoluteTimeGetCurrent()
var first: StrongNode? = nil
for _ in 1...30_000 {
let next = StrongNode()
next.next = first
first = next
}
allocTime += CFAbsoluteTimeGetCurrent() - start
func deallocList() {
first = nil
}
let start2 = CFAbsoluteTimeGetCurrent()
deallocList()
deallocTime += CFAbsoluteTimeGetCurrent() - start2
}
print("allocTime: \(allocTime), deallocTime: \(deallocTime), totalTime: \(allocTime + deallocTime)")
// allocTime: 20.429471373558044, deallocTime: 26.36126732826233, totalTime: 46.79073870182037
print("done")
Swift Unsafe
typealias NodePtr = UnsafeMutablePointer<Node>
struct Node {
var next: NodePtr
static func newNode() -> NodePtr {
let node = calloc(MemoryLayout<Node>.size, 1)!.assumingMemoryBound(to: Node.self)
return node
}
static func deleteNode(_ node: NodePtr) {
free(node)
}
}
print("start")
var allocTime = 0.0
var deallocTime = 0.0
for _ in 0 ..< 10_000 {
let start = CFAbsoluteTimeGetCurrent()
let firstNode = Node.newNode()
var first = firstNode
for i in 1...30_000 {
let next = Node.newNode()
next.pointee.next = first
first = next
}
allocTime += CFAbsoluteTimeGetCurrent() - start
let start2 = CFAbsoluteTimeGetCurrent()
while first != firstNode {
let cur = first
first = cur.pointee.next
Node.deleteNode(cur)
}
deallocTime += CFAbsoluteTimeGetCurrent() - start2
}
print("allocTime: \(allocTime), deallocTime: \(deallocTime), totalTime: \(allocTime + deallocTime)")
// allocTime: 14.85484755039215, deallocTime: 14.128059029579163, totalTime: 28.982906579971313
print("done")
C version
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
typedef struct NodeRec* Node;
struct NodeRec {
Node next;
};
Node newNode(void) {
Node node = malloc(sizeof(Node));
node->next = NULL;
return node;
}
void deleteNode(Node node) {
free(node);
}
void test(void) {
printf("start\n");
double allocTime = 0.0;
double deallocTime = 0.0;
for (int i = 0; i < 10000; i++) {
double start = CFAbsoluteTimeGetCurrent();
Node first = NULL;
for (int i = 0; i < 30000; i++) {
Node next = newNode();
next->next = first;
first = next;
}
allocTime += CFAbsoluteTimeGetCurrent() - start;
double start2 = CFAbsoluteTimeGetCurrent();
while (first) {
Node cur = first;
first = cur->next;
deleteNode(cur);
}
deallocTime += CFAbsoluteTimeGetCurrent() - start2;
}
printf("allocTime: %f, deallocTime: %f, totalTime: %f\n", allocTime, deallocTime, allocTime + deallocTime);
// allocTime: 13.667640, deallocTime: 13.962520, totalTime: 27.630160
printf("done\n");
}
int main(int argc, const char * argv[]) {
test();
return 0;
}
Obj-C ARC: allocTime: 21.27, deallocTime: 32.58, totalTime: 53.86
Obj-C MRC: allocTime: 15.84, deallocTime: 18.27, totalTime: 34.11
Swift ARC: allocTime: 20.43, deallocTime: 26.36, totalTime: 46.79
Swift Unsafe (*): allocTime: 14.85, deallocTime: 14.12, totalTime: 28.98
C version: allocTime: 13.66, deallocTime: 13.96, totalTime: 27.63
(*) - this uses raw memory data structures, unsafe pointers + malloc/free, quite different version compared to others.
(release mode, intel mac)
Edit: fixed bugs above and added "Swift unsafe" manual memory management version for completeness.
Edit 2: added C version.