欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-05-16 09:50:43
window phone7对手机硬件有对应要求,其中一项是手机内存不低于256m,这对运行在手机上的应用也带来了限制,那就是资源分配;所以在开发过程中关注自己应用的资源使用情况是非常有必要的,如果应...

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

      }

 
 
运行效果:

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

实例下载:


摘自 johnny默默