Jsoup V的幕后秘密:优化的技巧和窍门

我们做对了,现在是时候更快地做事了。 我们会牢记Donald Knuth的警告:“大约97%的时间,我们应该忘记效率低下:过早的优化是万恶之源”。

根据Jonathan Hedley的介绍,他使用YourKit Java Profiler来测量内存使用情况并找到性能热点。 使用此类工具的统计结果对于优化的成功至关重要,它将阻止您花费时间思考和进行无用的调优,这不会提高性能,但也会使代码不必要地变得复杂且难以维护。 乔纳森(Jonathan)在“科隆(Colophon)”中也谈到了这一点。

我们将列出Jsoup中使用的一些技巧和窍门,它们目前是随机排序的,将来会重新组织。

Jsoup的秘密

1.缩进填充

// memoised padding up to 21, from "", " ", "  " to "                   "
static final String[] padding = {......};public static String padding(int width) {if (width < 0)throw new IllegalArgumentException("width must be > 0");if (width < padding.length)return padding[width];char[] out = new char[width];for (int i = 0; i < width; i++)out[i] = ' ';return String.valueOf(out);
}protected void indent(Appendable accum, int depth, Document.OutputSettings out) throws IOException {accum.append('\n').append(StringUtil.padding(depth * out.indentAmount()));
}

很聪明吧? 它保留了不同长度的填充缓存,可以覆盖80%的情况-我认为这是基于作者的经验和统计数据。

2.是否上课?

Element#hasClass被标记为对性能敏感的 ,例如,我们要检查<div class="logged-in env-production intent-mouse">是否具有类production ,将类按空格分割为一个数组,然后循环并进行搜索,但深入了解这将是无效的。 Jsoup首先在这里介绍了Early Exit ,方法是将长度与目标类名进行比较,以避免不必要的扫描和搜索,这也将是有益的。 然后,它使用一个检测空白的指针并执行regionMatches-坦白地说,这是我第一次了解方法String#regionMatches &#55357;&#56904;&#55357;&#56837;。

public boolean hasClass(String className) {final String classAttr = attributes().getIgnoreCase("class");final int len = classAttr.length();final int wantLen = className.length();if (len == 0 || len < wantLen) {return false;}// if both lengths are equal, only need compare the className with the attributeif (len == wantLen) {return className.equalsIgnoreCase(classAttr);}// otherwise, scan for whitespace and compare regions (with no string or arraylist allocations)boolean inClass = false;int start = 0;for (int i = 0; i < len; i++) {if (Character.isWhitespace(classAttr.charAt(i))) {if (inClass) {// white space ends a class name, compare it with the requested one, ignore caseif (i - start == wantLen && classAttr.regionMatches(true, start, className, 0, wantLen)) {return true;}inClass = false;}} else {if (!inClass) {// we're in a class name : keep the start of the substringinClass = true;start = i;}}}// check the last entryif (inClass && len - start == wantLen) {return classAttr.regionMatches(true, start, className, 0, wantLen);}return false;
}

3.标签名称是否存在?

正如我们在之前的文章中所分析的那样, HtmlTreeBuilderState将通过检查某个集合中的标记名称是否正确来验证嵌套的正确性。 我们可以比较1.7.3之前和之后的实现以进行检查。

// 1.7.2
} else if (StringUtil.in(name, "base", "basefont", "bgsound", "command", "link", "meta", "noframes", "script", "style", "title")) {return tb.process(t, InHead);
}// 1.7.3
static final String[] InBodyStartToHead = new String[]{"base", "basefont", "bgsound", "command", "link", "meta", "noframes", "script", "style", "title"};
...
} else if (StringUtil.inSorted(name, Constants.InBodyStartToHead)) {return tb.process(t, InHead);
}

根据作者的评论,“这里有点难读,但与动态varargs相比,GC更少。 贡献了大约10%的解析GC负载。 必须确保将这些排序,如在findSorted中使用的一样。 简单地使用static final常量数组,也可以对其进行排序,以便二进制搜索也可以从O(n)改进为O(log(n)),在这里性价比非常好。

但是,“如果添加更多的数组,则必须更新HtmlTreebuilderStateTest”不是同步恕我直言的好方法,而不是复制和粘贴,我将使用反射来检索这些常量。 您可以在Pull Request #1157中找到我的建议:“简化状态排序状态单元测试–避免在HtmlTreeBuilderStateTest.java中重复代码” 。

4.轻量级模式

您知道Integer.valueOf(i)的技巧吗? 如果已配置( java.lang.Integer.IntegerCache.high ),则它将维护从-128到127或更高的IntegerCache缓存,结果,当值位于不同范围时, == equals结果将有所不同(经典Java面试问题?)。 这实际上是一个轻量级模式的示例。 对于Jsoup,应用此模式还将减少对象创建的时间并提高性能。

/*** Caches short strings, as a flywheel pattern, to reduce GC load. Just for this doc, to prevent leaks.* <p />* Simplistic, and on hash collisions just falls back to creating a new string, vs a full HashMap with Entry list.* That saves both having to create objects as hash keys, and running through the entry list, at the expense of* some more duplicates.*/
private static String cacheString(final char[] charBuf, final String[] stringCache, final int start, final int count) {// limit (no cache):if (count > maxStringCacheLen)return new String(charBuf, start, count);if (count < 1)return "";// calculate hash:int hash = 0;int offset = start;for (int i = 0; i < count; i++) {hash = 31 * hash + charBuf[offset++];}// get from cachefinal int index = hash & stringCache.length - 1;String cached = stringCache[index];if (cached == null) { // miss, addcached = new String(charBuf, start, count);stringCache[index] = cached;} else { // hashcode hit, check equalityif (rangeEquals(charBuf, start, count, cached)) { // hitreturn cached;} else { // hashcode conflictcached = new String(charBuf, start, count);stringCache[index] = cached; // update the cache, as recently used strings are more likely to show up again}}return cached;
}

还有另一种情况,可以使用相同的想法来最小化新的StringBuilder GC。

private static final Stack<StringBuilder> builders = new Stack<>();/*** Maintains cached StringBuilders in a flyweight pattern, to minimize new StringBuilder GCs. The StringBuilder is* prevented from growing too large.* <p>* Care must be taken to release the builder once its work has been completed, with {@see #releaseBuilder}
*/
public static StringBuilder borrowBuilder() {synchronized (builders) {return builders.empty() ?new StringBuilder(MaxCachedBuilderSize) :builders.pop();}
}

实际上, CharacterReaderStringUtil值得越来越消化,因为有许多有用的提示和技巧会激发您的灵感。

5.其他改善方法

  • 使用RandomAccessFile读取文件,使文件读取时间缩短了2倍。 查看#248了解更多详情
  • 节点层次结构重构。 查看#911了解更多详细信息
  • “在很大程度上基于对各种网站的分析重新排序HtmlTreeBuilder方法而带来的改进” –我在此列出了这一点,因为它非常实用。 更深入地了解和观察代码的运行方式也将为您提供一些见解
  • 调用list.toArray(0)而不是list.toArray(list.size()) –已在某些开源项目(例如h2database)中使用 ,因此我也在另一个Pull Request #1158中提出了此要求

6.未知数

优化永无止境。 我目前还没有发现很多提示和技巧。 如果您能在Jsoup中找到更多启发性的想法,请与我分享,我将不胜感激。 您可以在本网站的左侧栏中找到我的联系信息,或者直接通过ny83427 at gmail.com发送电子邮件至ny83427 at gmail.com

-未完待续-

翻译自: https://www.javacodegeeks.com/2019/02/secrets-jsoup-tricks-optimization.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤教育】广东开放大学 会议运行管理 形成性考核 (38)

选择题 题目&#xff1a; 会议的含义是 选择一项&#xff1a; 答案&#xff1a;看左侧 题目&#xff1a; 报告、发言、讲话、辩论等口头交流的方式是与会人员传递信息、交流思想、表达意志和阐明立场的主要手段。这是指的会议的什么性质 选择一项&#xff1a; 答案&#xff1…

计算机二级选择题复习整理(公共基础部分)

主要列个人不太熟悉或较为重要的点&#xff0c;不求全。 一、计算机基础 1、计算机最早应用领域是数值计算 2、冯诺依曼型体系计算机引进概念&#xff1a;二进制、存储程序 3、CAD&#xff1a;设计&#xff1b;CAM&#xff1a;制造&#xff1b;CAI&#xff1a;教育&#xff1…

【渝粤教育】广东开放大学 动画概论 形成性考核 (44)

选择题 题目&#xff1a;“动画”这个词最早是哪国人提出的 答案&#xff1a;看左侧 题目&#xff1a;被誉为“动画的鼻祖”的是 答案&#xff1a;看左侧 题目&#xff1a;被公认为世界上第一部动画影片的是 答案&#xff1a;看左侧 题目&#xff1a;动画片是电影的一种特殊类…

【渝粤教育】广东开放大学 嵌入式数据库 形成性考核 (48)

选择题 题目&#xff1a;SQL语句中的条件用以下哪一项来表达&#xff08; &#xff09; 题目&#xff1a;“Create Unique Index AAA On 学生表&#xff08;学号&#xff09;”将在学生表上创建名为I_xsb的&#xff08; &#xff09;。 题目&#xff1a;&#xff08; &#xff…

移动通信学习笔记03_蜂窝原理

教学大纲&#xff1a;组网技术 基本内容&#xff1a;典型的多址接入技术&#xff1b;话务量与呼损率的计算&#xff1b;蜂窝的概念、频率复用原则和区群的概念&#xff1b;信道的分配策略和分配原则&#xff1b;蜂窝系统的基本网络结构和各部分的功能&#xff1b;切换和漫游&am…

【渝粤教育】广东开放大学 影视艺术概论 形成性考核 (52)

选择题 题目&#xff1a; 电影被称为 。 选择一项&#xff1a; 答案&#xff1a;看左侧 题目&#xff1a; 《淘金记》是 的作品。 选择一项&#xff1a; 答案&#xff1a;看左侧 题目&#xff1a; 《母与法》是由 拍摄的。 选择一项&#xff1a; 答案&#xf…

java rmi 使用管道_使用Java RMI时要记住的两件事

java rmi 使用管道这是一篇简短的博客文章&#xff0c;介绍使用Java RMI时应注意的两个常见陷阱。 设置java.rmi.server.hostname 如果您感到陌生&#xff0c;Connection拒绝托管&#xff1a; RMI客户端上的错误消息&#xff0c;并且您确定连接应该正常工作&#xff08;您仔细…

【渝粤教育】广东开放大学 文化产业项目案例分析 形成性考核 (51)

选择题 题目&#xff1a;《武林外传》发生在虚拟的唐代。 答案&#xff1a;看左侧 题目&#xff1a;《武林外传》中李大嘴是一个厨师。 答案&#xff1a;看左侧 题目&#xff1a;《疯狂动物城》是一部动画片。 答案&#xff1a;看左侧 题目&#xff1a;影片的整体框架是“小镇少…

01_2_数字基带传输及其频谱特性

一、数字基带信号的表示 g(t)g(t)g(t)是一个基本的脉冲&#xff0c;有不同形状&#xff1b;ana_nan​从信源出来的信息码序列&#xff0c;只有电平特性。 二、功率谱密度的推导过程 ① 广义平稳随机信号的自相关函数和功率谱密度之间互为傅立叶变换关系 ② 计算基带信号的自相…

【渝粤教育】广东开放大学 标准化理论与方法 形成性考核 (53)

选择题 题目&#xff1a; 根据《标准化法》规定&#xff0c;企业生产的产品没有国家标准、行业标准和地方标准的&#xff0c;应当制定相应的企业标准作为( )。 答案&#xff1a;看左侧 题目&#xff1a; 现阶段常用的标准的载体包括( )。 答案&#xff1a;看左侧 题目&#x…

Linux环境变量剖析

一、什么是环境变量 概念&#xff1a;环境变量&#xff08;environment variables&#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;是在操作系统中一个具有特定名字的对象&#xff0c;它包含了一个或多个应用程序所将使用到的信息&#xff0c…

APIGEE:用于API代理的CI / CD管道

在本文中&#xff0c;我们将看到如何为APIGEE API代理创建CI / CD管道。 我已经参考了APIGEE社区上同一主题的几篇文章。 这些给了一些关于如何为API代理设置CI / CD管道的想法。 这是我用来设置CI / CD的工具。 詹金斯 节点 蜂胶 新人 APIGEE管理API 确保已创建APIGEE边…

【渝粤教育】广东开放大学 知识产权法 形成性考核 (34)

选择题 题目&#xff1a;作品的独创性要求作品系作者独立完成&#xff0c;不是抄袭而来。 题目&#xff1a;下列关于发行权的表述&#xff0c;不正确的是&#xff08; &#xff09; 题目&#xff1a;下列哪一情形可以授予专利&#xff1f;&#xff08; &#xff09; 题目&#…

01_3基带传输的常用码型和码间串扰

第十七讲 基带传输的常用码型和码间串扰 第一节 基带传输的常用码型 一、数字基带信号的编码规则 基带传输对信号的要求&#xff08;即独立又有联系&#xff09; 对传输码型的要求&#xff1a;原始消息码必须编成适合于信道传输用的码型&#xff08;码型的选择&#xff09; …

【渝粤教育】广东开放大学 网络市场调查与预测 形成性考核 (23)

选择题 题目&#xff1a;&#xff08;&#xff09;是利用互联网发掘和了解顾客需求、市场机会、竞争对手、行业潮流、分销渠道以及战略合作伙伴等方面的情况。 题目&#xff1a;市场调查首先要解决的问题是&#xff08; &#xff09;。 题目&#xff1a;为了在市场调查方案实施…

移动通信考前预习_第1章_无线通信系统概述

下周考试&#xff0c;开始预习。 第一章为概念&#xff0c;直接copyPPT。 第1章 无线通信系统概述 一、移动通信发展 1、第一代 80年代——模拟通信时代&#xff08;1G&#xff09; 典型系统&#xff1a;AMPS系统&#xff08;先进移动电话系统&#xff09;、TACS系统&#…

【渝粤教育】广东开放大学 财务管理 形成性考核 (58)

选择题 题目&#xff1a; 市场宣传的首要步骤就是确定&#xff08; &#xff09;&#xff0c;从而明确宣传目标和宣传内容。 选择一项&#xff1a; 答案&#xff1a;看左侧 题目&#xff1a;下列各项中体现债权与债务关系的是&#xff08; &#xff09; 答案&#xff1a;看左侧…

java 调试 工具_Java调试器–权威的工具列表

java 调试 工具Java调试是一个复杂的空间。 调试器的类型很多&#xff0c;工具也很多。 在此页面中&#xff0c;我们将介绍7种类型的调试器之间的区别&#xff0c;并查看每个类别中的主要工具&#xff0c;以帮助您为正确的工作选择正确的工具。 以下是我们介绍的调试器类型&a…

移动通信考前预习_第2章_蜂窝技术

一、蜂窝的概念 1、系统级的概念&#xff1a;用许多小功率的发射机&#xff08;小覆盖区&#xff09;来代替单个的大功率发射机&#xff08;大覆盖区&#xff09;&#xff0c;每个小覆盖区只提供服务范围内的一小部分覆盖。 2、不需要做技术上的重大修改&#xff0c;没有增加额…

【渝粤教育】电大中专中成药作业 题库

试卷答案 1.风寒感冒患者宜选用的中成药是&#xff08;&#xff09;。 A.连花清瘟胶囊 B.双黄连颗粒 C.银翘解毒颗粒 D.桑菊感冒颗粒 E.感冒清热颗粒 正确 正确答案&#xff1a;左边查询 学生答案&#xff1a;E 2.症见恶寒发热、头痛鼻塞、咳嗽痰多、胸闷呕逆、乏力气短宜选用的…