zoukankan      html  css  js  c++  java
  • window 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
    {

    }
    /// <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);
    }

    }

    运行效果:

    实例下载

  • 相关阅读:
    【Codecs系列】之NVIDIA Jetson TX1简介
    【Life系列】之工作与生活的关系《赢在下班后》
    【Bugs系列】之could not find or load the Qt platform plugin windows解决方案
    【Books系列】之第一本书:大冰《好吗好的》读书笔记和读后感
    【Qt系列】之Qt之打包发布
    【Life系列】之我在底层的生活
    【Life系列】之关于工作和生活的思考与反思
    【Tools系列】之WORD转成PDF并生成书签
    【Tools系列】之Excel冻结窗格
    【Script系列】之CMake学习总结
  • 原文地址:https://www.cnblogs.com/yoainet/p/2375775.html
Copyright © 2011-2022 走看看