I'm learning about Unsafe Swift and trying to see if I can translate some C algorithms into it. I've been using some C algorithms in my Swift code for a while in order to get super fast runtime execution speeds for large data sets, but I'd love to get similar speeds written entirely in Swift without needing to include C files.
For my first test, I translated parts of a LinkedList to UnsafeSwift. Here are the C and UnsafeSwift versions and their functions for adding elements to either end of the list:
// C Implementation
typedef struct LinkedList {
struct LinkedListNode *head;
struct LinkedListNode *tail;
} LinkedList;
typedef struct LinkedListNode {
void *data;
struct LinkedListNode *next;
} LinkedListNode;
void LinkedListInsertAtBeginning(struct LinkedList *list, void *newData) {
LinkedListNode *node = malloc(sizeof(LinkedListNode));
node->data = newData;
node->next = list->head;
list->head = node;
if (list->tail == NULL) {
list->tail = node;
}
}
void LinkedListInsertAtEnd(struct LinkedList *list, void *newData) {
if (list->head == NULL) {
LinkedListInsertAtBeginning(list, newData);
} else {
LinkedListNode *node = malloc(sizeof(LinkedListNode));
node->data = newData;
node->next = NULL;
list->tail->next = node;
list->tail = node;
}
}
// UnsafeSwift Implementation
class UnsafeLinkedList<Element> {
struct Node {
var data: UnsafePointer<Element>
var next: UnsafeMutableRawPointer?
}
var head: UnsafeMutableRawPointer?
var tail: UnsafeMutableRawPointer?
func addElementToFront(_ element: Element) {
let mutableData = UnsafeMutablePointer<Element>.allocate(capacity: 1)
mutableData.initialize(to: element)
var newNode = Node(data: mutableData)
newNode.next = head
let nodePointer = UnsafeMutableRawPointer.allocate(byteCount: MemoryLayout<Node>.stride, alignment: MemoryLayout<Node>.alignment)
nodePointer.initializeMemory(as: Node.self, to: newNode)
head = nodePointer
if tail == nil {
tail = head
}
}
func addElementToEnd(_ element: Element) {
let mutableData = UnsafeMutablePointer<Element>.allocate(capacity: 1)
mutableData.initialize(to: element)
let newNode = Node(data: mutableData)
let nodePointer = UnsafeMutableRawPointer.allocate(byteCount: MemoryLayout<Node>.stride, alignment: MemoryLayout<Node>.alignment)
nodePointer.initializeMemory(as: Node.self, to: newNode)
if head == nil {
head = nodePointer
tail = head
} else {
tail.unsafelyUnwrapped.assumingMemoryBound(to: Node.self).pointee.next = nodePointer
tail = nodePointer
}
}
}
The speed of execution in unit tests is about 20% slower than the C LinkedList. I'm kind of new to C and UnsafeSwift, so that's why I'm posting here for advice. Is there anything in my UnsafeSwift code that could be changed to improve its performance?