Deep recursion in deinit should not happen

Forgive me for the tangent: I tested the ARC and MRC (manual reference counting) version of this simple app that creates and drops a linked list a few times (keeping the list length within limits of the current ARC implementation). It did this in obj-c for simplicity (I suppose I'd get similar results for swift implementation that uses unowned references and some external table to keep strong references to the nodes).

ARC app
// ARC app
#import <Foundation/Foundation.h>

@interface Chained: NSObject {
    @public Chained* next;
}
@end

@implementation Chained
@end

void test(void) {
    NSLog(@"start");
    double allocTime = 0;
    double deallocTime = 0;

    for (int i = 0; i < 10000; i++) {
        double start = CFAbsoluteTimeGetCurrent();
        Chained* first = nil;
        for (int i = 1; i < 30000; i++) {
            Chained* next = [Chained new];
            next->next = first;
            first = next;
        }
        allocTime += CFAbsoluteTimeGetCurrent() - start;
        
        start = CFAbsoluteTimeGetCurrent();
        first = nil;
        deallocTime += CFAbsoluteTimeGetCurrent() - start;
    }
    NSLog(@"allocTime: %f, deallocTime: %f, totalTime: %f", allocTime, deallocTime, allocTime + deallocTime);
    // allocTime: 21.279008, deallocTime: 32.589441, totalTime: 53.868450
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        test();
    }
    return 0;
}
MRC app
// MRC app
//specify -fno-objc-arc for this file in build phases

#import <Foundation/Foundation.h>

@interface Chained: NSObject {
    @public Chained* next;
}
@end

@implementation Chained
@end

void test(void) {
    NSLog(@"start");
    double allocTime = 0;
    double deallocTime = 0;

    for (int i = 0; i < 10000; i++) {
        double start = CFAbsoluteTimeGetCurrent();
        Chained* first = nil;
        for (int i = 1; i < 30000; i++) {
            Chained* next = [Chained new];
            next->next = first;
            first = next;
        }
        allocTime += CFAbsoluteTimeGetCurrent() - start;
        
        start = CFAbsoluteTimeGetCurrent();
        while (first) {
            Chained* cur = first;
            first = cur->next;
            [cur release];
        }
        deallocTime += CFAbsoluteTimeGetCurrent() - start;
    }
    NSLog(@"allocTime: %f, deallocTime: %f, totalTime: %f", allocTime, deallocTime, allocTime + deallocTime);
    // allocTime: 15.840458, deallocTime: 18.275354, totalTime: 34.115811
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        test();
    }
    return 0;
}

Release mode, Intel mac:
ARC: allocTime: 21.27, deallocTime: 32.58, totalTime: 53.86
MRC: allocTime: 15.84, deallocTime: 18.27, totalTime: 34.11

oops. No free lunch with ARC.

PS. There are lies, damned lies, and benchmarks.