Tableview optimization Overview (from the network)

Source: Internet
Author: User

1. Cell child control creation written in Initwithstyle:reuseidentifier

2, the background calculation height, layout. Put in the collection the next time you use it.

3. Some of the displayed content has rich text, especially when converting from HTML to attribute strings.

Solution, the backend translates the required property strings in advance, and then caches them to avoid the CPU performance consumed by the recurring conversions. can refer to Dtcoretext from the HTML conversion attribute string idea, he is gcd backstage conversion.

4, picture fillet, shadow and other operations, will cause off-screen rendering. Consumption of CPU performance.

Solution: Use a picture to cover, or the background to draw the picture as a rounded picture display.

5, some show a lot of pictures of the place, the server picture is very large, not your control size.

Solution: The server returns a picture of the control's height, such as seven kn can be used to stitch parameters in the image path to get the specified width.

6, the view hierarchy complex situation, the CPU mixes them to be very consumes the resources

Solution: If not avoided, you can draw your view into a picture to display, of course, the process of rendering in the background. Can refer to the idea of Vvebotableviewdemo.

7, do not use SB and xib to create a cell with pure code to create

8, abandon the automatic layout with coordinates to calculate the layout

9, put some influence CPU operation in the background to operate, and then cache everything can be cached things

10, the cell height is not cached, this must have an impact

11, the short time refreshes 2 times, certainly will card. Prevents multiple refreshes in short time

12, repeatedly create view is not desirable ... are generally created at initialization time and then controlled to show and hide

13. Rounded corners. Be careful not to make the rounded corners the number of frames in your list killer

14, modify the size of the download picture.

15. Write the file to a sub-thread

16, the location of the network request when scrolling

17. separate assignment and calculation layout . This lets Tableview:cellforrowatindexpath: The method only assigns the value, Tableview:heightforrowatindexpath: The method is only responsible for calculating the height. Both need to be as simple and easy to calculate as possible.

18, after obtaining the data, the corresponding layout is calculated directly according to the data source, and cached to the data source , so that in the Tableview:heightforrowatindexpath: Method directly return the height, and do not need to calculate each time.

19, add the Draw method to the custom cell, (of course, you can rewrite DrawRect) and then implement it in the method body, each of which is drawn according to the previously calculated layout. Here is the need to draw asynchronously, but if you override the DrawRect method you do not need to use GCD async thread, because DrawRect is originally drawn asynchronously. For the drawing of picture and text mix, can shift Google, research under Coretext.

20. When sliding uitableview , load the corresponding contents on demand. // load on Demand - if the target row differs from the current row by more than the specified number of rows, only 3 lines are loaded before and after the target scroll range.

-(void) scrollviewwillenddragging: (Uiscrollview *) ScrollView withvelocity: (cgpoint) Velocity targetcontentoffset: ( InOut Cgpoint *) targetcontentoffset{

Nsindexpath *ip = [self indexpathforrowatpoint:cgpointmake (0, Targetcontentoffset->y)];

Nsindexpath *CIP = [[self indexpathsforvisiblerows] firstobject];

Nsinteger Skipcount = 8;

if (Labs (Cip.row-ip.row) >skipcount) {

Nsarray *temp = [self indexpathsforrowsinrect:cgrectmake (0, Targetcontentoffset->y, Self.width, Self.height)];

Nsmutablearray *arr = [Nsmutablearray arraywitharray:temp];

if (velocity.y<0) {

Nsindexpath *indexpath = [temp lastobject];

if (Indexpath.row+3<datas.count) {

[Arr Addobject:[nsindexpath indexpathforrow:indexpath.row+1 insection:0];

[Arr Addobject:[nsindexpath indexpathforrow:indexpath.row+2 insection:0];

[Arr Addobject:[nsindexpath indexpathforrow:indexpath.row+3 insection:0];

}

} Else {

Nsindexpath *indexpath = [temp firstobject];

if (indexpath.row>3) {

[Arr Addobject:[nsindexpath indexpathforrow:indexpath.row-3 insection:0];

[Arr Addobject:[nsindexpath indexpathforrow:indexpath.row-2 insection:0];

[Arr Addobject:[nsindexpath indexpathforrow:indexpath.row-1 insection:0];

}

}

[Needloadarr Addobjectsfromarray:arr];

}

}

Remember to add judgment in the Tableview:cellforrowatindexpath: method:

if (Needloadarr. count>0&&[needloadarr indexofobject:indexpath]==nsnotfound) {

[Cell Clear];

return;

}

When scrolling quickly, only the cells within the target range are loaded, so that loading on demand greatly improves smoothness.

Reference: Https://github.com/johnil/VVeboTableViewDemo

21, pre-calculation and cache the height (layout), because Heightforrowatindexpath: is the most frequent method to call;

22, asynchronous drawing, encountered a complex interface, encountered performance bottlenecks, may be a breakthrough;

23, when the sliding load on demand, this in a large number of picture display, the network load is very useful! (Sdwebimage has implemented asynchronous loading, with this performance leverage).

24. correct use of reuseidentifier to reuse cells

25. Try to make all view opaque, including the cell itself

26. Try to use less or no transparent layers

27. If the real content in the cell comes from the web, using asynchronous loading, the cache request results

28, reduce the number of subviews

29, in Heightforrowatindexpath: Try not to use Cellforrowatindexpath:, if you need to use it, only once and then cache the results

30, as far as possible with AddView to the cell dynamic add view, can be added when initialized, and then through hide to control whether the display

31, want to improve efficiency, or manual write useful! Throw away Xib, storyboard need system automatic transcoding, add a layer of burden to the system not to talk about, custom cell drawing is not the start

32 . The benefits of defining only one Cell

Reduce the amount of code, reduce the number of nib files, unified a nib file definition cell, easy to modify, maintenance.

Based on cell reuse, the number of cells needed to fully run the screen is roughly fixed and set to N . So if there is only one cell, it is an instance of only N cells, but if there is m type cell, then the runtime may be an instance of "m x N = MN" cell, although it may not consume too much memory , but it's better to be less.

33, use hidden Hide (show) Subview.

34. Calculate and cache the height of each cell in advance

35, in the Model (entity) to calculate and save the height of the cell, in fact, in the Model (entity) to save the UI parameters is very strange =. = (preferably in ViewModel, which is the MVVM pattern

36, in advance to create the real display, need to process the data and cache, cell display content, many times may not be directly from the server to get the data, but the "processing" of data. As in this article "dynamic" also, each cell's title, the body has clickable link link, the expression picture and so on rich text content, but we generally use the Nsattributestring class to display.

Since each time will be used, rather than in the acquisition of data at the time of the creation, processing of these content, until the need for reality, the direct use of the line.

37. Cache view! Yes, when some of the view in the cell is very independent, and is not easy to reuse, and "volume" is very small, in the premise of memory controllable, we can completely cache these view! The method of course also places the cached view in the entity ~.

38, try to set the cell view as opaque, to avoid the GPU on the contents of the cell below also draw.

39, avoid a large number of image scaling, color gradient and so on.

40, to avoid synchronization from the network, file access to data (this is a must =. =

41. Create a shadow with Shadowpath.

42, minimize the number of subview, such as multi-use drawrect drawing elements, instead of the view display.

43, try to display the " size just right " picture resources.

44, cache everything can be cached! is " replace time with space "!

45, in UITableView of the Delegate , DataSource method, reduce any unnecessary operations

46, for NSDateFormatter time cost out of reuse objects, try to avoid using it to handle multiple date formats. Of course, for date format processing if you need to increase speed, you can use C directly, you can use a third-party library to circumvent this problem.

47. The large use of the Imagenamed method adds additional overhead to the CPU in places where it does not need to be cached. When the application needs to load a larger picture and use a one-time, then there is no need to cache this picture, with Imagewithcontentsoffile is the most economical way , so that the CPU will be wasted too much time on the unnecessary cache one by one because of the uiimage element.

48, for a single view try not to viewwillappear time-consuming operation, viewwillappear before the view display is called, for efficiency considerations, in this method do not deal with complex time-consuming things; You should only set the view in this method Simple things like background color, font, and so on. Otherwise, the user will obviously feel a dull view display.

49,Reloaddata method Try not to call

50, if the height of the row must be, then delete the agent in this Tableview:heightforrowatindexpath: method, set the RowHeight property of Table View, similar numberofrowsinsection : The method of the series, I will not write it all. This can also reduce the call time as described in the Apple documentation.

51, with " Space for Time " , the time to calculate the high line to the data from the server back to the time, calculated the height and write back to the database.

52, directly set the image View of the contentmode property to the image view itself /c9> compression. This is a very trickery approach, but the scrolling speed of table View can also have a noticeable effect. The picture deformation needs to do transform to the picture , each compress the picture to multiply a transformation matrix to the picture, if your picture is many, this computation quantity is different ignores.

After the picture from the network back to the image according to the size of the image to fit into the appropriate size of the picture, each time only show the processed size of the image, when viewing a large map in the display large image. If the server can directly return the pre-processed small picture and the image size is better.

53. In the Settings View of the Frame high-split screen to avoid 21.3 , 6.7 such decimals, especially x , y coordinates, with Ceil or Floor or round Rounding . Each 0.5 point corresponds to a pixel,0.3,0.7 Such a difficult IPhone , low split screen do not appear decimal.

54, manual drawing method, not directly sub-class UITableViewCell, and then overwrite DrawRect: method, so you will get a big black block! Because there is not only one content view in the cell. If you don't understand the cell hierarchy, you can use Reveal to see it. The GPU does not like transparency, so all drawings must be opaque, and for fillets and shadows these can be truncated to a pseudo-transparent small figure and then plotted. In the layer callback must also only do the drawing, do not calculate!

55, do not use AutoLayout, do not use AutoLayout, do not use AutoLayout. We do manual layout, are very simple linear calculation, the CPU will not waste time, the CPU pressure is not very large, thus balancing the load of the CPU.

56, when a control itself is opaque, pay attention to set opaque = YES, this way can avoid useless alpha channel composition, reduce GPU load.

57, the control set Cornerradius after the clip or mask operation, will lead to offscreen rendering, and this is done in the GPU, so fast sliding tableview, if more rounded objects, will cause GPU load greatly increased. At this point we can set the Shouldrasterize property of the layer to Yes, and we can transfer the load to the CPU. A more thorough approach is to draw rounded pictures directly in the background and output them to the main thread display, avoiding the use of attributes such as fillets, shadows, masks, etc.

58, transfer part of the GPU rendering to the CPU, then how to transfer it? We can overload the DrawRect: Method in a single control, draw the text and picture directly and then output it to the main thread. You can also set dictionary to attributes to achieve the desired text effect. This code disables some of the blending operations and reduces the burden on the GPU, making the UITableView slide smoother.

59, the use of lightweight objects to replace the weight of the object, you can optimize performance. For example, Calayer is much lighter than UIView, so it is more appropriate to use Calayer to display a control that does not need to respond to touch events. If the object does not involve UI operations, it is put to the background thread to create, but unfortunately contains the Calayer control, can only be created and manipulated in the main thread.

60, try to postpone the creation of the object time, and the creation of objects scattered across multiple tasks. Although this is difficult to achieve, and the advantages are not many, but if you have the ability to do it, or try as much as possible. If the object can be reused, and the cost of reuse is smaller than freeing and creating new objects, such objects should be reused as much as possible in a cache pool.

61, in the application, should minimize the unnecessary property modification.

62. When the view level is adjusted, there are many method calls and notifications between UIView and Calayer, so you should try to avoid adjusting the view hierarchy, adding and removing views when optimizing performance.

63, the destruction of objects, although the consumption of resources is not much, but the accumulation is not to be ignored. Typically, when a container class holds a large number of objects, the resource consumption is very obvious when it is destroyed. Similarly, if the object can be placed in the background thread to release, then move to the background thread. Here's a tip: Capture the object into a block and throw it into the background queue to send a message to avoid a compiler warning so that the object can be destroyed in the background thread.

Nsarray *tmp = Self.array;

Self.array = nil;

Dispatch_async (Queue, ^{

[TMP class];

});

64, as far as possible to calculate the layout in advance, when necessary to adjust the corresponding properties at once, rather than multiple, frequent calculation and adjustment of these properties.

65, if you do not have special requirements for text display, you can refer to the following UILabel internal implementation: using [nsattributedstring BoundingRectWithSize:options:context:] To calculate the text width, with the-[ Nsattributedstring DrawWithRect:options:context:] to draw the text. Although these two methods perform well, they still need to be placed in a background thread to avoid blocking the main thread.

66, the screen can see all the text content control, including UIWebView, at the bottom are through coretext typesetting, drawing for Bitmap display. Common text controls (UILabel, Uitextview, and so on), whose layout and drawing are made on the main thread, can be very stressful when large amounts of text are displayed. For this solution there is only one, which is the custom text control, which is drawn asynchronously with Textkit or the bottommost coretext. Although this implementation is very troublesome, but its advantages are also very large, Coretext object creation, can directly obtain the text of the wide and high information, to avoid multiple calculations (adjust the size of the UILabel once, UILabel when drawing the internal calculation again); Coretext Object consumes less memory and can be cached for multiple renderings later

67. When you create a picture with UIImage or cgimagesource, the image data is not decoded immediately. The image is set to Uiimageview or calayer.contents, and the data in the Cgimage is decoded before Calayer is submitted to the GPU. This step takes place in the main thread and is unavoidable. If you want to circumvent this mechanism, it is common practice to draw the picture into cgbitmapcontext in the background thread, and then create the image directly from the Bitmap. Now the common network Picture library has this function.

68, the image drawing usually refers to the method that starts with the CG to draw the image to the canvas, then creates the picture from the canvas and displays such a process. The most common place is [UIView DrawRect:] inside. Since the Coregraphic method is usually thread-safe, the drawing of the image can be easily placed in a background thread. The process of a simple asynchronous drawing is generally as follows (the reality is much more complicated than this, but the principle is basically the same):

-(void) display {

Dispatch_async (Backgroundqueue, ^{

Cgcontextref CTX = cgbitmapcontextcreate (...);

Draw in context ...

Cgimageref img = cgbitmapcontextcreateimage (CTX);

Cfrelease (CTX);

Dispatch_async (Mainqueue, ^{

Layer.contents = img;

});

});

}

69, minimize the number of images in a short period of time to display, as many pictures as possible to become a picture to display. When the picture is too large to exceed the maximum texture size of the GPU, the picture needs to be pre-preprocessed by the CPU, which brings additional resource consumption to both the CPU and the GPU. At present, the IPhone 4S or more models, the maximum texture size is 4096x4096, more detailed information can be seen here: iosres.com. Therefore, try not to let the size of the picture and view exceed this value.

70. Applications should minimize the number and level of views and mark the opaque attribute in an opaque view to avoid useless Alpha channel compositing. Of course, this can also be used in the above method, a number of views pre-rendered as a picture to display.

71, Calayer border, fillet, shadow, mask, Casharplayer vector graphics display, usually trigger off-screen rendering (offscreen rendering), while off-screen rendering usually occurs in the GPU. When a large number of fillet calayer appear in a list view, and a quick swipe, you can observe that the GPU resources are already full, and CPU resource consumption is low. The interface still slides normally, but the average number of frames drops to a very low point. To avoid this, you can try to turn on the Calayer.shouldrasterize property, but this will pass the original off-screen rendering to the CPU. For some occasions where rounded corners are required, it is also possible to simulate the same visual effects by covering the original view with a picture of the rounded corners already drawn. The most thorough solution is to draw the graphic you want to display in a background thread as a picture, avoiding the use of attributes such as fillets, shadows, masks, and so on.

72, for the usual TableView, it is very important to calculate the layout result in advance in the background is a performance optimization point. To achieve maximum performance, you may need to sacrifice some development speed, do not use techniques such as AutoLayout, and less use text controls such as UILabel.

73, in order to avoid off-screen rendering, you should try to avoid using layer of border, corner, shadow, mask and other techniques, and try to pre-draw the corresponding content in the background thread. When the avatar is downloaded, I will pre-render the avatar as a circle in the background thread and save it to a imagecache.

74, "Premature optimization is the root of all evils", when the demand is undecided, performance problems are not obvious, there is no need to try to optimize, and to try to achieve the correct function. When it comes to performance optimization, it's also best to follow the process of modifying code, profile, and so on, to prioritize where to optimize. If you need a clear FPS indicator, you can try the kmcgeigercounter. For CPU lag, it can be detected by the built-in Cadisplaylink, and it uses a 1x1 skview to monitor the lag caused by the GPU. There are two minor problems with this project: Skview can monitor the lag of the GPU, but the introduction of Skview itself will bring additional resource consumption to CPU/GPU, which has some compatibility issues under IOS 9 and needs to be adjusted slightly.

I wrote a simple FPS indicator myself: Fpslabel only has dozens of lines of code and only uses Cadisplaylink to monitor CPU lag. It's not as good as the tools above, but it's not too much of a problem for everyday use.

75. Opaque views can greatly increase the speed of rendering. Therefore, if it is not necessary, you can set the Opaque property of the table cell and its child views to Yes (the default value).

The exceptions include the background color, which should have an alpha value of 1 (for example, do not use Clearcolor), an image should have an alpha value of 1, or be opaque when drawing.

76. Do not create unnecessary table cells repeatedly.

As I said earlier, UITableView only needs a screen of UITableViewCell objects. So when the cell is not visible, you can cache it and continue to use it when you need it. When the cell is reused, the content drawn inside it is not automatically cleared, so you may need to call the Setneedsdisplayinrect: or Setneedsdisplay method.

77. Reducing the number of views, using a custom view, rather than a predefined view, is significantly faster. The best solution, of course, is to inherit UITableViewCell and draw it on its own drawrect:

-(void) DrawRect: (cgrect) Rect {

if (image) {

[Image Drawatpoint:imagepoint];

Self.image =nil;

} else {

[PlaceHolder Drawatpoint:imagepoint];

}

[Text Drawinrect:textrect Withfont:font linebreakmode:uilinebreakmodetailtruncation];

}

However, you will find that the cell becomes blue when the row is selected, and the contents are blocked. The simplest way is to set the cell's Selectionstyle property to Uitableviewcellselectionstylenone so it won't be highlighted. You can also create a calayer, draw the content onto a layer, and then call Addsublayer: method on the cell's contentview.layer. In this example, the layer does not significantly affect performance, but if the layer is transparent, or has rounded corners, deformations and other effects, it will affect the drawing speed. Workaround refer to the pre-rendered image later.

78, do not do superfluous drawing work.

When implementing DrawRect:, its rect parameter is the area that needs to be drawn, which is not required to be drawn outside this area. In the example above, you can use Cgrectintersectsrect, cgrectintersection, or cgrectcontainsrect to determine if you need to draw an image and text, and then call the drawing method.

79, Insertrowsatindexpaths:withrowanimation: Method, insert a new line needs to be executed in the main thread, and insert a lot of lines at a time (for example, 50 lines), the main thread will be blocked by the president. and replaced by the Reloaddata method, the instant processing is done.

80, try not to call ' Cellforrowatindexpath '. Calling Cellforrowatindexpath causes the cell cache to become stale

81. Cache as many things as possible, including row heights

82, the cache is unlikely to change but need to read something frequently. Response, picture, calculation results of the remote server

83. Reuse large overhead objects. For objects that are slow to initialize, the object is persisted by adding a property, guaranteed to be initialized only once, and reused multiple times. such as Nsdataformatter.

84, method pointer cache. If a method is used in a loop with very many cycles, the IMP is called directly in the loop body by using Methodforselector to obtain the imp of the method before entering the loop.

85, decode the picture data. After you set the size of the image in a child thread, the scaled image is used in ImageView. Reason: Because UIImage's Imagewithdata function is to extract data into the ARGB image each time the drawing, so in each drawing, there will be an decompression operation, UIImage initialization is simply to load the image into memory, The actual decoding and resampling is performed only when the image needs to be displayed:

Picture resampling, in a child thread

Cgsize itemsize = cgsizemake (width, height);//The actual size to be scaled

Uigraphicsbeginimagecontext (itemsize);

CGRect imagerect = CGRectMake (0.0, 0.0, itemsize.width, itemsize.height);

[Image Drawinrect:imagerect];

UIImage newimage = Uigraphicsgetimagefromcurrentimagecontext (); resampled picture

Uigraphicsendimagecontext ();

86, the use of rich text label cost is very expensive

It's too expensive to use rich text tags. Avoid using this as much as you can. Ask yourself if you really need this. If so, do the caching as much as possible.

87. Do not use xib too much (use storyboard if you can)

Be careful if you want to use Xib. When you load a xib, the entire content will be loaded into memory (images, hidden views). But this doesn't happen in storyboard. He only instantiates what is currently being used.

88. Use Coregraphics and write your UI code in a view's DrawRect method.

89, can identify tableview prohibit or slow down the end of the time to load the picture asynchronously

-(void) scrollviewdidenddragging: (Uiscrollview *) ScrollView willdecelerate: (BOOL) decelerate

-(void) scrollviewdidenddecelerating: (Uiscrollview *) ScrollView

The following methods are used to perform an asynchronous load operation

Gets the object of the visible part

Nsarray *visiblepaths = [Self.tableview indexpathsforvisiblerows];

For (Nsindexpath *indexpath in visiblepaths)

{

Gets the object inside of the DataSource, and determines that loading is done without having to load asynchronously again

<code>

}

Also restricts the cell drawing.

-(UITableViewCell *) TableView: (UITableView *) TableView Cellforrowatindexpath: (Nsindexpath *) Indexpath

if (self.tableView.dragging = = no && self.tableView.decelerating = = no)

{

Start loading pictures asynchronously

<code>

}

If TableView starts to load the picture asynchronously when it stops sliding

90, in the case of memory tension release all asynchronous thread, to ensure that your app will not be forced to shut down the system

-(void) didreceivememorywarning{

Release the thread that loads the picture asynchronously and all the picture resource objects

<code>

}

Do not forget to manually set all the proxies used to nil.

91, as much as possible to draw the code (many people want to spit groove, my cell style many can not be done with pictures, Sao years, you are wrong, the app's UI elements are a lot of pictures combined out)

92, as little as possible to change the UI control of the frame, if the long text of the Uitextview, or you use high-end coretext, when you change frame, will call Layoutsubviews, this is undoubtedly, you do not need to use coretext redraw it? (Solution: I guess you can use a multi-style UI control to meet your diverse business presentation)

93, less use Reloaddata method, but with the Insert Reloadrow method will also recall the method to calculate the cell height, but here is a bit different, just refresh the visible cells refresh, not the entire TableView cell, But it's a bit of a resource drain.

94, easy to ignore the stringWithFormat:stringWithFormat: Operation will also cause the cost can not be ignored. we can use C Style the way to construct our string! It turns out that this can reduce the amount of overhead, and if you have a lot of stringwithformat in your Customcell method : The effect of performance improvement should be obvious. The following code can be used to convert the C and OBJC strings:

Char cstring[255]; This is going to be the size of the situation

sprintf (String, "click:%d", numberofclick);

NSString *objcstring = [[Nnstring alloc] initwithutf8string:cstring];

95, GIF pictures are compared to eat resources, full screen Cell each has a Gif in motion, think on the acid cool. The first is to use Flanimatedimage to add a GIF View to each Cell. With a few animations will be able to make the same effect, decisively changed the solution, after the change is simply smooth.

96, do not forget scrollviewdidscroll. just scroll a bit, Scrollviewdidscroll: N Times is called. Decisive transfer code, think of the next lost to the ScrollViewWillEndDragging:withVelocity:targetContentOffset: Agent method to go, the use of this targetcontentoffset can be solved. As with Cellforrowatindexpath: methods, the frequency of this method call is also very high, and it is not a necessity to put time-consuming code in it.

97, picture loading there is a small trick is when the picture in the asynchronous loading, the image of the Cell scrolled out of the screen, then immediately the download of the operation to Cancel off, to avoid unnecessary resource consumption.

98. Do not stretch the picture in the Cell

99, if the Cell has a shadow, try to use the picture instead of manipulating the layer to draw.

100, add a variable such as userdragging, in the willbegindragging set to YES, set to NO in didenddragging. So Tableview:cellforrowatindexpath: in the method, The logic of whether the load picture is:

if (!self.userdragging && tableview.decelerating) {

Cell.imageView.image = nil;

} else {

Code for loading image from network or disk

}

Tableview optimization Overview (from the network)

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.