zoukankan      html  css  js  c++  java
  • String.StartsWith与 EndsWith在大量使用时效率果然极低

    今天在写一个工具时,写着写着发现执行速度突然变慢。最后发现是string.StartsWith与EndsWith的锅,改为手动比较后,执行时间变成原来的1/5-1/10。代码如下 ,黄色背景是主要部分

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    using System.IO;
    using System.Threading;
    using System.Text.RegularExpressions;
    using System;
    
    public class XLogicCodeCheck
    {
    
        [MenuItem("代码检查/逻辑层代码检查")]
        public static void StartLogicCodeCheck()
        {
            Debug.Log("逻辑层代码检查");
    
            var path = "Assets/Scripts/Logic";
            var files = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories);
    
            var total = 0.0f;
            var totalFind = 0;
            var errLines = new List<string>(100);
            foreach (var item in files)
            {
                var allines = File.ReadAllLines(item);
                if(allines.Length > 0 && allines[0].Trim().StartsWith("//Float_Uncheck"))
                {//Float_Uncheck
                    continue;
                }
    
                for (int i = 0; i < allines.Length; ++i)
                {
                    var ltext = allines[i].Trim();
                    if (CheckLine(allines, i))
                    {
                        var info = $"发现有问题代码,文件:{item}, 行:{i + 1},  {ltext}";
                        EditorUtility.DisplayDialog("逻辑层代码检查", info, "确定");
                        errLines.Add(info);
                        totalFind++;
                    }
                }
    
                EditorUtility.DisplayProgressBar("逻辑层代码检查", $"进度:", total++ / files.Length);
            }
    
            if (totalFind == 0)
            {
                EditorUtility.DisplayDialog("逻辑层代码检查", "检查完成,没有发现问题", "确定");
            }
            else
            {
                var savePath = "Assets/FloatCheck.txt";
                EditorUtility.DisplayDialog("逻辑层代码检查", $"检查完成,共发现{totalFind}处问题,已保存到文件:{savePath}", "确定");
    
                File.WriteAllLines(savePath, errLines);
            }
    
            Debug.Log("逻辑层代码检查完成");
    
        }
    
        static string[] rules = new string[] {
                @"[s(]float[s)]", @"[s(]double[s)]", @"d+.d+",  //float, double, 浮点数值
                @"sMath.[a-zA-Z]+s*(", @"sMathf.[a-zA-Z]+s*(", //Math或Mathf相关API
                @"news+Randoms*(",@"news+Systems*.s*Randoms*(", @"Randoms*.s*RandomRanges*(", @"Randoms*.s*Ranges*(", @"Randoms*.s*ColorHSVs*(",//随机数
            };
    
        static string[] excludeRules = new string[] { "Math.Max", "Math.Min", "Math.Abs" }; //排除项,不检查这些
        private static bool CheckLine(string[] allines, int iline)
        {
            var codeStr = FilterComment(allines, iline).Trim();
            if (codeStr.Length <= 0) return false;
    
            foreach (var item in rules)
            {
                var matches = Regex.Matches(codeStr, item);
                foreach (Match match in matches)
                {
                    var isok = true;
                    foreach (var exc in excludeRules)
                    {
                        if (match.Value.Contains(exc)) isok = false;
                    }
    
                    if (isok) return true;
                }
    
            }
    
            return false;
        }
    
        //过滤掉注释
        private static string FilterComment(string[] allines, int iline)
        {
            if (InBlockComment(allines, iline)) return "";
    
            var codeStr = allines[iline];
            if (codeStr.Contains("Float_Uncheck") || codeStr.StartsWith("//") || codeStr.StartsWith("/*") || codeStr.StartsWith("#region"))
            {
                return "";
            }
    
            //去除行中注释
            var cmtIdx = codeStr.IndexOf("//");
            if (cmtIdx < 0)
            {
                cmtIdx = codeStr.IndexOf("/*");
            }
            if (cmtIdx >= 0)
            {
                codeStr = codeStr.Substring(0, cmtIdx);
            }
    
            return codeStr;
        }
    
        //是否在块注释中
        private static bool InBlockComment(string[] allines, int iline)
        {
            for (int i = iline-1; i>=0; --i)
            {
                var line = allines[i];
                var lineLen = line.Length;
                if(lineLen >= 2)
                {
                    if (line[lineLen - 2] == '*' && line[lineLen - 1] == '/')
                    {//line.EndsWith("*/"),这个函数非常低效
                        return false;
                    }
                    else if (line[0] == '/' && line[1] == '*')
                    {//line.StartsWith("*/"),这个函数非常低效
                        return true;
                    }
                }
            }
    
            return false;
        }
    
    }
  • 相关阅读:
    解决多并发
    一个交换机到底能带几台摄像头?结合生产经验咱们来分析!
    ELK查询命令详解
    Ansible自动化部署入门到进阶笔记
    批量SSH key-gen无密码登陆认证脚本
    ELK查询命令详解总结
    Shell 正则表达式详解
    Linux 常用系统性能命令总结
    什么叫做消息队列呢?
    批量SSH key-gen无密码登陆认证脚本 附件脚本
  • 原文地址:https://www.cnblogs.com/timeObjserver/p/14223755.html
Copyright © 2011-2022 走看看