Merge pull request #4072 from overleaf/jpa-pdfjs-metrics

[frontend] PdfController: observe PDF.js fetch/render performance

GitOrigin-RevId: bdd81ba06dabaa944b64266d0c36700d16790a30
This commit is contained in:
Jakob Ackermann
2021-05-21 13:31:47 +02:00
committed by Copybot
parent 9ad248af41
commit dfabc3a93b
5 changed files with 87 additions and 1 deletions

View File

@@ -281,6 +281,8 @@ div.full-size.pdf(ng-controller="PdfController")
resize-on="layout:main:resize,layout:pdf:resize"
highlights="pdf.highlights"
position="pdf.position"
first-render-done="pdf.firstRenderDone"
update-consumed-bandwidth="pdf.updateConsumedBandwidth"
dbl-click-callback="syncToCode"
)
iframe(

View File

@@ -338,6 +338,8 @@ App.controller(
}
}
function noop() {}
function parseCompileResponse(response) {
// keep last url
const lastPdfUrl = $scope.pdf.url
@@ -347,6 +349,8 @@ App.controller(
$scope.pdf.timedout = false
$scope.pdf.failure = false
$scope.pdf.url = null
$scope.pdf.updateConsumedBandwidth = noop
$scope.pdf.firstRenderDone = noop
$scope.pdf.clsiMaintenance = false
$scope.pdf.tooRecentlyCompiled = false
$scope.pdf.renderingError = false
@@ -396,6 +400,26 @@ App.controller(
// convert the qs hash into a query string and append it
$scope.pdf.url += createQueryString(qs)
const {
onFirstRenderDone,
firstRenderDone,
updateConsumedBandwidth,
} = trackPDFDownload()
$scope.pdf.firstRenderDone = firstRenderDone
$scope.pdf.updateConsumedBandwidth = updateConsumedBandwidth
const { serviceWorkerMetrics } = response
onFirstRenderDone.then(({ latencyFetch, latencyRender }) => {
sl_console.log(
JSON.stringify({
latencyFetch,
latencyRender,
totalBandwidthReportedByPdfJs,
serviceWorkerMetrics,
})
)
})
// Save all downloads as files
qs.popupDownload = true
@@ -543,6 +567,33 @@ App.controller(
)
}
let totalBandwidthReportedByPdfJs = 0
function trackPDFDownload() {
const t0 = performance.now()
let bandwidth = 0
function firstRenderDone({ timePDFFetched, timePDFRendered }) {
const latencyFetch = timePDFFetched - t0
// The renderer does not yield in case the browser tab is hidden.
// It will yield when the browser tab is visible again.
// This will skew our performance metrics for rendering!
const latencyRender = timePDFRendered - t0
done({ latencyFetch, latencyRender })
}
function updateConsumedBandwidth(bytes) {
totalBandwidthReportedByPdfJs += bytes - bandwidth
bandwidth = bytes
}
let done
const onFirstRenderDone = new Promise(resolve => {
done = resolve
})
return {
onFirstRenderDone,
firstRenderDone,
updateConsumedBandwidth,
}
}
function fetchLogs(fileByPath, options) {
let blgFile, chktexFile, logFile

View File

@@ -21,6 +21,8 @@ export default App.directive('pdfng', ($timeout, localStorage) => ({
highlights: '=',
position: '=',
dblClickCallback: '=',
firstRenderDone: '=',
updateConsumedBandwidth: '=',
},
link(scope, element, attrs) {
scope.loading = false
@@ -150,7 +152,18 @@ export default App.directive('pdfng', ($timeout, localStorage) => ({
// console.log 'pdfjs destroy event'
template: `\
<div data-pdf-viewer class="pdfjs-viewer" pdf-src='pdfSrc' position='position' scale='scale' highlights='highlights' please-jump-to='pleaseJumpTo'></div>
<div
data-pdf-viewer
class="pdfjs-viewer"
pdf-src='pdfSrc'
position='position'
scale='scale'
highlights='highlights'
please-jump-to='pleaseJumpTo'
first-render-done="firstRenderDone"
update-consumed-bandwidth="updateConsumedBandwidth"
>
</div>
<div class="pdfjs-controls" ng-class="{'flash': flashControls }">
<div class="btn-group">
<a href

View File

@@ -362,9 +362,20 @@ export default App.factory(
if (loadTask.cancelled) {
return
} // return from cancelled page load
const timePDFFetched = performance.now()
pageState.renderTask = this.doRender(element, pagenum, pageObject)
return pageState.renderTask.promise.then(
() => {
if (typeof this.options.firstRenderDone === 'function') {
const timePDFRendered = performance.now()
this.options.firstRenderDone({
timePDFFetched,
timePDFRendered,
})
// The rendering pipeline is processed repeatedly, skip the next ones.
this.options.firstRenderDone = null
}
// render task success
this.clearIndicator(page)
pageState.complete = true

View File

@@ -52,6 +52,11 @@ App.controller(
// add 'pdfng=true' to show that we are using the angular pdfjs viewer
const queryStringExists = /\?/.test(url)
url = url + (!queryStringExists ? '?' : '&') + 'pdfng=true'
// Take references as these must be invoked for this very URL
const firstRenderDone = $scope.firstRenderDone
const updateConsumedBandwidth = $scope.updateConsumedBandwidth
// for isolated compiles, load the pdf on-demand because nobody will overwrite it
const onDemandLoading = true
$scope.document = new PDFRenderer(url, {
@@ -63,11 +68,13 @@ App.controller(
return $scope.$apply()
},
progressCallback(progress) {
updateConsumedBandwidth(progress.loaded)
return $scope.$emit('progress', progress)
},
loadedCallback() {
return $scope.$emit('loaded')
},
firstRenderDone,
errorCallback(error) {
// MissingPDFException is "expected" as the pdf file can be on a
// CLSI server that has been cycled out.
@@ -324,6 +331,8 @@ export default App.directive('pdfViewer', ($q, $timeout, pdfSpinner) => ({
controllerAs: 'ctrl',
scope: {
pdfSrc: '=',
firstRenderDone: '=',
updateConsumedBandwidth: '=',
highlights: '=',
position: '=',
scale: '=',