Why stay away from the Heap in Swift development?

Source: Internet
Author: User

Why stay away from the Heap in Swift development?

WWDC video-understanding Swift performance, Apple comes up and says that the Heap is much more complex to operate than Stack. So when you choose a data structure, try to choose a value data type that is stored on the Stack, such as a struct, rather than the type of data stored on the heap like a class. The question is, where is the complexity of the operation compared to the stack,heap?

To answer this question, we have to understand what the Heap is for in Swift. At the same time, what happens on the Heap that causes it to be criticized for performance?

What is a Heap

Heap is generally referred to as two things, one is the heap in the data structure and the other is the heap in memory. This article is about the heap in memory. For the data structure of the HEAP, is a special two-fork tree. It meets the following conditions:

    • The minimum or maximum value of the heap at the root node. All of its child nodes are less than or greater than their parent nodes.
    • The heap is complete with a two-fork tree. All nodes except the lowest level are filled. The bottom-most node fills from left to right.

Specific details here do not expand, online related articles A lot, we can consult on their own.

Anyway In this article, a heap is a block of memory that can be used to dynamically allocate space. There is a keyword in this definition--dynamic allocation.

The so-called dynamic allocation, that is, for data, variables, the system does not pre-allocate a certain amount of space, but according to the program's operation and demand for immediate allocation, it occurs when the program calls in and run (run time). Static allocation is the space that the data needs to be known at compile time, so when the program compiles and connects (compile time), the system allocates space for the corresponding data. As an example:

// assume Defaultcellheight is a static global constant Static 44.0  // assume bar is a VAR used in a specific data structure var bar:myclass?

One of them is a defaultCellHeight floating-point variable, and the required memory size is determined, so its allocation is statically allocated. It is bar a class that, when compiled, does not know how many bytes it has, how much space it takes, and so it is dynamically allocated only after the program has run that the memory can determine the details.

In memory, there are two data areas responsible for dynamically allocating memory, one stack, and the other heap.

Comparison of Heap and Stack in memory management
Heap Stack
Structure Based on linked list, array, tree Stack
Characteristics Manually allocate size, free space at any time, data in and out of disorder Automatic allocation of size, automatic release of memory, advanced data out
Operation After query allocation/release, then do the integration, high degree of complexity Low complexity thanks to stack-bottom pointer movement for allocation/release
Object A reference type such as class. Information such as reference count, variable type, etc. Value types such as struct, enum, Int. function return value, local variable
Scene malloc and free operations in C, MRC, ARC in garbage Collection,ios in Java Applies to undo, save operations
Thread Shared, multithreading is not secure Exclusive, multi-threaded security
Design of the Heap in Swift

The Heap in Swift is implemented by a doubly linked list, and its operation is also called the malloc and Dealloc methods of C + +. So why is a doubly linked list? Let's take a closer look at the analysis.

Just now, the Stack operation is just a pointer movement, so the complexity is low and constant. And the Heap operation is very complex, then what is the specific? Let's take a look at two underlying functions: retain and release.

First clarify the requirements, retain is allocated space, for example [myString retain] , is to assign a string to a certain byte of memory. Release, in other words, frees up space, for example [myString release] , to release the memory allocated by this string.

The most intuitive design: arrays

The simplest and most crude way to design the HEAP is as follows: Design it into an array, where the memory is divided into n equal portions, each of which represents a single byte. Allocate space from left to right, freeing space in the same order, so that all operations are linear. But imagination is beautiful, but reality is cruel. If the HEAP has a total of 10 bytes, we have the following 4 strings:

" ABCD " // Suppose 4 bytes " a "    // Suppose 1 bytes " ABC "  // Suppose 3 bytes " ABCDE "  // Suppose 5 bytes
Then we do the following:

The number of heap leaders for each step this way, note that the number represents the memory size, which represents idle:

[Heap init], [Ten'] [String1 retain]-I [4,6'][string2 retain], [4,1,5'][String3 retain], [4,1,3,2'][String3 release], [4,1,3', 2'][string4 retain]?

At this point we found that although there is 5 bytes of free space in the Heap, it cannot be allocated to String4 because the 5 bytes of free space are not contiguous. The system only considers a 3-byte free space and a 2-byte free space. So we found that the idea of arrays was too naïve to deal with the problem of integrating free space after release.

Linked list design

So we think of a way to solve this problem. If we use the list to connect all the blocks of memory, and when we release it, we can integrate the space by adjusting the list pointers, which will solve the problem we just had. Along this line of thinking, we have implemented the following HEAP structure:

    • The memory block is connected with a linked list
    • The head node of each memory block indicates the size of the memory block and whether the memory block has been retain (0 for free and 1 for occupied)
    • The beginning and the end of the node indicate that the head and tail of the Heap have reached

Retain operation at this time there are three ways to control the choice of design:

    • Traverse the linked list from the beginning. Find the first free block of memory that can allocate enough space. The complexity of such operations is linear.
    • Search the list of spare memory blocks from the previously searched locations and find the appropriate block. This allows you to skip the previously searched blocks of memory that are definitely not compliant, and will generally be a little bit faster.
    • Traverse the linked list from the beginning. Find the most suitable block of free memory (the closest size) so that the space utilization will be high, but the time complexity is higher than the previous two.

Release operation in addition to allocating memory space, but also pay attention to the consolidation of memory blocks. In the example we just [string3 release] had, after that, the memory blocks allocated by it would be integrated with the spare. The process is as follows:

The design has passed the exam. But it has a very serious problem: performance. Because in general, the HEAP is relatively large, each traversal to find free space is more time-consuming, and second, each release must determine the current memory block of the first and last piece is idle, if it is to be integrated separately. This also involves the traversal of the list of queries, of course, the solution is relatively simple, with a doubly linked list.

Optimization: Doubly linked list

The introduction of doubly linked list is mainly the memory block integration problem after the introduction of release, so that the memory block can be queried quickly before and after the empty. And in order to solve the performance problems that were designed to be extremely time-consuming for each traversal, we designed this by simply connecting the free block of memory with pointers to form a linked list. So the data structure of the Heap becomes the following:

So each retain operation, we can walk less than half of the memory (already allocated), the efficiency is theoretically increased by one. and release operation, we can use the LIFO mechanism, the extra free space is inserted into the Heap head, and the original first free space integration. The complexity of this approach is constant and very efficient. Finally, we no longer have to spend extra energy on using 1 and zero to indicate whether the current memory block is empty.


A situation in which free memory blocks are consolidated after the release operation

To improve space utilization, we can also introduce arrays. Each element in the array is a doubly linked list. Each doubly linked list joins the free space in the Heap that is similar in size. So when we are in the retain, we start by the size of the quick positioning to the more appropriate free space in the list, and then do the traversal. As a result, space utilization is improved, the number of traversed elements is reduced, and the Heap is more efficient.

Summarize

Although now Apple has used ARC to help us automatically deal with memory allocation and release problems. We don't need to worry too much about memory scheduling compared to the MRC era manual retain and release operations. However, in terms of optimization, Apple recommends stack and value types because stack has high performance and complexity is almost constant. Although Heap seems freer and more flexible in dynamic memory allocation, it is relatively low in performance and high in complexity. So, the value type of Swift is so popular.

Why stay away from the Heap in Swift development?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.