window phone7开发中的性能、内存使用监控方法

原文地址:http://www.cnblogs.com/yoainet/archive/2012/03/01/2375775.html

window phone7对手机硬件有对应要求,其中一项是手机内存不低于256M,这对运行在手机上的应用也带来了限制,那就是资源分配;所以在开发过程中关注自己应用的资源使用情况是非常有必要的,如果应用占用资源过多,在提交marketplace时,提交审核过程可能会被拒绝,那么就这里就分享下,内存实时监控的方法了。并且首页加载内存应小于90M。

原理是使用 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
    {


    }
    /// <summary>
    /// Helper class for showing current memory usage
    /// </summary>
    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<MemoryCheckpoint> recentCheckpoints;


        static bool alreadyFailedPeak = false; // to avoid endless Asserts


        /// <summary>
        /// Starts the memory diagnostic timer and shows the counter
        /// </summary>
        /// <param name="timespan">The timespan between counter updates</param>
        /// <param name="forceGc">Whether or not to force a GC before collecting memory stats</param>
        [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<MemoryCheckpoint>();


            StartTimer(timespan);
            ShowPopup();
        }


        /// <summary>
        /// Stops the timer and hides the counter
        /// </summary>
        [Conditional("DEBUG")]
        public static void Stop()
        {
            HidePopup();
            StopTimer();
            recentCheckpoints = null;
        }


        /// <summary>
        /// Add a checkpoint to the system to help diagnose failures. Ignored in retail mode
        /// </summary>
        /// <param name="text">Text to describe the most recent thing that happened</param>
        [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()));
        }


        /// <summary>
        /// Recent checkpoints stored by the app; will always be empty in retail mode
        /// </summary>
        public static IEnumerable<MemoryCheckpoint> RecentCheckpoints
        {
            get
            {
                if (recentCheckpoints == null) yield break;


                foreach (MemoryCheckpoint checkpoint in recentCheckpoints) yield return checkpoint;
            }
        }


        /// <summary>
        /// Gets the current memory usage, in bytes. Returns zero in non-debug mode
        /// </summary>
        /// <returns>Current usage</returns>
        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
        }


        /// <summary>
        /// Gets the peak memory usage, in bytes. Returns zero in non-debug mode
        /// </summary>
        /// <returns>Peak memory usage</returns>
        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;
        }
    }


    /// <summary>
    /// Holds checkpoint information for diagnosing memory usage
    /// </summary>
    public class MemoryCheckpoint
    {
        /// <summary>
        /// Creates a new instance
        /// </summary>
        /// <param name="text">Text for the checkpoint</param>
        /// <param name="memoryUsage">Memory usage at the time of the checkpoint</param>
        internal MemoryCheckpoint(string text, long memoryUsage)
        {
            Text = text;
            MemoryUsage = memoryUsage;
        }


        /// <summary>
        /// The text associated with this checkpoint
        /// </summary>
        public string Text { get; private set; }


        /// <summary>
        /// The memory usage at the time of the checkpoint
        /// </summary>
        public long MemoryUsage { get; private set; }
    }
}

然要想使用还得在app.xaml.cs构造函数里启用监控

/// <summary>
        /// Constructor for the Application object.
        /// </summary>
        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);

            }


      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值