字符串的耗时操作

在一个新闻采集的项目中,处理一条信息时CPU竟然耗尽,后查找原因发现在一个do...while循环里耗时竟超过20分钟。一般而言,一百万的循环耗时一般为一秒。因此如果一个循环就能将CPU耗尽长达20多分钟,那么循环里一定会有其它非循环操作在作怪。原处理方法如下:

/// <summary>
        /// 格式化Html正文.
        /// </summary>
        /// <param name="Content">Html文档内容。</param>
        /// <param name="Buf">结果缓冲区。</param>
        public static void FormatHtml(string Content, HtmlBufBase Buf)
        {
            if (string.IsNullOrEmpty(Content))
                return;
            // 过滤前面未处理的标记
            int TagEnd = Content.IndexOf('>', 0);
            if (TagEnd == -1)
                TagEnd = 0;
            else
            {
                //处理Title中的HTML标签
                int pos = GetNextTagStartPosition(Content, 0);
                if (pos > -1 && TagEnd > pos)
                    TagEnd = 0;
                else
                    TagEnd++;
            }
            bool bIsNotInHideTag = true;  // 是否不在隐藏的标记内容中
            bool bIsNotInStyle = true;
            string HideTag = null;
            string LastTag = null;
            do
            {
                if (Content.Contains("国家统计局服务业调查中心"))
                {
                }
                // 找标记开始
                int TagStart = GetNextTagStartPosition(Content, TagEnd);
                if (TagStart == -1)
                    TagStart = Content.Length;// 达到结尾
                else if (Content.IndexOf("!--", TagStart) == TagStart+1)   // 判断是否是注释
                {
                    TagEnd = Content.IndexOf("-->", TagStart)+3;
                    if (TagStart == -1)
                        TagStart = Content.Length;
                    continue;
                }
                // 转换内容
                if (bIsNotInHideTag && bIsNotInStyle)
                    Buf.AppendText(Content.Substring(TagEnd, TagStart - TagEnd));
                // 找标记结束
                TagEnd = GetNextTagEndPosition(Content, TagStart);
                if (TagEnd > -1)
                {
                    TagEnd++;
                    TagStart++;
                    string TagInfo;
                    string Tag = GetTagAndTagInfo(Content, TagEnd, TagStart, out TagInfo);
 
                    if (Tag == "script")  // 脚本开始
                    {
                        int scriptEndPos = Content.IndexOf("</script>", TagStart, StringComparison.OrdinalIgnoreCase);
                        if (scriptEndPos > 0)
                        {
                            TagEnd = scriptEndPos + 9;
                        }
                        else
                        {
                            TagEnd = Content.Length;
                        }
                    }
                    else if (Tag == "style")
                    {
                        bIsNotInStyle = false;
                    }
                    else if (Tag == "/style")
                    {
                        bIsNotInStyle = true;
                    }
                    else if (TagInfo.ToLower().IndexOf("display:none") > 0)
                    {
                        bIsNotInHideTag = false;
                        HideTag = Tag;
                    }
                    else if (Tag == "/" + HideTag)
                    {
                        bIsNotInHideTag = true;
                        HideTag = null;
                    }
                    else
                        Buf.AppendTag(Tag, TagInfo);
 
                    //else if (Tag == "base")
                    //    BaseUrl = GetBaseUrl(TagInfo);
                    LastTag = Tag;
                }
                else
                    break;
            } while (true);
            Buf.ReFormatText();
        }
 
最近查找到有一条语句特别耗时即
 else if (Content.IndexOf("!--", TagStart) == TagStart+1)   // 判断是否是注释,这个字符串的查找都是全文查找,肯定特别耗时,这条语句的功能是判断标签是否是注释,因此没必要去判断”!--“只需要判断!即可。因此使用字符查找即可,改动如下:
 else if (Content[TagStart+1] == '!')   // 判断是否是注释
改成上面语句后CPU尽管会耗尽,但耗时只需30秒。
深入追究一下,可知字符的查找应该是数组的查找,为什么不直接使用数组下标呢?改动如下:
Content[TagStart + 1] == '!'
改后测试一下,在本方法中的两万多次循环中只需要60毫秒。
最后程序改动如下:
 /// <summary>
        /// 格式化Html正文.
        /// </summary>
        /// <param name="Content">Html文档内容。</param>
        /// <param name="Buf">结果缓冲区。</param>
        public static void FormatHtml(string Content, HtmlBufBase Buf)
        {
            if (string.IsNullOrEmpty(Content))
                return;
 
            // 过滤前面未处理的标记
            int TagEnd = Content.IndexOf('>', 0);
            if (TagEnd == -1)
                TagEnd = 0;
            else
            {
                //处理Title中的HTML标签
                int pos = GetNextTagStartPosition(Content, 0);
                if (pos > -1 && TagEnd > pos)
                    TagEnd = 0;
                else
                    TagEnd++;
            }
            bool bIsNotInHideTag = true;  // 是否不在隐藏的标记内容中
            bool bIsNotInStyle = true;
 
            string HideTag = null;
            string LastTag = null;
            do
            {
                // 找标记开始
                int TagStart = GetNextTagStartPosition(Content, TagEnd);
                if (TagStart == -1)
                    TagStart = Content.Length;// 达到结尾
              
                // 转换内容
                if (bIsNotInHideTag && bIsNotInStyle)
                    Buf.AppendText(Content.Substring(TagEnd, TagStart - TagEnd));
                // 判断是否是注释
                if (TagStart != -1 && TagStart < Content.Length && Content[TagStart + 1] == '!')   
                {
                    TagEnd = Content.IndexOf("-->", TagStart);
                    if (TagEnd == -1)//没有找到注释的结束标记
                    {
                        TagEnd = Content.Length;
                    }
                    else//有注释的结束标记,跳过本标记
                    {
                        TagEnd = TagEnd + 3;
                        continue;
                    }
                }
                // 找标记结束
                TagEnd = GetNextTagEndPosition(Content, TagStart);
                if (TagEnd > -1)
                {
                    TagEnd++;
                    TagStart++;
                    string TagInfo;
                    string Tag = GetTagAndTagInfo(Content, TagEnd, TagStart, out TagInfo);
 
                    if (Tag == "script")  // 脚本开始
                    {
                        int scriptEndPos = Content.IndexOf("</script>", TagStart, StringComparison.OrdinalIgnoreCase);
                        if (scriptEndPos > 0)
                        {
                            TagEnd = scriptEndPos + 9;
                        }
                        else
                        {
                            TagEnd = Content.Length;
                        }
                    }
                    else if (Tag == "style")
                    {
                        bIsNotInStyle = false;
                    }
                    else if (Tag == "/style")
                    {
                        bIsNotInStyle = true;
                    }
                    else if (TagInfo.ToLower().IndexOf("display:none") > 0)
                    {
                        bIsNotInHideTag = false;
                        HideTag = Tag;
                    }
                    else if (Tag == "/" + HideTag)
                    {
                        bIsNotInHideTag = true;
                        HideTag = null;
                    }
                    else
                        Buf.AppendTag(Tag, TagInfo);
 
                    //else if (Tag == "base")
                    //    BaseUrl = GetBaseUrl(TagInfo);
                    LastTag = Tag;
                }
                else
                    break;
            } while (true);
            Buf.ReFormatText();
        }

转载于:https://www.cnblogs.com/chensuqian/p/9644813.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Flutter中,可以使用Dart语言提供的字符串截取方法来截取字符串。有几种常用的方法可以实现字符串截取操作。 一种方法是使用Dart的substring()方法。这个方法可以通过指定起始位置和结束位置来截取字符串的一部分。例如,使用str.substring(startIndex, endIndex)可以截取字符串str从startIndex位置到endIndex位置的子字符串。 另一种方法是使用split()方法。通过传入一个分隔符作为参数,split()方法可以将字符串拆分成一个字符串数组。例如,可以使用str.split(",")来以逗号作为分隔符来拆分字符串str,并返回一个包含拆分后子字符串的数组。 还可以使用正则表达式来进行字符串截取。可以使用split()方法,其中传入的参数是一个正则表达式,这样可以根据正则表达式来拆分字符串。不过需要注意,使用这种方式截取字符串会有一定的性能损耗,因为分析正则表达式非常耗时。 综上所述,在Flutter中可以通过substring()方法、split()方法和正则表达式来实现字符串截取操作。具体使用哪种方法取决于你的具体需求和性能要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [字符串截取的常用方法](https://blog.csdn.net/weixin_31319319/article/details/112044745)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值