TÌM HIỂU VỀ CÁCH THỨC NÂNG CAO PERFORMANCE CỦA APP TRÊN WINDOWS STORE VỚI NGÔN NGỮ LÀ C# XAML.
TÌM HIỂU VỀ CÁCH THỨC NÂNG CAO PERFORMANCE CỦA APP TRÊN WINDOWS STORE VỚI NGÔN NGỮ LÀ C# XAML. Đầu tiên, tôi xin giới thiệu các công cụ và cách sử dụng các công cụ có sẵn trong visual studio thường được sử dụng để phân tích về hiệu quả hoạt động (performance), sử dụng bộ nhớ của app. Các công ...
TÌM HIỂU VỀ CÁCH THỨC NÂNG CAO PERFORMANCE CỦA APP TRÊN WINDOWS STORE VỚI NGÔN NGỮ LÀ C# XAML.
Đầu tiên, tôi xin giới thiệu các công cụ và cách sử dụng các công cụ có sẵn trong visual studio thường được sử dụng để phân tích về hiệu quả hoạt động (performance), sử dụng bộ nhớ của app. Các công cụ trên sẽ giúp bạn đánh giá được những phần quan trọng, tốn nhiều bộ nhớ và thời gian xử lý của app để tập trung tìm giải pháp và giúp chương trình hoạt động gọn gàng hơn.
1. Công cụ hỗ trợ phân tích performance.
Với bộ cài visual studio express, microsoft hỗ trợ 3 công cụ cơ bản để phân tích performance của app viết bằng ngôn ngữ C# xaml sau:
-
CPU Sampling
-
Energy Consumption
-
XAML UI Responsiveness
2. Thu thập dữ liệu phân tích
- Trên thanh toolbar, chọn Debug-> Performance and Diagnosis
Hình ảnh nội tuyến 1
-
Trong cửa sổ Performance and Diagnosis, bạn có thể chọn một trong các công cụ để tiên hành thu thập dữ liệu.
-
Click vào Start button để bắt đầu thu thập thông tin.
-
Lúc này application của bạn sẽ khởi động, việc cần làm lúc này là bạn chạy ứng dụng theo follow mà bạn muốn phân tích. Khi đó công cụ sẽ thu thập thông tin các functions app chạy qua.
Để phân tích performance công cụ cần thiết nhất là XAML UI Responsiveness
3. Performance report.
Khi bạn ngừng thu thập dữ liệu hoặc ngừng chạy app, dữ liệu sẽ được phân tích ngay lập tức và sau đó công cụ sẽ xuất ra báo cáo về performance cho bạn. Hiệu suất và Diagnostics trang dữ liệu
-
Các mốc thời gian cho thấy chiều dài follow bạn chạy ứng dụng, các sự kiện xảy ra.
-
Bạn có thể giới hạn báo cáo cho một phần thời gian bằng cách kéo các thanh màu xanh và chọn 1 vùng của timeline để phân tích.
-
Biểu đồ hiển thị tổng thể.
-
Biểu đồ chi tiết cho các thread con được sử dụng trong chương trình.
-
Nếu bạn sử dụng nhiều công cụ cùng thu thập dữ liệu thì sẽ hiện thị theo tab, như ví dụ trên là được sử dụng bởi 2 công cụ CPU Usage và XAML UI Responsiveness.
-
Chi tiết về các thành phần được thu thập, như ví dụ trên nhìn vào ta sẽ có thông tin là: element TextBox1 sử dụng 905 ms để binding data và display trên màn hình. .
Ở biểu đồ tổng quát, nó sẽ cung cấp cho bạn cái nhìn chung nhất về tình hình của app, ti lệ thời gian dành cho các sử lý, màu xanh da trời là khu vực dành cho việc parsing data, da cam là thời gian sử lý generate UI, load UI, màu xanh lơ thể hiện thời gian xử lý code behind và màu xám là thời gian xử lý các thẻ xaml.
Qua ví dụ minh họa trên tôi thấy app hoạt động đang không được tốt cho lắm, tiến trình thể hiện trên UI thread nhiều thời điểm đạt xấp xỉ 100%, kết hợp với thông tin chi tiết ta có thể thấy phần liên quan TextBox1 đang bị delay. Reference site: http://msdn.microsoft.com/en-us/library/ie/dn255009(v=vs.85).aspx
4. Cải thiện performance trên code C#
4.1 Sử dụng mảng (array) và tập hợp (collection):
Sử dụng mảng array sẽ giúp truy xuất nhanh hơn nhưng không linh hoạt bằng tập hợp. Tập hợp giống như một danh sách liên kết – linkedlist có khả năng cấp phát động, cung cấp thao tác thêm, xóa các vị trí mà mảng không hỗ trợ. Trong một số trường hợp không cần xử dụng chức năng này của tập hợp thì ta nên sử dụng mảng.
4.2 Sự khác biệt khi sử dụng class và structure
Đối với kiểu dữ liệu đơn giản và không cần tham chiếu, ta nên sử dụng structure thay cho class sẽ giúp giảm chi phí tài nguyên tiêu hao cho chương trình vì structure có ít tính năng hơn class.
4.3 Lưu trữ biến bằng property và lưu trữ trực tiếp
Lưu trữ bằng biến property sẽ lâu hơn khoảng 20 lần sơ với dùng biến trực tiếp, tuy nhiên dùng biến property sẽ tăng khả năng kiểm xoát khi truy xuất và lưu trữ biến.
4.4 So sanh giữa dùng StringBuilder và toán tử + để nối chuỗi string
Khi sử dụng vòng lặp for và nối chuối thì dùng StringBuilder sẽ nhanh hơn dùng toán tử + do dùng toán tử cộng sẽ tạo ra đối tượng mới.
Ngoài ra trong khi code việc hạn chế sử dụng try/ catch và ép kiểu dữ liệu cũng sẽ góp phần làm tăng tốc độ chương trình ở code behind.
Source code sample: https://onedrive.live.com/redir?resid=AAAFFCDAE249948A!110
5. Cải thiện performance trên code XAML.
5.1 Sử dụng ít nhất số lượng Element trên code XAML.
Tránh việc sử dụng các elelement không cần thiết, ví dụ: để set background của grid thì nên sử dụng property Backgound thay vì sử dụng control Rectangle bên trong Grid đó.
<Grid> <!-- BAD CODE DO NOT USE.--> <Rectangle Fill="Black"/> <!-- BAD CODE DO NOT USE.--> </Grid> <!-- BAD CODE DO NOT USE.--> thay thế bởi <Grid Background="Black" />.
5.2 Sử dụng Resource key để định nghĩa Color, tránh sử dụng cùng một màu trên nhiều control như sau:
<!-- BAD CODE DO NOT USE.--> <Page ...> <!-- BAD CODE DO NOT USE.--> <StackPanel> <!-- BAD CODE DO NOT USE.--> <TextBox> <!-- BAD CODE DO NOT USE.--> <TextBox.Foreground> <!-- BAD CODE DO NOT USE.--> <SolidColorBrush Color="#FF3F42CC"/> <!-- BAD CODE DO NOT USE.--> </TextBox.Foreground> <!-- BAD CODE DO NOT USE.--> </TextBox> <!-- BAD CODE DO NOT USE.--> <Button Content="Submit"> <!-- BAD CODE DO NOT USE.--> <Button.Foreground> <!-- BAD CODE DO NOT USE.--> <SolidColorBrush Color="#FF3F42CC"/> <!-- BAD CODE DO NOT USE.--> </Button.Foreground> <!-- BAD CODE DO NOT USE.--> </Button> <!-- BAD CODE DO NOT USE.--> </StackPanel> <!-- BAD CODE DO NOT USE.--> </Page> <!-- BAD CODE DO NOT USE.-->
thay vì thế nên sử dụng Resource để định nghĩa
<Page ...> <Page.Resources> <SolidColorBrush x:Key="TextColor" Color="#FF3F42CC"/> </Page.Resources> <StackPanel> <TextBox Foreground="{StaticResource TextColor}" /> <Button Content="Submit" Foreground="{StaticResource TextColor}" /> </StackPanel> </Page>
5.3 Sử dụng CacheMode nếu sử dụng nhiều Shape có hình dạng giống nhau.
<Canvas Background="White"> <Ellipse Height="40" Width="40" Fill="Blue"/> <Ellipse Canvas.Left="21" Height="40" Width="40" Fill="Blue"/> <Ellipse Canvas.Top="13" Canvas.Left="10" Height="40" Width="40" Fill="Blue"/> </Canvas> nên sử dụng CacheMode để tăng tốc độ vẽ của control <Canvas Background="White" CacheMode="BitmapCache"> <Ellipse Height="40" Width="40" Fill="Blue"/> <Ellipse Canvas.Left="21" Height="40" Width="40" Fill="Blue"/> <Ellipse Canvas.Top="13" Canvas.Left="10" Height="40" Width="40" Fill="Blue"/> </Canvas>
5.4 Load UI của GridView và ListView.
Với mỗi item trong GridView và ListView nó có thể chứa rất nhiều các control khác và có rất nhiều trạng thái khác nhau như khi click vào thì sẽ hiện thị khác, khi chuột đi qua sẽ hiện thị một kiểu khác nữa v.v.. Lúc này chúng ta nên sử dụng GridViewItemPresenter để hiển thị.
<GridView> <!-- ... --> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="GridViewItem"> <GridViewItemPresenter SelectionCheckMarkVisualEnabled="False" SelectedBackground="Orange"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </GridView.ItemContainerStyle> </GridView>
5.5 Tránh freezing UI thread
Với những hành động có thể tiến hành song song được khi user click vào button như, ta nên sử dụng async method để tránh app bị treo vì chờ sử lý từ code behind.
public class Example { // ... private async void NextMove_Click(object sender, RoutedEventArgs e) { await Task.Run(() => ComputeNextMove()); // Update the UI with results } private async Task ComputeNextMove() { // ... } // ... }
Hoặc với những trường hợp không sử dụng async được thì bạn nên hiển thị progress ring để thông báo cho người dùng ứng dụng đang thực thi và ngăn người dùng không thao tác tiếp với app được.
5.6 Hiện thị image
Nên sử dụng DecodePixelWidth va DecodePixelHeight thay cho Width va Height sẽ giúp Image được load lên nhanh hơn.
<Image Source="ms-appx:///Assets/highresCar.jpg" Width="300" Height="200"/> <!-- BAD CODE DO NOT USE.--> thay bằng: <Image> <Image.Source> <BitmapImage UriSource="ms-appx:///Assets/highresCar.jpg" DecodePixelWidth="300" DecodePixelHeight="200"/> </Image.Source> </Image>