Use an aging system for caches
This commit is contained in:
parent
d312466556
commit
0930af652f
11 changed files with 61 additions and 37 deletions
|
@ -2,46 +2,65 @@
|
||||||
|
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const zlib = require("zlib");
|
const zlib = require("zlib");
|
||||||
|
const { encode, decode } = require("@msgpack/msgpack");
|
||||||
|
|
||||||
const Edition = 2;
|
const Edition = 3;
|
||||||
|
const MAX_AGE = 5;
|
||||||
|
|
||||||
|
class GfEntry {
|
||||||
|
constructor(age, value) {
|
||||||
|
this.age = age;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Cache {
|
class Cache {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.gfSource = {};
|
this.gf = new Map();
|
||||||
this.gfSink = {};
|
|
||||||
}
|
}
|
||||||
loadRep(version, rep) {
|
loadRep(version, rep) {
|
||||||
if (!rep || rep.version !== version + "@" + Edition) return;
|
if (!rep || rep.version !== version + "@" + Edition) return;
|
||||||
this.gfSource = rep.gf || {};
|
for (const [k, e] of Object.entries(rep.gf)) {
|
||||||
|
this.gf.set(k, new GfEntry((e.age || 0) + 1, e.value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
toRep(version) {
|
toRep(version) {
|
||||||
return { version: version + "@" + Edition, gf: this.gfSink };
|
let gfRep = {};
|
||||||
|
for (const [k, e] of this.gf) {
|
||||||
|
if (e.age < MAX_AGE) gfRep[k] = { age: e.age, value: e.value };
|
||||||
|
}
|
||||||
|
return { version: version + "@" + Edition, gf: gfRep };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Geometry flattening conversion cache
|
// Geometry flattening conversion cache
|
||||||
getGF(ck) {
|
getGF(k) {
|
||||||
return this.gfSource[ck];
|
const entry = this.gf.get(k);
|
||||||
|
if (!entry) return undefined;
|
||||||
|
else return entry.value;
|
||||||
}
|
}
|
||||||
saveGF(ck, val) {
|
refreshGF(k) {
|
||||||
this.gfSink[ck] = val;
|
const entry = this.gf.get(k);
|
||||||
|
if (!entry) return;
|
||||||
|
entry.age = 0;
|
||||||
|
}
|
||||||
|
saveGF(k, v) {
|
||||||
|
this.gf.set(k, new GfEntry(0, v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.load = async function (argv) {
|
exports.load = async function (argv) {
|
||||||
let cache = new Cache();
|
let cache = new Cache();
|
||||||
if (argv.oCache && fs.existsSync(argv.oCache)) {
|
if (argv.oCache && fs.existsSync(argv.oCache)) {
|
||||||
cache.loadRep(argv.menu.version, unzip(await fs.readFile(argv.oCache)));
|
const buf = zlib.gunzipSync(await fs.readFile(argv.oCache));
|
||||||
|
cache.loadRep(argv.menu.version, decode(buf));
|
||||||
}
|
}
|
||||||
return cache;
|
return cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.save = async function savePTCache(argv, cache) {
|
exports.save = async function savePTCache(argv, cache) {
|
||||||
if (argv.oCache) await fs.writeFile(argv.oCache, zip(cache.toRep(argv.menu.version)));
|
if (argv.oCache) {
|
||||||
|
const buf = encode(cache.toRep(argv.menu.version));
|
||||||
|
const bufZip = zlib.gzipSync(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength));
|
||||||
|
await fs.writeFile(argv.oCache, bufZip);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function unzip(buf) {
|
|
||||||
return JSON.parse(zlib.gunzipSync(buf));
|
|
||||||
}
|
|
||||||
function zip(obj) {
|
|
||||||
return zlib.gzipSync(Buffer.from(JSON.stringify(obj), "utf-8"));
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ function flattenSimpleGlyph(cache, skew, g) {
|
||||||
if (ck && cached) {
|
if (ck && cached) {
|
||||||
g.clearGeometry();
|
g.clearGeometry();
|
||||||
g.includeContours(CurveUtil.repToShape(cached), 0, 0);
|
g.includeContours(CurveUtil.repToShape(cached), 0, 0);
|
||||||
cache.saveGF(ck, cached);
|
cache.refreshGF(ck);
|
||||||
} else {
|
} else {
|
||||||
const tfBack = new Transform(1, -skew, 0, 1, 0, 0);
|
const tfBack = new Transform(1, -skew, 0, 1, 0, 0);
|
||||||
const tfForward = new Transform(1, +skew, 0, 1, 0, 0);
|
const tfForward = new Transform(1, +skew, 0, 1, 0, 0);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const zlib = require("zlib");
|
const zlib = require("zlib");
|
||||||
|
const { encode } = require("@msgpack/msgpack");
|
||||||
|
|
||||||
const { FontIo } = require("ot-builder");
|
const { FontIo } = require("ot-builder");
|
||||||
const Toml = require("@iarna/toml");
|
const Toml = require("@iarna/toml");
|
||||||
|
@ -103,12 +104,5 @@ async function saveCharMap(argv, glyphStore) {
|
||||||
...createGrDisplaySheet(glyphStore, gn)
|
...createGrDisplaySheet(glyphStore, gn)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
await fs.writeFile(argv.oCharMap, zip(charMap));
|
await fs.writeFile(argv.oCharMap, zlib.gzipSync(encode(charMap)));
|
||||||
}
|
|
||||||
|
|
||||||
function unzip(buf) {
|
|
||||||
return JSON.parse(zlib.gunzipSync(buf));
|
|
||||||
}
|
|
||||||
function zip(obj) {
|
|
||||||
return zlib.gzipSync(Buffer.from(JSON.stringify(obj), "utf-8"));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,7 +310,7 @@ class BooleanGeometry extends GeometryBase {
|
||||||
exports.hashGeometry = function (geom) {
|
exports.hashGeometry = function (geom) {
|
||||||
const s = geom.toShapeStringOrNull();
|
const s = geom.toShapeStringOrNull();
|
||||||
if (!s) return null;
|
if (!s) return null;
|
||||||
return crypto.createHash("sha256").update(s).digest();
|
return crypto.createHash("sha256").update(s).digest("hex");
|
||||||
};
|
};
|
||||||
|
|
||||||
function combineWith(a, b) {
|
function combineWith(a, b) {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"@msgpack/msgpack": "^2.6.0",
|
||||||
"@unicode/unicode-13.0.0": "^1.0.4",
|
"@unicode/unicode-13.0.0": "^1.0.4",
|
||||||
"cldr": "^6.0.0",
|
"cldr": "^6.0.0",
|
||||||
"ejs": "^3.1.6",
|
"ejs": "^3.1.6",
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const toml = require("@iarna/toml");
|
const toml = require("@iarna/toml");
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const cldr = require("cldr");
|
const cldr = require("cldr");
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const zlib = require("zlib");
|
const zlib = require("zlib");
|
||||||
|
const { decode } = require("@msgpack/msgpack");
|
||||||
|
|
||||||
const gatherCov = require("./coverage-export/gather-coverage-data");
|
const gatherCov = require("./coverage-export/gather-coverage-data");
|
||||||
|
|
||||||
|
@ -8,9 +11,9 @@ const gatherCov = require("./coverage-export/gather-coverage-data");
|
||||||
const overrideSupportedLanguages = [];
|
const overrideSupportedLanguages = [];
|
||||||
|
|
||||||
module.exports = async function (charMapPath, charMapItalicPath, charMapObliquePath) {
|
module.exports = async function (charMapPath, charMapItalicPath, charMapObliquePath) {
|
||||||
const charMap = await readJsonGz(charMapPath);
|
const charMap = await readMpCharMap(charMapPath);
|
||||||
const charMapItalic = await readJsonGz(charMapItalicPath);
|
const charMapItalic = await readMpCharMap(charMapItalicPath);
|
||||||
const charMapOblique = await readJsonGz(charMapObliquePath);
|
const charMapOblique = await readMpCharMap(charMapObliquePath);
|
||||||
|
|
||||||
const rawCoverage = getRawCoverage(charMap);
|
const rawCoverage = getRawCoverage(charMap);
|
||||||
const rawCoverageItalic = getRawCoverage(charMapItalic);
|
const rawCoverageItalic = getRawCoverage(charMapItalic);
|
||||||
|
@ -26,9 +29,8 @@ module.exports = async function (charMapPath, charMapItalicPath, charMapObliqueP
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
async function readJsonGz(p) {
|
async function readMpCharMap(p) {
|
||||||
const buf = await fs.readFile(p);
|
return decode(zlib.gunzipSync(await fs.readFile(p)));
|
||||||
return JSON.parse(zlib.gunzipSync(buf).toString("utf-8"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSupportedLanguageSet(rawCoverage) {
|
function getSupportedLanguageSet(rawCoverage) {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
|
||||||
module.exports = function (output, family, hs, formats) {
|
module.exports = function (output, family, hs, formats) {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
module.exports = function (main) {
|
module.exports = function (main) {
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() =>
|
() =>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const wawoff = require("wawoff2");
|
const wawoff = require("wawoff2");
|
||||||
|
|
||||||
|
|
|
@ -276,8 +276,9 @@ const DistUnhintedTTF = file.make(
|
||||||
async (target, out, gr, fn) => {
|
async (target, out, gr, fn) => {
|
||||||
await target.need(Scripts, Parameters, Dependencies);
|
await target.need(Scripts, Parameters, Dependencies);
|
||||||
const charMapDir = `${BUILD}/ttf/${gr}`;
|
const charMapDir = `${BUILD}/ttf/${gr}`;
|
||||||
const charMapPath = `${charMapDir}/${fn}.cm.gz`;
|
const charMapPath = `${charMapDir}/${fn}.charmap.mpz`;
|
||||||
const cachePath = `${charMapDir}/${fn}.cache.gz`;
|
const cachePath = `${charMapDir}/${fn}.cache.mpz`;
|
||||||
|
|
||||||
const [fi] = await target.need(FontInfoOf(fn), de(out.dir), de(charMapDir));
|
const [fi] = await target.need(FontInfoOf(fn), de(out.dir), de(charMapDir));
|
||||||
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
|
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
|
||||||
await silently.node("font-src/index", {
|
await silently.node("font-src/index", {
|
||||||
|
@ -290,7 +291,7 @@ const DistUnhintedTTF = file.make(
|
||||||
);
|
);
|
||||||
|
|
||||||
const BuildCM = file.make(
|
const BuildCM = file.make(
|
||||||
(gr, f) => `${BUILD}/ttf/${gr}/${f}.cm.gz`,
|
(gr, f) => `${BUILD}/ttf/${gr}/${f}.charmap.mpz`,
|
||||||
async (target, output, gr, f) => {
|
async (target, output, gr, f) => {
|
||||||
await target.need(DistUnhintedTTF(gr, f));
|
await target.need(DistUnhintedTTF(gr, f));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue