1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00

Mass_parse: Change page_cache to LRU cache [#483]

This commit is contained in:
gnosygnu
2019-06-21 23:02:49 -04:00
parent 0cfb0b19ad
commit a01e7409eb
21 changed files with 367 additions and 144 deletions

View File

@@ -0,0 +1,117 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.core.lists.caches; import gplx.*; import gplx.core.*; import gplx.core.lists.*;
public class Lru_cache {
private final Hash_adp map = Hash_adp_.New();
private long max;
private long cur = 0;
private Lru_node head;
private Lru_node tail;
private long evicts;
public void Max_(long max) {
this.max = max;
}
public long Evicts() {return evicts;}
public long Cur() {return cur;}
public Object Get_or_null(Object key) {
Lru_node nde = (Lru_node)map.Get_by(key);
if (nde == null) {
return null;
}
Del_node_from_linked_list(nde);
Add_to_tail(nde);
return nde.Val();
}
public void Set(Object key, Object val, long size) {
Lru_node nde = (Lru_node)map.Get_by(key);
if (nde != null) {
nde.Val_(val);
Del_node_from_linked_list(nde);
Add_to_tail(nde);
}
else {
while (cur + size > max) {
Del_node_from_this(head);
evicts++;
}
nde = new Lru_node(key, val, size);
Add_to_tail(nde);
map.Add(key, nde);
cur += size;
}
}
public void Del(Object key) {
Lru_node nde = (Lru_node)map.Get_by(key);
if (nde != null) {
Del_node_from_this(nde);
}
}
public void Clear() {
map.Clear();
head = null;
tail = null;
cur = 0;
}
private void Del_node_from_this(Lru_node nde) {
map.Del(nde.Key());
cur -= nde.Size();
Del_node_from_linked_list(nde);
}
private void Del_node_from_linked_list(Lru_node nde) {
if (nde.Prv() == null)
head = nde.Nxt();
else
nde.Prv().Nxt_(nde.Nxt());
if (nde.Nxt() == null)
tail = nde.Prv();
else
nde.Nxt().Prv_(nde.Prv());
}
private void Add_to_tail(Lru_node nde) {
if (tail != null)
tail.Nxt_(nde);
nde.Prv_(tail);
nde.Nxt_(null);
tail = nde;
if (head == null)
head = tail;
}
}
class Lru_node {
private final Object key;
private Object val;
private final long size;
private Lru_node prv;
private Lru_node nxt;
public Lru_node(Object key, Object val, long size) {
this.key = key;
this.val = val;
this.size = size;
}
public Object Key() {return key;}
public Object Val() {return val;} public void Val_(Object v) {this.val = v;}
public long Size() {return size;}
public Lru_node Prv() {return prv;} public void Prv_(Lru_node v) {this.prv = v;}
public Lru_node Nxt() {return nxt;} public void Nxt_(Lru_node v) {this.nxt = v;}
}

View File

@@ -0,0 +1,116 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.core.lists.caches; import gplx.*; import gplx.core.*; import gplx.core.lists.*;
import org.junit.*; import gplx.core.tests.*;
import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.wikis.nss.*;
public class Lru_cache_tst {
private final Lru_cache_fxt fxt = new Lru_cache_fxt();
@Test public void Get_one() {
fxt.Init__max(10);
fxt.Exec__set("a", 5);
fxt.Test__get_y("a");
}
@Test public void Pop_one() {
fxt.Init__max(10);
fxt.Exec__set("a", 10);
fxt.Exec__set("b", 10);
fxt.Test__get_n("a");
fxt.Test__get_y("b");
}
@Test public void Add_many() {
fxt.Init__max(10);
fxt.Exec__set("a", 4);
fxt.Exec__set("b", 3);
fxt.Exec__set("c", 2);
fxt.Exec__set("d", 1);
fxt.Test__get_y("a", "b", "c", "d");
}
@Test public void Pop_many() {
fxt.Init__max(10);
fxt.Exec__set("a", 4);
fxt.Exec__set("b", 3);
fxt.Exec__set("c", 2);
fxt.Exec__set("d", 1);
fxt.Exec__set("e", 6);
fxt.Test__get_y("c", "d", "e");
fxt.Test__get_n("a", "b");
}
@Test public void Set_repeatedly() {
fxt.Init__max(10);
fxt.Exec__set("a", "a1", 10);
fxt.Exec__set("a", "a2", 10);
fxt.Exec__set("a", "a3", 10);
fxt.Test__get_val("a", "a3");
}
@Test public void Set_bumps_priority() {
fxt.Init__max(10);
fxt.Exec__set("a", 2);
fxt.Exec__set("b", 3);
fxt.Exec__set("c", 2);
fxt.Exec__set("a", 2);
fxt.Exec__set("d", 7);
fxt.Test__get_y("a", "d");
fxt.Test__get_n("b", "c");
}
@Test public void Del() {
fxt.Init__max(10);
fxt.Exec__set("a", 2);
fxt.Exec__set("b", 2);
fxt.Exec__del("b");
fxt.Test__get_y("a");
fxt.Test__get_n("b");
}
@Test public void Clear() {
fxt.Init__max(10);
fxt.Exec__set("a", 2);
fxt.Exec__set("b", 2);
fxt.Exec__clear();
fxt.Test__get_n("a", "b");
}
}
class Lru_cache_fxt {
private final Lru_cache cache = new Lru_cache();
public void Init__max(long max) {
cache.Max_(max);
}
public void Exec__set(String key, long size) {
cache.Set(key, key, size);
}
public void Exec__set(String key, String val, long size) {
cache.Set(key, val, size);
}
public void Exec__del(String key) {
cache.Del(key);
}
public void Exec__clear() {
cache.Clear();
}
public void Test__get_y(String... keys) {
for (String key : keys)
Test__get(key, key);
}
public void Test__get_n(String... keys) {
for (String key : keys)
Test__get(key, null);
}
public void Test__get_val(String key, String val) {
Test__get(key, val);
}
private void Test__get(String key, String expd) {
Object actl = cache.Get_or_null(key);
Gftest.Eq__obj_or_null(expd, actl);
}
}