Răsfoiți Sursa

Remove CM6 performance measurement (#22663)

GitOrigin-RevId: 2178f2b66c200005517ed8ff52afadd8b5fda14b
Alf Eaton 1 an în urmă
părinte
comite
4351805f7c

+ 1 - 16
services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts

@@ -1,7 +1,6 @@
 import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
 import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
 import { EditorType } from '@/features/ide-react/editor/types/editor-type'
-import { reportCM6Perf } from '@/infrastructure/cm6-performance'
 import { putJSON } from '@/infrastructure/fetch-json'
 import { debugConsole } from '@/utils/debugging'
 import moment from 'moment'
@@ -10,23 +9,9 @@ import useEventListener from '@/shared/hooks/use-event-listener'
 import useDomEventListener from '@/shared/hooks/use-dom-event-listener'
 
 function createEditingSessionHeartbeatData(editorType: EditorType) {
-  const segmentation: Record<string, unknown> = {
+  return {
     editorType,
   }
-  const cm6PerfData = reportCM6Perf()
-
-  // Ignore if no typing has happened
-  if (cm6PerfData.numberOfEntries > 0) {
-    for (const [key, value] of Object.entries(cm6PerfData)) {
-      const segmentationPropName =
-        'cm6Perf' + key.charAt(0).toUpperCase() + key.slice(1)
-      if (value !== null) {
-        segmentation[segmentationPropName] = value
-      }
-    }
-  }
-
-  return segmentation
 }
 
 function sendEditingSessionHeartbeat(

+ 0 - 5
services/web/frontend/js/features/source-editor/components/codemirror-editor.tsx

@@ -7,7 +7,6 @@ import CodeMirrorSearch from './codemirror-search'
 import { CodeMirrorToolbar } from './codemirror-toolbar'
 import { CodemirrorOutline } from './codemirror-outline'
 import { CodeMirrorCommandTooltip } from './codemirror-command-tooltip'
-import { dispatchTimer } from '../../../infrastructure/cm6-performance'
 import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
 import { FigureModal } from './figure-modal/figure-modal'
 import { ReviewPanelProviders } from '@/features/review-panel-new/context/review-panel-providers'
@@ -45,20 +44,16 @@ function CodeMirrorEditor() {
   // create the view using the initial state and intercept transactions
   const viewRef = useRef<EditorView | null>(null)
   if (viewRef.current === null) {
-    const timer = dispatchTimer()
-
     // @ts-ignore (disable EditContext-based editing until stable)
     EditorView.EDIT_CONTEXT = false
 
     const view = new EditorView({
       state,
       dispatchTransactions: trs => {
-        timer.start(trs)
         view.update(trs)
         if (isMounted.current) {
           setState(view.state)
         }
-        timer.end(trs, view)
       },
     })
     viewRef.current = view

+ 0 - 331
services/web/frontend/js/infrastructure/cm6-performance.ts

@@ -1,331 +0,0 @@
-import { Transaction } from '@codemirror/state'
-import { EditorView } from '@codemirror/view'
-import { round } from 'lodash'
-import grammarlyExtensionPresent from '../shared/utils/grammarly'
-import getMeta from '../utils/meta'
-import { debugConsole } from '@/utils/debugging'
-
-const TIMER_START_NAME = 'CM6-BeforeUpdate'
-const TIMER_END_NAME = 'CM6-AfterUpdate'
-const TIMER_DOM_UPDATE_NAME = 'CM6-DomUpdate'
-const TIMER_MEASURE_NAME = 'CM6-Update'
-const TIMER_KEYPRESS_MEASURE_NAME = 'CM6-Keypress-Measure'
-
-let latestDocLength = 0
-const sessionStart = Date.now()
-
-let performanceOptionsSupport = false
-
-// Check that performance.mark and performance.measure accept an options object
-try {
-  const testMarkName = 'featureTestMark'
-  performance.mark(testMarkName, {
-    startTime: performance.now(),
-    detail: { test: 1 },
-  })
-  performance.clearMarks(testMarkName)
-
-  const testMeasureName = 'featureTestMeasure'
-  performance.measure(testMeasureName, {
-    start: performance.now(),
-    detail: { test: 1 },
-  })
-  performance.clearMeasures(testMeasureName)
-
-  performanceOptionsSupport = true
-} catch (e) {}
-
-let performanceMemorySupport = false
-
-function measureMemoryUsage() {
-  // @ts-ignore
-  return performance.memory.usedJSHeapSize
-}
-
-try {
-  if ('memory' in window.performance) {
-    measureMemoryUsage()
-    performanceMemorySupport = true
-  }
-} catch (e) {}
-
-let performanceLongtaskSupported = false
-let longTaskSinceLastReportCount = 0
-
-// Detect support for long task monitoring
-try {
-  if (PerformanceObserver.supportedEntryTypes.includes('longtask')) {
-    performanceLongtaskSupported = true
-
-    // Register observer for long task notifications
-    const observer = new PerformanceObserver(list => {
-      longTaskSinceLastReportCount += list.getEntries().length
-    })
-    observer.observe({ entryTypes: ['longtask'] })
-  }
-} catch (e) {}
-
-function isInputOrDelete(userEventType: string | undefined) {
-  return (
-    !!userEventType && ['input', 'delete'].includes(userEventType.split('.')[0])
-  )
-}
-
-// "keypress" is not strictly accurate; what we really mean is a user-initiated
-// event that either inserts or deletes exactly one character. This corresponds
-// to CM6 user event types input.type, delete.forward or delete.backward
-function isKeypress(userEventType: string | undefined) {
-  return (
-    !!userEventType &&
-    ['input.type', 'delete.forward', 'delete.backward'].includes(userEventType)
-  )
-}
-
-export function dispatchTimer(): {
-  start: (trs: readonly Transaction[]) => void
-  end: (trs: readonly Transaction[], view: EditorView) => void
-} {
-  if (!performanceOptionsSupport) {
-    return { start: () => {}, end: () => {} }
-  }
-
-  let userEventsSinceDomUpdateCount = 0
-  let keypressesSinceDomUpdateCount = 0
-  const unpaintedKeypressStartTimes: number[] = []
-
-  const start = (trs: readonly Transaction[]) => {
-    const keypressStart = performance.now()
-
-    trs.forEach(tr => {
-      const userEventType = tr.annotation(Transaction.userEvent)
-
-      if (isKeypress(userEventType)) {
-        unpaintedKeypressStartTimes.push(keypressStart)
-      }
-    })
-
-    performance.mark(TIMER_START_NAME)
-  }
-
-  const end = (trs: readonly Transaction[], view: EditorView) => {
-    performance.mark(TIMER_END_NAME)
-
-    let anyInputOrDelete = false
-
-    trs.forEach(tr => {
-      const userEventType = tr.annotation(Transaction.userEvent)
-
-      if (isInputOrDelete(userEventType)) {
-        anyInputOrDelete = true
-        ++userEventsSinceDomUpdateCount
-
-        if (isKeypress(userEventType)) {
-          ++keypressesSinceDomUpdateCount
-        }
-
-        performance.measure(TIMER_MEASURE_NAME, {
-          start: TIMER_START_NAME,
-          end: TIMER_END_NAME,
-          detail: { userEventType, userEventsSinceDomUpdateCount },
-        })
-      }
-    })
-
-    if (anyInputOrDelete) {
-      // The `key` property ensures that the measurement task is only run once
-      // per measure phase
-      view.requestMeasure({
-        key: 'inputEventCounter',
-        read() {
-          performance.mark(TIMER_DOM_UPDATE_NAME, {
-            detail: { keypressesSinceDomUpdateCount },
-          })
-          userEventsSinceDomUpdateCount = 0
-          keypressesSinceDomUpdateCount = 0
-
-          const keypressEnd = performance.now()
-
-          for (const keypressStart of unpaintedKeypressStartTimes) {
-            performance.measure(TIMER_KEYPRESS_MEASURE_NAME, {
-              start: keypressStart,
-              end: keypressEnd,
-            })
-          }
-          unpaintedKeypressStartTimes.length = 0
-        },
-      })
-    }
-
-    latestDocLength = trs[trs.length - 1].state.doc.length
-  }
-
-  return { start, end }
-}
-
-function calculateMean(durations: number[]) {
-  if (durations.length === 0) return 0
-
-  const sum = durations.reduce((acc, entry) => acc + entry, 0)
-  return sum / durations.length
-}
-
-function calculateMedian(sortedDurations: number[]) {
-  if (sortedDurations.length === 0) return 0
-
-  const middle = Math.floor(sortedDurations.length / 2)
-
-  if (sortedDurations.length % 2 === 0) {
-    return (sortedDurations[middle - 1] + sortedDurations[middle]) / 2
-  }
-  return sortedDurations[middle]
-}
-
-function calculate95thPercentile(sortedDurations: number[]) {
-  if (sortedDurations.length === 0) return 0
-
-  const index = Math.round((sortedDurations.length - 1) * 0.95)
-  return sortedDurations[index]
-}
-
-function calculateMax(numbers: number[]) {
-  return numbers.reduce((a, b) => Math.max(a, b), 0)
-}
-
-function clearCM6Perf(type: string) {
-  switch (type) {
-    case 'measure':
-      performance.clearMeasures(TIMER_MEASURE_NAME)
-      performance.clearMarks(TIMER_START_NAME)
-      performance.clearMarks(TIMER_END_NAME)
-      break
-
-    case 'dom':
-      performance.clearMarks(TIMER_DOM_UPDATE_NAME)
-      break
-
-    case 'keypress':
-      performance.clearMeasures(TIMER_KEYPRESS_MEASURE_NAME)
-      break
-  }
-}
-
-// clear performance measures and marks when switching between Source and Rich Text
-window.addEventListener('editor:visual-switch', () => {
-  clearCM6Perf('measure')
-  clearCM6Perf('dom')
-  clearCM6Perf('keypress')
-})
-
-export function reportCM6Perf() {
-  // Get entries triggered by keystrokes
-  const cm6Entries = performance.getEntriesByName(
-    TIMER_MEASURE_NAME,
-    'measure'
-  ) as PerformanceMeasure[]
-
-  clearCM6Perf('measure')
-
-  const inputEvents = cm6Entries.filter(({ detail }) =>
-    isInputOrDelete(detail.userEventType)
-  )
-
-  const inputDurations = inputEvents
-    .map(({ duration }) => duration)
-    .sort((a, b) => a - b)
-
-  const max = round(calculateMax(inputDurations), 2)
-  const mean = round(calculateMean(inputDurations), 2)
-  const median = round(calculateMedian(inputDurations), 2)
-  const ninetyFifthPercentile = round(
-    calculate95thPercentile(inputDurations),
-    2
-  )
-  const maxUserEventsBetweenDomUpdates = calculateMax(
-    inputEvents.map(e => e.detail.userEventsSinceDomUpdateCount)
-  )
-  const grammarly = grammarlyExtensionPresent()
-  const sessionLength = Math.floor((Date.now() - sessionStart) / 1000) // In seconds
-
-  const memory = performanceMemorySupport ? measureMemoryUsage() : null
-
-  // Get entries for keypress counts between DOM updates
-  const domUpdateEntries = performance.getEntriesByName(
-    TIMER_DOM_UPDATE_NAME,
-    'mark'
-  ) as PerformanceMark[]
-
-  clearCM6Perf('dom')
-
-  let lags = 0
-  let nonLags = 0
-  let longestLag = 0
-  let totalKeypressCount = 0
-
-  for (const entry of domUpdateEntries) {
-    const keypressCount = entry.detail.keypressesSinceDomUpdateCount
-    if (keypressCount === 1) {
-      ++nonLags
-    } else if (keypressCount > 1) {
-      ++lags
-    }
-    if (keypressCount > longestLag) {
-      longestLag = keypressCount
-    }
-    totalKeypressCount += keypressCount
-  }
-
-  const meanLagsPerMeasure = round(lags / (lags + nonLags), 4)
-  const meanKeypressesPerMeasure = round(
-    totalKeypressCount / (lags + nonLags),
-    4
-  )
-
-  // Get entries triggered by keystrokes
-  const keypressPaintEntries = performance.getEntriesByName(
-    TIMER_KEYPRESS_MEASURE_NAME,
-    'measure'
-  ) as PerformanceMeasure[]
-
-  const keypressPaintDurations = keypressPaintEntries.map(
-    ({ duration }) => duration
-  )
-
-  const meanKeypressPaint = round(calculateMean(keypressPaintDurations), 2)
-
-  clearCM6Perf('keypress')
-
-  let longTasks = null
-
-  // Get long task entries (Chromium-based browsers only at time of writing)
-  if (performanceLongtaskSupported) {
-    longTasks = longTaskSinceLastReportCount
-    longTaskSinceLastReportCount = 0
-  }
-
-  const release = getMeta('ol-ExposedSettings')?.sentryRelease || null
-
-  return {
-    max,
-    mean,
-    median,
-    ninetyFifthPercentile,
-    maxUserEventsBetweenDomUpdates,
-    docLength: latestDocLength,
-    numberOfEntries: inputDurations.length,
-    grammarly,
-    sessionLength,
-    memory,
-    lags,
-    nonLags,
-    longestLag,
-    meanLagsPerMeasure,
-    meanKeypressesPerMeasure,
-    meanKeypressPaint,
-    longTasks,
-    release,
-  }
-}
-
-window._reportCM6Perf = () => {
-  debugConsole.warn(reportCM6Perf())
-}

+ 0 - 1
services/web/types/window.ts

@@ -17,7 +17,6 @@ declare global {
         removeListener: (event: string, listener: any) => void
       }
     }
-    _reportCM6Perf: () => void
     MathJax: Record<string, any>
     crypto: {
       randomUUID: () => string