开机之后,首次制作索引会非常慢,但后面就会快了 重启机器,第一次制作又会非常慢 这是为什么呢?
在 parserContent 里面,我们进行了一个读文件的操作
缓存
parserContent
的核心操作,就是读取文件,从磁盘进行访问,操作系统就会对“经常读取的文件”进行缓存
首次运行的时候,当前的这些 Java 文档,都没有在内存中缓存,因此读取的时候只能直接从硬盘上读取(相对耗时)
后面再运行的时候,由于前面已经读取过这些文档了,这些文档都在操作系统中其实已经有了一份缓存(在内存中),这次的读取不必直接读取硬盘,而是直接读内存的缓存(速度就会快很多)
我们可以通过使用一些线程类,来将缓存加进去,提高读取速率。
我们使用的读文件操作是:
int ret = fileReader.read();
read()
每次都是在读磁盘,速度就会比较慢fileReader
的内容提前就读取到内存之中,然后每次调用 read()
的时候,就可以直接从内存中进行读取了BufferedReader
可以搭配 FileReader
来使用。我们只需要在构造 BufferedReader
的时候,把 FileReader
实例给设置进去就可以了
BufferedReader
内部就会内置一个缓冲区,就能够自动的把 FileReader
中的一些内容预读到内存中,从而减少直接访问磁盘的次数BufferedReader bufferedReader = new BufferedReader(new FileReader(f))
通过 BufferedReader
类可以看到,它的缓冲区默认值是 8192(8k),我们可以将其设置大一点。我们就将 BufferedReader 的第二个参数,手动设置一下大小
BufferedReader bufferedReader = new BufferedReader(new FileReader(f), 1024 * 1024)
1M
大小我们的索引加载逻辑,就是要从这两个文件进行加载。这里的文件保存好的索引数据,再给它保存到内存中,把它还原成内存中的那两个数据结构
// 正排索引
private ArrayList<DocInfo> forwardIndex = new ArrayList<>();
// 倒排索引
private HashMap<String, ArrayList<Weight>> invertedIndex = new HashMap<>();
我们可以验证一下这个索引加载
public static void main(String[] args) {
Index index = new Index();
index.load();
System.out.println("索引加载完毕!");
}
HTML
文件
HTML
进行解析
<
和 >
作为“是否要拷贝数据”的开关Index
类中(addDoc
方法)
通过这个 Parser
类,最主要的事情,还是辅助 Index
类,来完成索引制作的过程
Parser
类主要就是:
Index
类Parser
的 main
方法即可单线程制作索引比较低效,速度比较慢。改进成多线程之后,速度就明显有了提升。
我们要明确地描述出,这些文档什么时候能处理完。如果没处理完,我们是不能轻易地保存索引的,必须得保证所有的文档都解析完毕了、在索引中加载完毕了,才能够真正地保存在文件当中。
CountDownLatch
来计数。只有当所有的文档都处理完毕,都已经调用了 countDown
方法,撞线了,然后我们才能执行保存索引的操作在 Parser 类中,涉及到大量的读文件操作,我们通过实验得出:首次加载索引的时候速度会慢一些,后面再读就会变快了。
private ArrayList<DocInfo> forwardIndex = new ArrayList<>();
DocInfo
都表示一个文档,在这个文档里面就包含了 id
、title
、url
、content
private HashMap<String, ArrayList<Weight>> invertedIndex = new HashMap<>();
标题中出现的次数 * 10 + 正文中出现的次数
)ArrayList<DocInfo>
中的元素即可
HashMap<String, ArrayList<Weight>>
的 value
即可
Parser
类,在构建索引的时候,调用该方法
DocInfo
对象,给其添加到正排索引末尾JSON
格式,把索引数据保存到指定文件中
JSON
格式,对数据进行解析。把文件中的内容读出来,解析到内存中