IOS Asynchronous picture loading optimization and common open Source Library analysis

Source: Internet
Author: User
Tags gcd

1. The network picture shows the general steps:
    1. Download image
    2. Picture processing (cropping, borders, etc.)
    3. Write to disk
    4. Read data from disk to kernel buffer
    5. Copy from kernel buffer to user space (memory level copy)
    6. Unzip to bitmap (high CPU consumption)
    7. If the bitmap data is not byte-aligned, CoreAnimation it will be copy a copy of the bitmap data and byte-aligned
    8. CoreAnimationRender an uncompressed bitmap

The above 4,5,6,7,8 steps are performed at UIImageView the setImage time, so the default is on the main thread (IOS UI operations must be performed on the main thread).

2. Some optimization ideas:
    • Download Images asynchronously
    • Image decompression drop to child thread
    • Use cache (including memory level and disk level)
    • Store uncompressed images to avoid being decompressed again the next time you load from disk
    • Reduce memory-level copies (for 5th and 7th)
    • Good interface (e.g. SDWebImage use category )
    • Core DataVS file storage
    • Picture Pre-Download
2.1 About asynchronous Picture downloads:

fastImageCacheIt is designed for extreme optimizations that read and display images from disk files, so there is no capability to integrate asynchronous picture downloads. Here's a look at the implementation of Sdwebimage (Afnetworking's basic similarity):

TableView, the management of asynchronous picture download tasks:

We know that Tableviewcell is a reusable mechanism, that is, in memory only the currently visible instances of the number of cells, when sliding, the new cell will reuse the slide out of the Cell object. So there is a problem:

In general, in the Cellforrow method we will set the cell image data source, that is, if a cell ImageView object opens a download task, this time the cell object has been reused, the new image data source will open another download task , 2 download task callbacks to the same ImageView object occur because their associated ImageView object is actually the ImageView object of the same cell instance. At this point it is necessary to do some processing to avoid the wrong image data source refreshing the UI when the callback occurs.

Sdwebimage offers solutions for Uiimageview extensions:

ImageView object will be associated with a download list (list is for animationimages, this time will download multiple images), when TableView sliding, ImageView reset the data source (URL), will cancel the load list of all the tasks, Then open a new download task. This ensures that only the download task associated with the ImageView object of the currently visible cell object can be recalled without image confusion.

At the same time, Sdwebimage manages a global download queue (in Downloadmanager) with a concurrency set of 6. That is, if the number of cells that are visible is greater than 6, a partial download queue will be in the waiting state. Also, when adding a download task to the global download queue, sdwebimage By default is to take a LIFO policy, specifically when adding download tasks, the last added download task added dependent on the newly added download task.

        addOperation:operation];        if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {            // Emulate LIFO execution order by systematically adding new operations as last operation‘s dependency [wself.lastAddedOperation addDependency:operation]; wself.lastAddedOperation = operation; }

Another solution is:

The ImageView object is associated with the URL of the picture, and while it is sliding, it does not cancel the old download task, but instead makes the URL match when the download task completes the callback, only the image that matches the success refreshes the ImageView object, while the other image only caches the cache and does not refresh the UI.

At the same time, an execution queue is still managed, and in order to avoid consuming too many resources, a maximum concurrency is usually set for the execution queue. In addition, in order to guarantee LIFO the download policy, you can maintain a waiting queue, each time the download task starts, the post-entry download task is inserted in front of the waiting queue.

iOS async tasks are typically implemented in 3 ways:
    • Nsoperationqueue
    • GCD
    • Nsthread

These methods are not elaborate, sdwebimage is through the custom nsoperation to abstract download tasks, and combined with GCD to do some of the main thread and sub-thread switching. The implementation of the specific asynchronous download, afnetworking and sdwebimage are very good code, interested can look into the source.

2.2 About Image decompression: A general solution for compression

The main idea is to get an uncompressed picture in a sub-thread, rendering the original picture into a new picture that can be shown in bytes.

Basically, some of the most popular open source libraries have supported the completion of the image in the asynchronous thread decompression, and the uncompressed image after the cache.

The advantage of doing so is that the setImage system eliminates the 6th step above, the disadvantage is that the image occupies a larger space.
For example, 1 images of 50*50 pixels, the retina space occupied by the screen is 100*100*4 ~ 40KB

The following code is SDWebImage the solution:

+ (UIImage *) Decodedimagewithimage: (UIImage *) Image {if (image. Images) {Do not decode animated imagesreturn image; } cgimageref imageref = image. Cgimage;Cgsize imageSize = Cgsizemake (Cgimagegetwidth (Imageref), Cgimagegetheight (Imageref));CGRect Imagerect = (CGRect) {. origin = Cgpointzero,. size = ImageSize}; Cgcolorspaceref colorspace = Cgcolorspacecreatedevicergb (); Cgbitmapinfo bitmapinfo = Cgimagegetbitmapinfo (imageref);int infomask = (Bitmapinfo & kcgbitmapalphainfomask);BOOL Anynonalpha = (Infomask = = Kcgimagealphanone | | infomask = = Kcgimagealphanoneskipfirst | | infomask = kCGImageAlphaNo Neskiplast);Cgbitmapcontextcreate doesn ' t support Kcgimagealphanone with RGB.https://developer.apple.com/library/mac/#qa/qa1037/_index.htmlif (Infomask = = Kcgimagealphanone && cgcolorspacegetnumberofcomponents (colorspace) >1) {Unset the old Alpha info. Bitmapinfo &= ~kcgbitmapalphainfomask;Set Noneskipfirst. Bitmapinfo |= Kcgimagealphanoneskipfirst; }Some PNGs tell us they has alpha but only 3 components. Odd.Elseif (!anynonalpha && cgcolorspacegetnumberofcomponents (colorspace) = =3) {Unset the old Alpha info. Bitmapinfo &= ~kcgbitmapalphainfomask; Bitmapinfo |= Kcgimagealphapremultipliedfirst; }It calculates the bytes-per-row based on the bitspercomponent and width arguments. Cgcontextref context = Cgbitmapcontextcreate (NULL, ImageSize. width, imageSize. Height, cgimagegetbitspercomponent (imageref), 0, ColorSpace, BITMAPINFO); Cgcolorspacerelease (ColorSpace); //If failed, return undecompressed image If (!context) return image; Cgcontextdrawimage (context, imagerect, imageref); Cgimageref Decompressedimageref = cgbitmapcontextcreateimage (context); Cgcontextrelease (context); UIImage *decompressedimage = [UIImage imagewithcgimage:decompressedimageref scale:image. Scale Orientation:image. imageorientation]; Cgimagerelease (DECOMPRESSEDIMAGEREF); return decompressedimage;}           
2.3 About byte alignment

Sdwebimage and afnetworking are not optimized for the 7th, Fastimagecache relative to other open source libraries, the 5th and 7th are optimized. Here we talk about the 7th, the byte alignment of the picture data.

In some cases, the Core animation copies the image data before rendering, usually in the case of non-byte alignment of the image data will be copied processing, the official document does not explain the copy behavior, the simulator and instrument have highlighted "copied images" function, but it seems that it has a bug, even if a picture is not highlighted to be copied during rendering, the Ca::render::copy_image method is still visible from the call stack:

What is byte alignment, according to my understanding, in order to performance, the underlying rendering image is not a pixel one pixel rendering, but a piece of rendering, the data is a block to take, you may encounter this piece of contiguous memory data in the end of the data is not the content of the image, is the memory of other data, Possible cross-reading causes some strange things to get mixed up, so before rendering coreanimation to copy the data for processing, make sure each piece is image data, and empty the data for less than one piece. Approximate figure: (pixel is the image pixel data, the data is other in memory)

The size of the block should be related to CPU cache line, ARMV7 is 32byte,a9 is 64byte, under A9 coreanimation should be 64byte as a piece of data to read and render, Aligning the image data to 64byte prevents Coreanimation from copying a copy of the data for patching. The byte alignment that Fastimagecache does is the thing.

From the code point of view, mainly in the process of creating the decoding, the CGBitmapContextCreate parameters of the function bytesPerRow must pass a multiple of 64.

Compare the code of each open source framework, you can see that sdwebimage and afnetworking This parameter is passed 0, that is, let the system automatically calculate the value (then why the system automatically calculate the time when the image data bytes to the byte alignment?) )。

2.4 about 3rd, 4 points, memory level copies

Of the above 3 open source libraries, Fastimagecache has done a great job of optimizing this, while the other 2 open source libraries are not paying attention to this. This piece of wood has an in-depth study, citing some of the Fastimagecache team's instructions for that point. Have the ability to take a look at the original article (English): here.

Memory mapping
Normally we read a file on the disk, the upper API call to the end will use the System method read () reads the data, the kernel reads the disk data into the kernel buffer, the user then reads the data from the kernel buffer to the user memory space, there is a time consumption of memory copy, And after reading the entire file data already exists in the user memory, occupies the process memory space.

Fastimagecache uses another way to read and write files, that is, to mmap map the file to the virtual memory in the user space, the location of the file in the virtual memory has a corresponding address, you can manipulate the memory like the operation of this file, equivalent to the entire file into memory, But before the actual use of these data will not consume physical memory, there will not be read and write disk operations, only when the actual use of the data, that is, when the image is ready to render on the screen, the virtual memory management system VMS from the disk load the corresponding data block to the physical memory, and then render. Such a file read and write files in a way less data from the kernel cache to the user space copy, high efficiency.

2.5 about the second step picture processing (cropping, borders, etc.)

In general, for downloaded images we may want to do some processing, such as doing some scaling, cropping, or adding rounded corners and so on.

For more general-purpose scaling, or for features such as rounded corners, you can integrate into the control itself. However, it is necessary to provide an interface that allows users to have the opportunity to do some other special processing of the downloaded images.

 /** Sdwebimage * Allows to transform the image immediately after it had been downloaded 
    
     and just before-cache it on disk 
     and memory. * Note:this Method 
      
       is called 
       from a global queue in order to not to block the main thread. *  @param imagemanager the current ' sdwebimagemanager ' *  @param image of the image to transform *  @param imageURL the URL of the image to transform * *  @return Th E transformed Image object. */-(UIImage *) Imagemanager: (Sdwebimagemanager *) Imagemanager transformdownloadedimage: (UIImage *) image withurl: ( Nsurl *) ImageURL;         
         
     
2.6 Other (pre-download, GIF support, etc., download progress bar)

Pending additions

3. Common Open Source Library comparison
Tip Sdwebimage afnetworking Fastimagecache
Download Images asynchronously YES YES NO
Sub-thread Decompression YES YES YES
Sub-threading Picture processing (zoom, fillet, etc.) YES YES YES
Store uncompressed bitmap YES YES YES
Memory level Cache YES YES YES
Disk-level caching YES YES YES
Uiimageview category YES NO NO
Reduce memory-level copies NO NO YES
Interface ease-of-use *** *** *
Resources
    1. Fastimagecache-github
    2. Sdwebimage-github
    3. Afnetworking-github
    4. File System vs Core data:the image cache test
    5. IOS image caching. Libraries Benchmark (sdwebimage vs Fastimagecache)
    6. Avoiding Image Decompression Sickness
    7. iOS image loading speed limit optimization-fastimagecache analysis

IOS Asynchronous picture loading optimization and common open Source Library analysis

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.