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
{
}
/// /// 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 Queue recentCheckpoints;
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 IEnumerable RecentCheckpoints
{
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; }
}
} 當然要想使用還得在app.xaml.cs構造函數里啟用監控 ////// 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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!