C#& Unity:在移动设备上更改显示时间并获得良好性能

时间:2018-04-23 06:31:51

标签: c# android unity3d mobile

嘿伙计们,所以我做了这个功能,每个帧调用。 - 您认为这是保存性能的好方法还是有更好的方法?

    private void GetCurrentTime()
{
    m_TimeNow = System.Convert.ToString(System.DateTime.Now);

    //If the previous time is not equals to the current time (without seconds = every minute)
    if (m_PreTime != m_TimeNow.Remove(14))
    {                                                   //Change the Time displayed on the screen:
        m_PreTime = m_TimeNow.Remove(14);               //1. Copy current Time
        m_Times = m_TimeNow.Split(' ');                 //2. Split to following parts
        m_Time = m_Times[1].Remove(4);                  //3. Cutout seconds

        m_Text_Time.text = m_Time + " " + m_Times[2];   //4. And change UI-Text: Time + AM/PM
    }
}

此功能在每个帧中调用,并且将在移动设备上运行。

谢谢!

1 个答案:

答案 0 :(得分:0)

我可能会看到您的实施方面有所改进。以下是我根据自己的经验告诉你的事情。

简单回答一下,这是我写你的函数的方法:

// 
// Version 2
// 
class TimerExample_V2 {
    private DateTime    _TimeNow = System.DateTime.Now;
    private DateTime    _PreTime = System.DateTime.Now;
    private string      _format = "t";
    private string      _cultureName = "en-US";

    public TimerExample_V2() {
        CultureInfo culture = new CultureInfo(_cultureName);
        CultureInfo.CurrentCulture = culture;
    }

    public void UpdateCurrentTimeUI() {
        _TimeNow = System.DateTime.Now;

        if(_PreTime.Minute != _TimeNow.Minute) {
            // Note: this case appear only once per minute.
            _PreTime = System.DateTime.Now;
            string newText = _TimeNow.ToString(_format);
            //m_Text_Time.text = newText; // Update unity display
            // I omit this display unity. (Same cost in both case)
        }
    }

现在有更长的答案解释:

  • 字符串(性能): 字符串通常很昂贵,特别是在处理str处理和比较时。例如,'String.Remove(int)'创建一个新字符串,可以调用几个昂贵的方法,如malloc等(在场景后面)。据我所知,您将所有日期保留为字符串,但只能使用原始格式DateTime。更好的方法是将数据保持为“DateTime”格式,并将其转换为仅供最终用户使用的字符串。 (例如,更新Unity显示)。最好比较两个int(例如:DateTime.ElapsedMilliseconds)而不是字符串(例如:m_PreTime!= m_TimeNow.Remove(14))

  • 日期格式(灵活性): 在处理不同的日期格式时,您会遇到几个问题。您的实现需要“HH:mm AM / PM”格式,但用户可能有可能更改格式(例如24小时)。使用C#为您提供的暗魔力。例如,使用CultureInfo或已经实现的“DateTime.ToString(format)”。 (我刚刚了解了'CultureInfo'。可能还有其他方法。但作为一般规则,看看语言是否已经具备了你需要的功能。

  • 功能名称: 这是一个小东西,但尝试使用它所说的功能。在您的情况下,从'GetCurrentTime',我们期望返回值。此函数实际更新显示并返回void。像'UpdateTimeDisplay'这样的东西可能更好。

  • 重复通话: 第二件小事:你有2次调用m_timeNow.Remove(14)。您可以创建一个新字符串(从此函数)并在两个位置使用此新字符串。

实验(测量和验证)

无论如何,在处理性能时,您必须测量,对代码进行基准测试。 (作为一个例子,我首先为你的GetCurrentTime做了一个实现,并意识到它实际上并没有更好。)以下是我创建的一些经验,以向您展示一些测量。我不是C#萨满专家,也不是性能向导专家,但我希望我的例子很清楚。我在笔记本电脑上运行实验:( Intel i5-3320M CPU @ 2.60GHz)。

我有两个函数实现。我运行每个函数10 000次并打印每个函数的执行时间。 (我省略了更新统一显示的调用,两种情况都是一样的)。我的测量显示你的实现花费了45毫秒,另一个花了23毫秒。

第二种实现听起来更好。但是,不要忘记我拨打了10 000次这些功能。在实践中,使用60fps,您每秒呼叫更新60次。在我的笔记本电脑上,60次迭代花费了0毫秒。

还有另一个要点:

m_PreTime   = m_TimeNow.Remove(14);
m_Times     = m_TimeNow.Split(' ');
m_Time      = m_Times[1].Remove(4);

自从处理字符串创建以来,这些函数很慢。但是,每分钟只调用一次。作为一个fack,我测量了一下,我的实现,当切换分钟时,使用与你的相同的毫秒数。我可能没有通过我的测量或其他什么,但也许,每一分钟,我的功能需要花费你的时间。在所有其他情况下,它“更快”。我可以用引号来总结这一点:

  

“首先解决最常见的情况,不是最通用的”

(据我记得,这是关于优化的讨论:https://www.youtube.com/watch?v=nXaxk27zwlk。好的谈话顺便说一下)

实验(源代码)

所以这是我可怕的实验的完整代码:

using System;
using System.Globalization;
using System.Diagnostics;

// Instructions to compile (With mono)
// csc Program.cs
// mono Program.exe

class Program {
    static void Main(string[] args) {
        TimerExample_V1 timer_v1 = new TimerExample_V1();
        TimerExample_V2 timer_v2 = new TimerExample_V2();

        Stopwatch profiler;
        int nbBenchLoops = 10000; // 10 000 times
        float t1;
        float t2;

        // Profil version 1
        profiler = Stopwatch.StartNew();
        for(int k = 0; k < nbBenchLoops; ++k) {
            timer_v1.UpdateCurrentTimeUI();
        }
        t1 = profiler.ElapsedMilliseconds;


        // Profil version 2
        profiler = Stopwatch.StartNew();
        for(int k = 0; k < nbBenchLoops; ++k) {
            timer_v2.UpdateCurrentTimeUI();
        }
        t2 = profiler.ElapsedMilliseconds;


        // Print mesured times
        Console.WriteLine("[SCOPE_PROFILER] [Version 1]: {0} ms", t1);
        Console.WriteLine("[SCOPE_PROFILER] [Version 2]: {0} ms", t2);
    }
}

//
// Version 1
//
class TimerExample_V1 {
    private string      m_TimeNow = System.Convert.ToString(System.DateTime.Now);
    private string      m_PreTime = System.Convert.ToString(System.DateTime.Now);
    private string[]    m_Times;
    private string      m_Time;

    public void UpdateCurrentTimeUI() {
        m_TimeNow = System.Convert.ToString(System.DateTime.Now);

        if (m_PreTime != m_TimeNow.Remove(14)) {
            // Note: this case appear only once per minute.
            m_PreTime   = m_TimeNow.Remove(14);
            m_Times     = m_TimeNow.Split(' ');
            m_Time      = m_Times[1].Remove(4);

            string newText = m_Time + " " + m_Times[2];
            //m_Text_Time.text = newText; // Update unity display
            // I omit this display unity. (Same cost in both case)
        }

    }
}


// 
// Version 2
// 
class TimerExample_V2 {
    private DateTime    _TimeNow = System.DateTime.Now;
    private DateTime    _PreTime = System.DateTime.Now;
    private string      _format = "t";
    private string      _cultureName = "en-US";

    public TimerExample_V2() {
        CultureInfo culture = new CultureInfo(_cultureName);
        CultureInfo.CurrentCulture = culture;
    }

    public void UpdateCurrentTimeUI() {
        _TimeNow = System.DateTime.Now;

        if(_PreTime.Minute != _TimeNow.Minute) {
            // Note: this case appear only once per minute.
            _PreTime = System.DateTime.Now;
            string newText = _TimeNow.ToString(_format);
            //m_Text_Time.text = newText; // Update unity display
            // I omit this display unity. (Same cost in both case)
        }
    }
}

有关DateTime.ToString和CultureInfo的更多信息,请查看文档:

希望这会有所帮助:)