mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Merge pull request #28880 from overleaf/bg-add-time-option-to-clsi
add latexmk `-time` option to clsi and record performance logs GitOrigin-RevId: 467473859359913da73f83e10b63b45603ea175c
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const MODULE_PATH = require('node:path').join(
|
||||
__dirname,
|
||||
@@ -87,6 +89,7 @@ describe('LatexRunner', function () {
|
||||
'-outdir=$COMPILE_DIR',
|
||||
'-synctex=1',
|
||||
'-interaction=batchmode',
|
||||
'-time',
|
||||
'-f',
|
||||
'-pdf',
|
||||
'$COMPILE_DIR/main-file.tex',
|
||||
@@ -140,6 +143,7 @@ describe('LatexRunner', function () {
|
||||
'-outdir=$COMPILE_DIR',
|
||||
'-synctex=1',
|
||||
'-interaction=batchmode',
|
||||
'-time',
|
||||
'-f',
|
||||
'-lualatex',
|
||||
'$COMPILE_DIR/main-file.tex',
|
||||
@@ -209,11 +213,75 @@ describe('LatexRunner', function () {
|
||||
'-outdir=$COMPILE_DIR',
|
||||
'-synctex=1',
|
||||
'-interaction=batchmode',
|
||||
'-time',
|
||||
'-halt-on-error',
|
||||
'-pdf',
|
||||
'$COMPILE_DIR/main-file.tex',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('with old latexmk timing output', function () {
|
||||
beforeEach(function (done) {
|
||||
this.commandRunnerOutput.stdout = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'latexmk1.txt'),
|
||||
'utf-8'
|
||||
)
|
||||
// pass in the `latexmk` property to signal that we want to receive parsed stats
|
||||
this.stats.latexmk = {}
|
||||
this.call(done)
|
||||
})
|
||||
|
||||
it('should parse latexmk 4.52c (2017) timing information', function () {
|
||||
expect(this.stats.latexmk).to.deep.equal({
|
||||
'latexmk-rule-times': [
|
||||
{ rule: 'makeindex', time_ms: 30 },
|
||||
{ rule: 'bibtex', time_ms: 40 },
|
||||
{ rule: 'latex', time_ms: 690 },
|
||||
{ rule: 'makeindex', time_ms: 40 },
|
||||
{ rule: 'bibtex', time_ms: 39 },
|
||||
{ rule: 'latex', time_ms: 750 },
|
||||
{ rule: 'makeindex', time_ms: 39 },
|
||||
{ rule: 'bibtex', time_ms: 20 },
|
||||
{ rule: 'latex', time_ms: 770 },
|
||||
],
|
||||
'latexmk-rule-signature':
|
||||
'makeindex,bibtex,latex,makeindex,bibtex,latex,makeindex,bibtex,latex',
|
||||
'latexmk-rules-run': 9,
|
||||
'latexmk-time': { total: 2930 },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with modern latexmk timing output', function () {
|
||||
beforeEach(function (done) {
|
||||
this.commandRunnerOutput.stdout = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'latexmk2.txt'),
|
||||
'utf-8'
|
||||
)
|
||||
// pass in the `latexmk` property to signal that we want to receive parsed stats
|
||||
this.stats.latexmk = {}
|
||||
this.call(done)
|
||||
})
|
||||
|
||||
it('should parse latexmk 4.83 (2024) timing information', function () {
|
||||
expect(this.stats.latexmk).to.deep.equal({
|
||||
'latexmk-rule-times': [
|
||||
{ rule: 'latex', time_ms: 1880 },
|
||||
{ rule: 'makeindex', time_ms: 50 },
|
||||
{ rule: 'bibtex', time_ms: 50 },
|
||||
{ rule: 'latex', time_ms: 2180 },
|
||||
],
|
||||
'latexmk-rule-signature': 'latex,makeindex,bibtex,latex',
|
||||
'latexmk-time': {
|
||||
total: 4770,
|
||||
invoked: 4160,
|
||||
other: 610,
|
||||
},
|
||||
'latexmk-clock-time': 4870,
|
||||
'latexmk-rules-run': 4,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
const { expect } = require('chai')
|
||||
const { sampleByHash } = require('../../../app/js/StatsManager')
|
||||
|
||||
describe('StatsManager', function () {
|
||||
describe('sampleByHash', function () {
|
||||
it('should always return false for a sample percentage of 0', function () {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const key = `test-key-${i}`
|
||||
expect(sampleByHash(key, 0), `key ${key} should be false`).to.be.false
|
||||
}
|
||||
})
|
||||
|
||||
it('should always return false for a negative sample percentage', function () {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const key = `test-key-${i}`
|
||||
expect(sampleByHash(key, -10), `key ${key} should be false`).to.be.false
|
||||
}
|
||||
})
|
||||
|
||||
it('should always return true for a sample percentage of 100', function () {
|
||||
// This isn't strictly true, if the hash is exactly 0xffffffff, then the percentile is 100
|
||||
// and 100 < 100 is false. But the chances of that are 1 in 4 billion.
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const key = `test-key-${i}`
|
||||
expect(sampleByHash(key, 100), `key ${key} should be true`).to.be.true
|
||||
}
|
||||
})
|
||||
|
||||
it('should return the expected number of results for a sample percentage of 75', function () {
|
||||
// This isn't strictly true, if the hash is exactly 0xffffffff, then the percentile is 100
|
||||
// and 100 < 100 is false. But the chances of that are 1 in 4 billion.
|
||||
let count = 0
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const key = `test-key-${i}`
|
||||
count += sampleByHash(key, 75) ? 1 : 0
|
||||
}
|
||||
// Actual result is 74, it's deterministic but the test allows the algorithm to change
|
||||
expect(count).to.be.within(70, 80)
|
||||
})
|
||||
|
||||
it('should return true when the hash is within the sample percentage', function () {
|
||||
// The MD5 hash of 'test-key-in' gives a percentile of 13
|
||||
const key = 'test-key-in'
|
||||
const percentage = 40
|
||||
expect(sampleByHash(key, percentage)).to.be.true
|
||||
})
|
||||
|
||||
it('should return false when the hash is outside the sample percentage', function () {
|
||||
// The MD5 hash of 'test-key-outer' gives a percentile of 47
|
||||
const key = 'test-key-outer'
|
||||
const percentage = 40
|
||||
expect(sampleByHash(key, percentage)).to.be.false
|
||||
})
|
||||
|
||||
it('should produce consistent results for the same key', function () {
|
||||
const key = 'consistent-key'
|
||||
const percentage = 50
|
||||
const result1 = sampleByHash(key, percentage)
|
||||
const result2 = sampleByHash(key, percentage)
|
||||
expect(result1).to.equal(result2)
|
||||
})
|
||||
|
||||
it('should handle different keys correctly', function () {
|
||||
// MD5('key1') => percentile 76
|
||||
// MD5('key2') => percentile 47
|
||||
expect(sampleByHash('key1', 80)).to.be.true
|
||||
expect(sampleByHash('key1', 70)).to.be.false
|
||||
expect(sampleByHash('key2', 50)).to.be.true
|
||||
expect(sampleByHash('key2', 40)).to.be.false
|
||||
})
|
||||
|
||||
it('should be monotonic with respect to percentage', function () {
|
||||
const key = 'test-key'
|
||||
const percentile = 32
|
||||
for (let i = 0; i <= 100; i++) {
|
||||
const result = sampleByHash(key, i)
|
||||
if (i <= percentile) {
|
||||
expect(result, `percentage ${i} should be false`).to.be.false
|
||||
} else {
|
||||
expect(result, `percentage ${i} should be true`).to.be.true
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
Latexmk: Found bibliography file(s) [tex.bib]
|
||||
Latexmk: All targets (TeXbyTopic.dvi) are up-to-date
|
||||
'makeindex -o "TeXbyTopic.ind" "TeXbyTopic.idx"': time = 0.03
|
||||
'bibtex "TeXbyTopic"': time = 0.04
|
||||
'latex -recorder "TeXbyTopic.tex"': time = 0.69
|
||||
'makeindex -o "TeXbyTopic.ind" "TeXbyTopic.idx"': time = 0.04
|
||||
'bibtex "TeXbyTopic"': time = 0.0399999999999998
|
||||
'latex -recorder "TeXbyTopic.tex"': time = 0.75
|
||||
'makeindex -o "TeXbyTopic.ind" "TeXbyTopic.idx"': time = 0.0399999999999996
|
||||
'bibtex "TeXbyTopic"': time = 0.02
|
||||
'latex -recorder "TeXbyTopic.tex"': time = 0.77
|
||||
Accumulated processing time = 2.93
|
||||
@@ -0,0 +1,7 @@
|
||||
'latex': time = 1.88
|
||||
'makeindex TeXbyTopic.idx': time = 0.05
|
||||
'bibtex TeXbyTopic': time = 0.05
|
||||
'latex': time = 2.18
|
||||
Processing time = 4.77, of which invoked processes = 4.16, other = 0.61.
|
||||
Elapsed clock time = 4.87.
|
||||
Number of rules run = 4
|
||||
Reference in New Issue
Block a user