jjzjj

Unity - 带耗时 begin ... end 的耗时统计的Log - TSLog

Jave.Lin 2024-05-14 原文

CSharp Code

// jave.lin 2023/04/21 带 timespan 的日志 (不帶 log hierarchy 结构要求,即: 不带 stack 要求)

using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class TSLog
{
    // ts == time span
    public class WithTimeSpanLogData
    {
        public int idx;
        public string tag;
        public TimeSpan timeSpan; // (DateTime)start - (DateTime)end

        public string startDesc;
        public string endDesc;
        public DateTime startDateTime;
        public DateTime endDateTime;
        public string classNameStart;
        public int lineStart;
        public string classNameEnd;
        public int lineEnd;

        public static string GetCSVTitle()
        {
            return $"编号, 标记, 耗时, 开始描述, 结束描述, 开始时间, 结束时间, 开始文件, 开始行, 结束文件, 结束行\n";
        }

        public override string ToString()
        {
            return $"{idx}, {tag}, {timeSpan}, {startDesc}, {endDesc}, {startDateTime}, {endDateTime}, {classNameStart}, {lineStart}, {classNameEnd}, {lineEnd}";
        }
    }

    // clog == custom log
    public static void CLog(string content)
    {
        Debug.Log($"[{DateTime.Now}] {content}");
    }

    private static void GetCodeLineNum(out string fileName, out int lineNum)
    {
        System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(0, true);
        System.Diagnostics.StackFrame frame = st.GetFrame(st.FrameCount - 1);
        fileName = frame.GetFileName();
        lineNum = frame.GetFileLineNumber();
    }

    //=== DEMO START ======================

    private static void Test()
    {
        System.Threading.Thread.Sleep(2000);
        CLog("Test Func Testing with date time Log");
    }

    private static void Test2()
    {
        System.Threading.Thread.Sleep(1000);
        CLog("Test2 Func Testing with date time Log");
    }

    [MenuItem("实用工具/测试/测试TSLog并写日志结果")]
    private static void Usage()
    {
        var tslog = new TSLog();

        tslog.Clear();

        tslog.BeginTag("Test", "开始Test函数,并标记");
        Test();
        tslog.EndTag("Test", "结束Test函数,并统计消耗");

        tslog.BeginTag("Test2", "开始Test2函数,并标记");
        Test2();
        tslog.EndTag("Test2", "结束Test2函数,并统计耗时");

        tslog.WriteTagLogs();

        /*

        测试输出:

编号, 标记, 耗时, 开始描述, 结束描述, 开始时间, 结束时间, 开始文件, 开始行, 结束文件, 结束行
0, Test, 00:00:02.0112773, 开始Test函数,并标记, 结束Test函数,并统计消耗, 2023/4/21 15:36:10, 2023/4/21 15:36:12, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 73, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 75
1, Test2, 00:00:01.0104517, 开始Test2函数,并标记, 结束Test2函数,并统计耗时, 2023/4/21 15:36:12, 2023/4/21 15:36:13, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 77, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 79


         * */
    }

    //=== DEMO END ======================

    // WTSL ==> With TimeSpan Log
    private int WTSLDataIDXCounter = 0;

    private List<WithTimeSpanLogData> logTag_List = new List<WithTimeSpanLogData>();

    private Dictionary<string, WithTimeSpanLogData> logTag_Dict = new Dictionary<string, WithTimeSpanLogData>();

    public void Clear()
    {
        WTSLDataIDXCounter = 0;
        logTag_List.Clear();
        logTag_Dict.Clear();
    }

    public void BeginTag(string tag, string description = null)
    {
        tag = tag.Replace(",", "_");
        if (description != null)
            description = description.Replace(",", "_");

        var alreadyBeginTag = logTag_Dict.TryGetValue(tag, out var data);
        var nowDateTime = DateTime.Now;
        if (alreadyBeginTag)
        {
            Debug.LogWarning($"[{nowDateTime}] W BeginTag : {tag}, but alreadyBeginTag at time : {data}");
        }
        else
        {
            GetCodeLineNum(out string fileName, out int lineNum);

            Debug.Log($"[{nowDateTime}] D BeginTag : {tag}");
            logTag_Dict[tag] = new WithTimeSpanLogData
            {
                idx = WTSLDataIDXCounter++,
                tag = tag,
                startDesc = description,
                startDateTime = nowDateTime,
                classNameStart = fileName,
                lineStart = lineNum,
            };
        }
    }

    public void EndTag(string tag, string description = null)
    {
        tag = tag.Replace(",", "_");
        if (description != null)
            description = description.Replace(",", "_");

        var hasBeginTag = logTag_Dict.TryGetValue(tag, out var data);
        var nowDateTime = DateTime.Now;
        if (hasBeginTag)
        {
            var ts = nowDateTime - data.startDateTime;
            Debug.Log($"[{nowDateTime}] D EndTag : {tag}, Timespan : {ts}");
            logTag_Dict.Remove(tag);

            GetCodeLineNum(out string fileName, out int lineNum);

            data.endDesc = description;
            data.endDateTime = nowDateTime;
            data.classNameEnd = fileName;
            data.lineEnd = lineNum;
            data.timeSpan = ts;

            logTag_List.Add(data);
        }
        else
        {
            Debug.LogWarning($"[{nowDateTime}] W EndTag : {tag}, have no Timespan");
        }
    }

    public bool WriteTagLogs()
    {
        var ret = false;
        var error = string.Empty;
        try
        {
            using (var streamWriter = new StreamWriter("BuildingTagLogs.csv", false))
            {
                // 标题
                streamWriter.Write(WithTimeSpanLogData.GetCSVTitle());

                // 内容

                var list = logTag_List;
                list.Sort((a, b) => a.idx - b.idx);

                foreach (var data in list)
                {
                    streamWriter.Write($"{data}\n");
                }

                streamWriter.Close();
            }
            Debug.Log("WriteTagLogs : BuildingTagLogs.csv Successfully!");

            ret = true;
            error = string.Empty;
        }
        catch (System.Exception er)
        {
            ret = false;
            error = er.ToString();
        }
        finally
        {
            if (!ret)
            {
                Debug.LogError($"WriteTagLogs : BuildingTagLogs.csv Failured, error : {error}");
            }
        }
        return ret;
    }
}

CSV Output

编号, 标记, 耗时, 开始描述, 结束描述, 开始时间, 结束时间, 开始文件, 开始行, 结束文件, 结束行
0, Test, 00:00:02.0112773, 开始Test函数,并标记, 结束Test函数,并统计消耗, 2023/4/21 15:36:10, 2023/4/21 15:36:12, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 73, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 75
1, Test2, 00:00:01.0104517, 开始Test2函数,并标记, 结束Test2函数,并统计耗时, 2023/4/21 15:36:12, 2023/4/21 15:36:13, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 77, C:\SuoguoProject\Client\Assets\Editor\TSLog.cs, 79

有关Unity - 带耗时 begin ... end 的耗时统计的Log - TSLog的更多相关文章

  1. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  2. UE4 源码阅读:从引擎启动到Receive Begin Play - 2

    一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  5. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  6. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  7. ruby - Heroku production.log 文件位置 - 2

    我想在heroku.com上查看我的应用程序日志的内容,所以我关注了thisexcellentadvice并拥有我所有的日志内容。但是我现在很想知道我的日志文件实际在哪里,因为“log/production.log”似乎是空的:C:\>herokuconsoleRubyconsoleforajpbrevx.heroku.com>>files=Dir.glob("*")=>["public","tmp","spec","Rakefile","doc","config.ru","app","config","lib","README","Gemfile.lock","vendor","sc

  8. ruby-on-rails - 语法错误 : unexpected $end when using if/else if? - 2

    我从我的一个Controller类中收到一个错误,我不知道为什么。错误是:SyntaxErrorinTermsController#show,syntaxerror,unexpected$end,expectingkeyword_end这是terms_controller.rb:classTermsController我的展示页面目前只包含:这可能是我遗漏的一些小东西-感谢您的帮助! 最佳答案 问题是end关键字不够,它在它之前找到了$end(代表文件结尾的标记)可以找到它要找的东西——另一个end。(end关键字的解析器标记是“k

  9. ruby - 可以像在 C# 中使用#region 一样在 Ruby 中使用 begin/end 吗? - 2

    我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用

  10. ruby - 在不添加 "end"的情况下编写 Ruby 的任何方法? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭11年前。Ruby是一种美丽的语言,但有一个我讨厌写很多次的关键词“结束”。有什么方法可以写出简洁的代码而不用每次都写“end”吗?

随机推荐