Array performance

When I run profiler and click on the extended detail icon ( icon with E in the circle ), it shows me the least performant area of my code for main thread. Turns out its Array's removeLast. Seems surprising. I would have expected this to be a non-event but its dragging my code down. Is there a higher performance way to remove the last element in a Swift Array? I wanted to avoid NSArray -- kind of a pain with Any and where. The swift documentation says removeLast should be O(1) and popLast is O(n). Is it copying the entire array to remove the last item? The array just contains class references.


Before, I was doing some recursion in code that was ported from C++. But it appears that the recursion in Swift was slow. I suspected there might have been retains when I passed data to the recursive function. So, I made it iterative but I still needed a stack -- a swift Array. It was faster but now I've got this removeLast issue.


Is NSArray and NSDictionary still more performant? I was using map in C++ before which always was rock solid.


I ran the code in single file optimized mode and its Swift 3.


Weight Self Weight Symbol Name
5.08 s    7.9% 1.00 ms                            RangeReplaceableCollection<A where ...>.removeLast() -> A.Iterator.Element
3.48 s    5.4% 8.00 ms                             Array.remove(at : Int) -> A
2.98 s    4.6% 2.00 ms                              RangeReplaceableCollection<A where ...>.replaceSubrange<A where ...> (CountableRange<A.Index>, with : A1) -> ()
2.65 s    4.1% 4.00 ms                               Array.replaceSubrange<A where ...> (Range<Int>, with : A1) -> ()
2.25 s    3.5% 1.00 ms                                _arrayOutOfPlaceReplace<A, B where ...> (inout A, Range<Int>, B, Int) -> ()
1.07 s    1.6% 3.00 ms                                 _arrayOutOfPlaceUpdate<A, B where ...> (inout A, inout _ContiguousArrayBuffer<A.Element>, Int, Int, B) -> ()
430.00 ms    0.6% 5.00 ms                                  protocol witness for _ArrayBufferProtocol._copyContents(subRange : Range<Int>, initializing : UnsafeMutablePointer<A.Element>) -> UnsafeMutablePointer<A.Element> in conformance <A> _ArrayBuffer<A>
372.00 ms    0.5% 1.00 ms                                   _ArrayBuffer._copyContents(subRange : Range<Int>, initializing : UnsafeMutablePointer<A>) -> UnsafeMutablePointer<A>
197.00 ms    0.3% 9.00 ms                                    UnsafeMutablePointer.initialize(from : UnsafePointer<A>, count : Int) -> ()
143.00 ms    0.2% 7.00 ms                                     UnsafeMutablePointer.initialize(from : UnsafePointer<A>, count : Int) -> ()
37.00 ms    0.0% 0 s                                     swift::metadataimpl::ValueWitnesses<swift::metadataimpl::SwiftRetainableBox>::initializeArrayWithCopy(swift::OpaqueValue*, swift::OpaqueValue*, unsigned long, swift::TargetMetadata<swift::InProcess> const*)
3.00 ms    0.0% 3.00 ms                                     < infix<A> (UnsafePointer<A>, UnsafePointer<A>) -> Bool
Answered by ahltorp in 185359022

On my computer:


10 million inserts for an array that holds a class instance: 0.2 s

10 million removeLast() on that array: 0.5 s

10 million popLast() on that array: 0.5 s

100 million inserts for an array that holds a class instance: 2.2 s

100 millon removeLast() on that array: 5.4 s

100 millon popLast() on that array: 5.4 s


So, from what I can see, both removeLast and popLast are O(1). Both removeLast and popLast were followed by making a mutating operation on the class instance to ensure that it wasn't optimized away. The class was implemented in Objective-C.


In the above tests, the instance was the same. With a different instance for each element:


10 million inserts: 0.8 s (including instance creation)

100 million inserts: 8.2 s (including instance creation)

10 million removeLast(): 1.5 s

100 million removeLast(): 15.1 s

Can you show the context where you call removeLast ?


RangeReplaceableCollection<A where ...>.removeLast()

Accepted Answer

On my computer:


10 million inserts for an array that holds a class instance: 0.2 s

10 million removeLast() on that array: 0.5 s

10 million popLast() on that array: 0.5 s

100 million inserts for an array that holds a class instance: 2.2 s

100 millon removeLast() on that array: 5.4 s

100 millon popLast() on that array: 5.4 s


So, from what I can see, both removeLast and popLast are O(1). Both removeLast and popLast were followed by making a mutating operation on the class instance to ensure that it wasn't optimized away. The class was implemented in Objective-C.


In the above tests, the instance was the same. With a different instance for each element:


10 million inserts: 0.8 s (including instance creation)

100 million inserts: 8.2 s (including instance creation)

10 million removeLast(): 1.5 s

100 million removeLast(): 15.1 s

The code is running in an iPad Air 2 with iOS 10. Xcode 8.


Regarding Big O notation. I chose removeLast() per documentation. I'm just going with the descriptions at swiftdoc org :


popLast()

Removes and returns the last element of the array.

Returns: The last element of the array if the array is not empty; otherwise, nil.

Complexity: O(n) if the array is bridged, where n is the length of the array; otherwise, O(1). See Also: removeLast()


removeLast()

Removes and returns the last element of the collection.

The collection must not be empty.

Calling this method may invalidate all saved indices of this collection. Don't rely on a previously stored index value after altering a collection with any operation that can change its length.

Returns: The last element of the collection.

Complexity: O(1)


Its traversing a binary tree thats been previously constructed. It use to be a C++ template. Now in Swift, using an iterative approach and not recursion, each node is a generic.The leaves store the paremterized generic type. To determine what is collected there is a callback which the user can customize. The tree might have 10 to approx 15,000 items in it -- depends what the generic is being used for. As an option, the user can sort the result just before return.


Here is another trace. Line 4 was my concern at 7.8% for removeLast. If I click on the routine and instruments shows me the code, then the line for removeLast is blue and it says 54.5%. I anticipated some time being taken in the callback but its at about 19%.


Also, I did set minimum capacity to 100 on the array before hand.


Weight Self Weight Symbol Name
8.96 s   15.8% 0 s                           RBBSPTree.findCollisions(position : [Float], thickness : Float, results : inout [A]?, sort : Bool, clearResults : Bool, callback : ([Float], Float, [Float], Float, inout Float) -> Bool?) -> Bool
8.49 s   15.0% 0 s                             static RBBSPTree.findCollisionsInternalIterative(RBBSPNode<RBBSPLeaf<A>>?, position : [Float], thickness : Float, results : inout [RBBSPLeaf<A>], callback : ([Float], Float, [Float], Float, inout Float) -> Bool?) -> ()
4.41 s    7.8% 1.00 ms                             RangeReplaceableCollection<A where ...>.removeLast() -> A.Iterator.Element
2.99 s    5.3% 21.00 ms                               Array.remove(at : Int) -> A
2.52 s    4.4% 3.00 ms                               RangeReplaceableCollection<A where ...>.replaceSubrange<A where ...> (CountableRange<A.Index>, with : A1) -> ()
2.24 s    3.9% 7.00 ms                                 Array.replaceSubrange<A where ...> (Range<Int>, with : A1) -> ()
1.90 s    3.3% 4.00 ms                                 _arrayOutOfPlaceReplace<A, B where ...> (inout A, Range<Int>, B, Int) -> ()
928.00 ms    1.6% 3.00 ms                                   _arrayOutOfPlaceUpdate<A, B where ...> (inout A, inout _ContiguousArrayBuffer<A.Element>, Int, Int, B) -> ()
330.00 ms    0.5% 1.00 ms                                   protocol witness for _ArrayBufferProtocol._copyContents(subRange : Range<Int>, initializing : UnsafeMutablePointer<A.Element>) -> UnsafeMutablePointer<A.Element> in conformance <A> _ArrayBuffer<A>
147.00 ms    0.2% 1.00 ms                                   protocol witness for _PointerFunction.call(UnsafeMutablePointer<A.Element>, count : Int) -> () in conformance <A where ...> _InitializeMemoryFromCollection<A>
113.00 ms    0.2% 113.00 ms                                   _swift_release_
90.00 ms    0.1% 10.00 ms                                   initializeBufferWithCopyOfBuffer for Array
59.00 ms    0.1% 2.00 ms                                   protocol witness for _ArrayBufferProtocol.count.getter in conformance <A> _ArrayBuffer<A>
59.00 ms    0.1% 51.00 ms                                   _arrayOutOfPlaceUpdate<A, B where ...> (inout A, inout _ContiguousArrayBuffer<A.Element>, Int, Int, B) -> ()
51.00 ms    0.0% 1.00 ms                                   protocol witness for IndexableBase.endIndex.getter in conformance <A> _ArrayBuffer<A>
20.00 ms    0.0% 20.00 ms                                   _swift_retain_
19.00 ms    0.0% 4.00 ms                                   assignWithTake for Array
8.00 ms    0.0% 2.00 ms                                   protocol witness for _ArrayBufferProtocol.init(_ContiguousArrayBuffer<A.Element>, shiftedToStartIndex : Int) -> A in conformance <A> _ArrayBuffer<A>
8.00 ms    0.0% 0 s                                   _ArrayBuffer.requestUniqueMutableBackingBuffer(minimumCapacity : Int) -> _ContiguousArrayBuffer<A>?
5.00 ms    0.0% 2.00 ms                                   ManagedBufferPointer._elementPointer.getter
5.00 ms    0.0% 5.00 ms                                   swift_release
3.00 ms    0.0% 3.00 ms                                   destroyBuffer for Array
2.00 ms    0.0% 2.00 ms                                   static _HeapBuffer._valueOffset() -> Int
2.00 ms    0.0% 2.00 ms                                   swift_bridgeObjectRetain
1.00 ms    0.0% 1.00 ms                                   ManagedBufferPointer._address.getter
1.00 ms    0.0% 1.00 ms                                   protocol witness for _ArrayBufferProtocol.startIndex.getter in conformance <A> _ArrayBuffer<A>
1.00 ms    0.0% 1.00 ms                                   swift_bridgeObjectRelease
1.00 ms    0.0% 1.00 ms                                   associated type metadata accessor for Value in <A, B where ...> _VariantDictionaryStorage<A, B>
655.00 ms    1.1% 3.00 ms                                   _forceCreateUniqueMutableBufferImpl<A where ...> (inout A, countForBuffer : Int, minNewCapacity : Int, requiredCapacity : Int) -> _ContiguousArrayBuffer<A.Element>
97.00 ms    0.1% 8.00 ms                                   type metadata accessor for _InitializeMemoryFromCollection
57.00 ms    0.1% 2.00 ms                                   protocol witness for _ArrayBufferProtocol.count.getter in conformance <A> _ArrayBuffer<A>
51.00 ms    0.0% 2.00 ms                                   _InitializeMemoryFromCollection.init(A) -> _InitializeMemoryFromCollection<A>
46.00 ms    0.0% 46.00 ms                                   _swift_release_
35.00 ms    0.0% 30.00 ms                                   _arrayOutOfPlaceReplace<A, B where ...> (inout A, Range<Int>, B, Int) -> ()
16.00 ms    0.0% 1.00 ms                                   initializeBufferWithCopyOfBuffer for Array
6.00 ms    0.0% 6.00 ms                                   swift_bridgeObjectRelease
1.00 ms    0.0% 1.00 ms                                   protocol witness for _ArrayBufferProtocol.startIndex.getter in conformance <A> _ArrayBuffer<A>
1.00 ms    0.0% 1.00 ms                                   _forceCreateUniqueMutableBuffer<A where ...> (inout A, newCount : Int, requiredCapacity : Int) -> _ContiguousArrayBuffer<A.Element>
1.00 ms    0.0% 1.00 ms                                   swift_bridgeObjectRetain
1.00 ms    0.0% 1.00 ms                                   pod_noop_return(void*, swift::TargetMetadata<swift::InProcess> const*)
1.00 ms    0.0% 1.00 ms                                   swift_release
169.00 ms    0.2% 27.00 ms                                 Array.replaceSubrange<A where ...> (Range<Int>, with : A1) -> ()
72.00 ms    0.1% 1.00 ms                                 _ArrayBuffer.count.getter
35.00 ms    0.0% 35.00 ms                                 _swift_release_
22.00 ms    0.0% 0 s                                 _ArrayBuffer.requestUniqueMutableBackingBuffer(minimumCapacity : Int) -> _ContiguousArrayBuffer<A>?
22.00 ms    0.0% 3.00 ms                                 swift_bridgeObjectRetain
9.00 ms    0.0% 9.00 ms                                 protocol witness for _Pointer._rawValue.getter in conformance UnsafeRawPointer
1.00 ms    0.0% 1.00 ms                                 swift_release
1.00 ms    0.0% 1.00 ms                                 swift_getGenericMetadata
1.00 ms    0.0% 1.00 ms                                 type metadata accessor for Int
1.00 ms    0.0% 1.00 ms                                 _InitializeMemoryFromCollection.init(A) -> _InitializeMemoryFromCollection<A>
1.00 ms    0.0% 1.00 ms                                 __swift_noop_void_return
126.00 ms    0.2% 1.00 ms                                 Range.init(uncheckedBounds : (lower : A, upper : A)) -> Range<A>
94.00 ms    0.1% 27.00 ms                                 RangeReplaceableCollection<A where ...>.replaceSubrange<A where ...> (CountableRange<A.Index>, with : A1) -> ()
19.00 ms    0.0% 19.00 ms                                 __swift_memcpy8_8
13.00 ms    0.0% 13.00 ms                                 _swift_release_
11.00 ms    0.0% 1.00 ms                                 initializeBufferWithCopyOfBuffer for Array
3.00 ms    0.0% 3.00 ms                                 swift_getGenericMetadata
3.00 ms    0.0% 3.00 ms                                 type metadata accessor for Int
3.00 ms    0.0% 3.00 ms                                 protocol witness for RangeReplaceableIndexable.replaceSubrange<A where ...> (Range<A.Index>, with : A1) -> () in conformance <A> [A]
2.00 ms    0.0% 2.00 ms                                 swift_bridgeObjectRelease
2.00 ms    0.0% 2.00 ms                                 protocol witness for RangeReplaceableCollection.replaceSubrange<A where ...> (Range<A.Index>, with : A1) -> () in conformance <A> [A]
2.00 ms    0.0% 2.00 ms                                 Range.init(uncheckedBounds : (lower : A, upper : A)) -> Range<A>
1.00 ms    0.0% 1.00 ms                                 pod_noop_return(void*, swift::TargetMetadata<swift::InProcess> const*)
1.00 ms    0.0% 1.00 ms                                 protocol witness table accessor for Int
230.00 ms    0.4% 15.00 ms                               Array.subscript.getter
181.00 ms    0.3% 5.00 ms                               Array.remove(at : Int) -> A
20.00 ms    0.0% 20.00 ms                               _swift_release_
11.00 ms    0.0% 11.00 ms                               swift_getGenericWitnessTable
2.00 ms    0.0% 2.00 ms                               swift_bridgeObjectRetain
2.00 ms    0.0% 2.00 ms                               swift_getGenericMetadata
1.00 ms    0.0% 1.00 ms                               swift_bridgeObjectRelease
1.00 ms    0.0% 1.00 ms                               swift_release
250.00 ms    0.4% 2.00 ms                               protocol witness for Collection.isEmpty.getter in conformance <A> [A]
189.00 ms    0.3% 1.00 ms                               _ContiguousArrayStorage.__deallocating_deinit
185.00 ms    0.3% 1.00 ms                               swift_deallocClassInstance
161.00 ms    0.2% 23.00 ms                               free_tiny
157.00 ms    0.2% 2.00 ms                               type metadata accessor for Optional
117.00 ms    0.2% 34.00 ms                               RangeReplaceableCollection<A where ...>.removeLast() -> A.Iterator.Element
69.00 ms    0.1% 1.00 ms                               protocol witness for Collection.count.getter in conformance <A> [A]
49.00 ms    0.0% 49.00 ms                               _swift_release_
46.00 ms    0.0% 4.00 ms                               free
43.00 ms    0.0% 6.00 ms                               protocol witness for RangeReplaceableCollection._customRemoveLast() -> A.Iterator.Element? in conformance <A> [A]
39.00 ms    0.0% 3.00 ms                               initializeBufferWithCopyOfBuffer for Array
13.00 ms    0.0% 13.00 ms                               nano_free_definite_size
12.00 ms    0.0% 12.00 ms                               default_zone_free_definite_size
12.00 ms    0.0% 12.00 ms                               associated type metadata accessor for Element in <A where ...> IndexingIterator<A>
10.00 ms    0.0% 10.00 ms                               _swift_release_dealloc
9.00 ms    0.0% 9.00 ms                               rt_swift_getEnumCaseSinglePayload
9.00 ms    0.0% 9.00 ms                               protocol witness for RangeReplaceableIndexable.remove(at : A.Index) -> A._Element in conformance <A> [A]
7.00 ms    0.0% 7.00 ms                               deallocateBuffer for _ClosedRangeIndexRepresentation
6.00 ms    0.0% 3.00 ms                               protocol witness for BidirectionalIndexable.index(before : A.Index) -> A.Index in conformance <A> [A]
5.00 ms    0.0% 5.00 ms                               _TWTu0_rGVs17DictionaryLiteralxq__s10Collections8IteratorPs16IteratorProtocol_
4.00 ms    0.0% 1.00 ms                               RangeReplaceableCollection._customRemoveLast() -> A.Iterator.Element?
3.00 ms    0.0% 3.00 ms                               protocol witness for RangeReplaceableCollection.remove(at : A.Index) -> A.Iterator.Element in conformance <A> [A]
2.00 ms    0.0% 2.00 ms                               associated type metadata accessor for Iterator in <A> [A]
2.00 ms    0.0% 2.00 ms                               allocateBuffer for _ClosedRangeIndexRepresentation
2.00 ms    0.0% 2.00 ms                               swift_bridgeObjectRelease
2.00 ms    0.0% 2.00 ms                               swift_bridgeObjectRetain
2.00 ms    0.0% 2.00 ms                               associated type metadata accessor for Value in <A, B where ...> _VariantDictionaryStorage<A, B>
2.00 ms    0.0% 2.00 ms                               swift_getEnumCaseSinglePayload
1.00 ms    0.0% 1.00 ms                               associated type metadata accessor for _Element in <A> [A]
1.00 ms    0.0% 1.00 ms                               szone_free_definite_size
1.00 ms    0.0% 1.00 ms                               swift::metadataimpl::ValueWitnesses<swift::metadataimpl::SwiftRetainableBox>::storeExtraInhabitant(swift::OpaqueValue*, int, swift::TargetMetadata<swift::InProcess> const*)
1.00 ms    0.0% 1.00 ms                               __swift_noop_void_return
1.00 ms    0.0% 1.00 ms                               _TWTurGSax_s10Collections8IteratorPs16IteratorProtocol_
1.00 ms    0.0% 1.00 ms                               swift::metadataimpl::ValueWitnesses<swift::metadataimpl::SwiftRetainableBox>::getExtraInhabitantIndex(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*)
1.00 ms    0.0% 1.00 ms                               rt_swift_storeEnumTagSinglePayload
1.00 ms    0.0% 1.00 ms                               deallocateBuffer for Optional
1.61 s    2.8% 2.00 ms                             partial apply for thunk
524.00 ms    0.9% 1.00 ms                             IndexingIterator.next() -> A._Element?
385.00 ms    0.6% 82.00 ms                             static RBBSPTree.findCollisionsInternalIterative(RBBSPNode<RBBSPLeaf<A>>?, position : [Float], thickness : Float, results : inout [RBBSPLeaf<A>], callback : ([Float], Float, [Float], Float, inout Float) -> Bool?) -> ()
247.00 ms    0.4% 1.00 ms                             ContiguousArray._copyToNewBuffer(oldCount : Int) -> ()
165.00 ms    0.2% 2.00 ms                             Array._appendElementAssumeUniqueAndCapacity(Int, newElement : A) -> ()
153.00 ms    0.2% 1.00 ms                             Collection.isEmpty.getter
117.00 ms    0.2% 117.00 ms                             _swift_release_
104.00 ms    0.1% 5.00 ms                             Array._makeUniqueAndReserveCapacityIfNotUnique() -> ()
91.00 ms    0.1% 0 s                             type metadata accessor for Optional
80.00 ms    0.1% 0 s                             IndexingIterator.init(_elements : A) -> IndexingIterator<A>
78.00 ms    0.1% 0 s                             Array._getCount() -> Int
77.00 ms    0.1% 0 s                             Array.reserveCapacity(Int) -> ()
68.00 ms    0.1% 4.00 ms                             swift_bridgeObjectRetain
67.00 ms    0.1% 1.00 ms                             Array._reserveCapacityAssumingUniqueBuffer(oldCount : Int) -> ()
51.00 ms    0.0% 7.00 ms                             type metadata accessor for Array
33.00 ms    0.0% 33.00 ms                             swift_getGenericWitnessTable
31.00 ms    0.0% 31.00 ms                             _swift_retain_
31.00 ms    0.0% 31.00 ms                             DYLD-STUB$$type metadata accessor for Optional
15.00 ms    0.0% 15.00 ms                             objc_object::release()
13.00 ms    0.0% 0 s                             type metadata accessor for IndexingIterator
11.00 ms    0.0% 11.00 ms                             swift_bridgeObjectRelease
11.00 ms    0.0% 2.00 ms                             destroyBuffer for RBBSPLeaf
11.00 ms    0.0% 11.00 ms                             rt_swift_getGenericWitnessTable
11.00 ms    0.0% 1.00 ms                             destroy for RBBSPLeaf
10.00 ms    0.0% 1.00 ms                             initializeBufferWithCopyOfBuffer for Array
10.00 ms    0.0% 10.00 ms                             DYLD-STUB$$free
10.00 ms    0.0% 10.00 ms                             protocol witness table accessor for <A> [A]
9.00 ms    0.0% 2.00 ms                             swift::metadataimpl::ValueWitnesses<swift::metadataimpl::ObjCRetainableBox>::initializeWithCopy(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*)
7.00 ms    0.0% 1.00 ms                             type metadata accessor for RBBSPNode
6.00 ms    0.0% 0 s                             static RBBSPTree.findNodeTest([Float], thickness : Float, node : RBBSPNode<RBBSPLeaf<A>>, branchLeft : inout Bool, branchRight : inout Bool) -> ()
3.00 ms    0.0% 0 s                             swift_deallocClassInstance
3.00 ms    0.0% 3.00 ms                             swift::metadataimpl::ValueWitnesses<swift::metadataimpl::ObjCRetainableBox>::initializeWithTake(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*)
3.00 ms    0.0% 3.00 ms                             rt_swift_retain
3.00 ms    0.0% 3.00 ms                             rt_swift_release
3.00 ms    0.0% 3.00 ms                             protocol witness table accessor for <A> [A]
3.00 ms    0.0% 3.00 ms                             rt_swift_storeEnumTagSinglePayload
3.00 ms    0.0% 0 s                             type metadata accessor for RBBSPLeaf
2.00 ms    0.0% 2.00 ms                             deallocateBuffer for _ClosedRangeIndexRepresentation
2.00 ms    0.0% 2.00 ms                             rt_swift_getEnumCaseSinglePayload
2.00 ms    0.0% 2.00 ms                             swift_getEnumCaseSinglePayload
2.00 ms    0.0% 2.00 ms                             _swift_release_dealloc
1.00 ms    0.0% 1.00 ms                             swift_storeEnumTagSinglePayload
1.00 ms    0.0% 0 s                             free
1.00 ms    0.0% 1.00 ms                             swift_release
1.00 ms    0.0% 1.00 ms                             _swift_release_n_
1.00 ms    0.0% 0 s                             free_tiny
1.00 ms    0.0% 1.00 ms                             DYLD-STUB$$swift_bridgeObjectRelease
1.00 ms    0.0% 1.00 ms                             swift::metadataimpl::ValueWitnesses<swift::metadataimpl::ObjCRetainableBox>::getExtraInhabitantIndex(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*)
1.00 ms    0.0% 1.00 ms                             protocol witness table accessor for <A> [A]
1.00 ms    0.0% 0 s                             _ContiguousArrayStorage.__deallocating_deinit
1.00 ms    0.0% 1.00 ms                             DYLD-STUB$$objc_retain
1.00 ms    0.0% 1.00 ms                             DYLD-STUB$$memcpy
1.00 ms    0.0% 1.00 ms                             getExtraInhabitantIndex for RBBSPLeaf

One of my types for a node is final swift class. The leaf information is a struct.


Hmm, I am running single file optimization, though. I suppose the other types are in a different file? Maybe that is the problem? Yes it is! lol Pilot error. 😁


With whole file optimization the removeLast is no longer highlighted blue and its not listed as an issue. Now the callback goes to 75%. Darn.


For kicks, if I keep single file fast optimization and I remove the Swift array [GenericSwiftTypes]() and replace it with NSMutableArray. Then where removeLast() use to be, I change it to :


//let n = stack.removeLast()

let n = stack.lastObject

stack.removeLastObject()


Now when I run instruments, lastObject is 6% and removeLastObject is 6% for a total of 12%. Thats down from 54% to 12%. The callback rises in time now to about 40% but the callback did not change.


So, I suppose after some more observations, whole file optimizaiton solved the issue with the Swift Array. But if your using single file fast optimization then NSMutableArray was faster.

Array performance
 
 
Q