Windows Phone7 開發中的性能、內存使用監控方法
window phone7對手機硬件有對應要求,其中一項是手機內存不低于256M,這對運行在手機上的應用也帶來了限制,那就是資源分配;所以在開發過程中關注自己 應用的資源使用情況是非常有必要的,如果應用占用資源過多,在提交marketplace時,提交審核過程可能會被拒絕,那么就這里就分享下,內存實時監 控的方法了。
原理是使用 DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage")獲取應用使用 的內存,然后啟用一個timer定時查詢并顯示到ui上,為了不影響應用在正常情況下的使用,只有在debug時將內存使用情況顯示出來,這樣可以看到在 各個頁面上運行時內存使用情況,可以分析內存消耗在具體哪個地方;
代碼如下:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Controls.Primitives; using System.Windows.Threading; using Microsoft.Phone.Info; using System.Diagnostics; using System.Collections.Generic; namespace ScrollViewerStyle { public class MemoryDiagnostics { } ///當然要想使用還得在app.xaml.cs構造函數里啟用監控/// Helper class for showing current memory usage /// public static class MemoryDiagnosticsHelper { static Popup popup; static TextBlock currentMemoryKB; static TextBlock currentMemoryMB; static TextBlock peakMemoryBlock; static DispatcherTimer timer; static bool forceGc; const long MAX_MEMORY = 90 * 1024 * 1024; // 90MB, per marketplace static int lastSafetyBand = -1; // to avoid needless changes of colour const long MAX_CHECKPOINTS = 10; // adjust as needed static QueuerecentCheckpoints; static bool alreadyFailedPeak = false; // to avoid endless Asserts /// /// Starts the memory diagnostic timer and shows the counter /// /// The timespan between counter updates /// Whether or not to force a GC before collecting memory stats [Conditional("DEBUG")] public static void Start(TimeSpan timespan, bool forceGc) { if (timer != null) throw new InvalidOperationException("Diagnostics already running"); MemoryDiagnosticsHelper.forceGc = forceGc; recentCheckpoints = new Queue(); StartTimer(timespan); ShowPopup(); } /// /// Stops the timer and hides the counter /// [Conditional("DEBUG")] public static void Stop() { HidePopup(); StopTimer(); recentCheckpoints = null; } ////// Add a checkpoint to the system to help diagnose failures. Ignored in retail mode /// /// Text to describe the most recent thing that happened [Conditional("DEBUG")] public static void Checkpoint(string text) { if (recentCheckpoints == null) return; if (recentCheckpoints.Count >= MAX_CHECKPOINTS - 1) recentCheckpoints.Dequeue(); recentCheckpoints.Enqueue(new MemoryCheckpoint(text, GetCurrentMemoryUsage())); } ////// Recent checkpoints stored by the app; will always be empty in retail mode /// public static IEnumerableRecentCheckpoints { get { if (recentCheckpoints == null) yield break; foreach (MemoryCheckpoint checkpoint in recentCheckpoints) yield return checkpoint; } } /// /// Gets the current memory usage, in bytes. Returns zero in non-debug mode /// ///Current usage public static long GetCurrentMemoryUsage() { #if DEBUG // don't use DeviceExtendedProperties for release builds (requires a capability) return (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage"); #else return 0; #endif } ////// Gets the peak memory usage, in bytes. Returns zero in non-debug mode /// ///Peak memory usage public static long GetPeakMemoryUsage() { #if DEBUG // don't use DeviceExtendedProperties for release builds (requires a capability) return (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage"); #else return 0; #endif } private static void ShowPopup() { popup = new Popup(); double fontSize = (double)Application.Current.Resources["PhoneFontSizeSmall"] - 2; Brush foreground = (Brush)Application.Current.Resources["PhoneForegroundBrush"]; StackPanel sp = new StackPanel { Orientation = Orientation.Horizontal, Background = (Brush)Application.Current.Resources["PhoneSemitransparentBrush"] }; currentMemoryKB = new TextBlock { Text = "---", FontSize = fontSize, Foreground = foreground }; peakMemoryBlock = new TextBlock { Text = "", FontSize = fontSize, Foreground = foreground, Margin = new Thickness(5, 0, 0, 0) }; sp.Children.Add(currentMemoryKB); //sp.Children.Add(new TextBlock { Text = " kb", FontSize = fontSize, Foreground = foreground }); sp.Children.Add(peakMemoryBlock); currentMemoryMB = new TextBlock { Text = "---", FontSize = fontSize, Foreground = foreground }; sp.Children.Add(currentMemoryMB); sp.RenderTransform = new CompositeTransform { Rotation = 90, TranslateX = 480, TranslateY = 480, CenterX = 0, CenterY = 0 }; popup.Child = sp; popup.IsOpen = true; } private static void StartTimer(TimeSpan timespan) { timer = new DispatcherTimer(); timer.Interval = timespan; timer.Tick += new EventHandler(timer_Tick); timer.Start(); } static void timer_Tick(object sender, EventArgs e) { if (forceGc) GC.Collect(); UpdateCurrentMemoryUsage(); UpdatePeakMemoryUsage(); } private static void UpdatePeakMemoryUsage() { if (alreadyFailedPeak) return; long peak = GetPeakMemoryUsage(); if (peak >= MAX_MEMORY) { alreadyFailedPeak = true; Checkpoint("*MEMORY USAGE FAIL*"); peakMemoryBlock.Text = "FAIL!"; peakMemoryBlock.Foreground = new SolidColorBrush(Colors.Red); if (Debugger.IsAttached) Debug.Assert(false, "Peak memory condition violated"); } } private static void UpdateCurrentMemoryUsage() { long mem = GetCurrentMemoryUsage(); currentMemoryKB.Text = string.Format("{0:N}", mem / 1024) + "KB "; currentMemoryMB.Text = string.Format("{0:f}", mem / 1024.00 / 1024.00) + "MB"; int safetyBand = GetSafetyBand(mem); if (safetyBand != lastSafetyBand) { currentMemoryKB.Foreground = GetBrushForSafetyBand(safetyBand); lastSafetyBand = safetyBand; } } private static Brush GetBrushForSafetyBand(int safetyBand) { switch (safetyBand) { case 0: return new SolidColorBrush(Colors.Green); case 1: return new SolidColorBrush(Colors.Orange); default: return new SolidColorBrush(Colors.Red); } } private static int GetSafetyBand(long mem) { double percent = (double)mem / (double)MAX_MEMORY; if (percent <= 0.75) return 0; if (percent <= 0.90) return 1; return 2; } private static void StopTimer() { timer.Stop(); timer = null; } private static void HidePopup() { popup.IsOpen = false; popup = null; } } ////// Holds checkpoint information for diagnosing memory usage /// public class MemoryCheckpoint { ////// Creates a new instance /// /// Text for the checkpoint /// Memory usage at the time of the checkpoint internal MemoryCheckpoint(string text, long memoryUsage) { Text = text; MemoryUsage = memoryUsage; } ////// The text associated with this checkpoint /// public string Text { get; private set; } ////// The memory usage at the time of the checkpoint /// public long MemoryUsage { get; private set; } } }
////// Constructor for the Application object. /// public App() { // Global handler for uncaught exceptions. UnhandledException += Application_UnhandledException; // Standard Silverlight initialization InitializeComponent(); // Phone-specific initialization InitializePhoneApplication(); // Show graphics profiling information while debugging. if (System.Diagnostics.Debugger.IsAttached) { // Display the current frame rate counters. Application.Current.Host.Settings.EnableFrameRateCounter = true; // Show the areas of the app that are being redrawn in each frame. //Application.Current.Host.Settings.EnableRedrawRegions = true; // Enable non-production analysis visualization mode, // which shows areas of a page that are handed off to GPU with a colored overlay. //Application.Current.Host.Settings.EnableCacheVisualization = true; // Disable the application idle detection by setting the UserIdleDetectionMode property of the // application's PhoneApplicationService object to Disabled. // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run // and consume battery power when the user is not using the phone. PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; //啟動性能監控,只在debug時候 MemoryDiagnosticsHelper.Start(TimeSpan.FromMilliseconds(500), true); } }
運行效果:
轉自:http://www.cnblogs.com/yoainet/archive/2012/03/01/2375775.html
本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!