zoukankan      html  css  js  c++  java
  • 字符串的耗时操作

    在一个新闻采集的项目中,处理一条信息时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();
            }
  • 相关阅读:
    gain 基尼系数
    luogu P5826 【模板】子序列自动机 主席树 vector 二分
    牛客挑战赛39 树与异或 离线 树上莫队 树状数组 约数
    4.22 省选模拟赛 三元组 manacher 回文自动机
    4.22 省选模拟赛 最优价值 网络流 最大权闭合子图
    4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列
    luogu P4008 [NOI2003]文本编辑器 splay 块状链表
    牛客挑战赛39 密码系统 后缀数组
    luogu P1526 [NOI2003]智破连环阵 搜索+最大匹配+剪枝
    luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并
  • 原文地址:https://www.cnblogs.com/chensuqian/p/9644813.html
Copyright © 2011-2022 走看看