当前位置: 移动技术网 > IT编程>移动开发>WP > window phone7开发中的性能、内存使用监控方法

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

2018年10月05日  | 移动技术网IT编程  | 我要评论

城南大道,黎明的曙光麦词,李亿龙最新消息

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

      }

 
 
运行效果:

 \

实例下载:


摘自 johnny默默
 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网