UBERF-9501: Fix use of Date.now() (#8069)
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / uitest-workspaces (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions

This commit is contained in:
Andrey Sobolev 2025-02-21 19:46:13 +07:00 committed by GitHub
parent 4429d33c68
commit 3673078b11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 150 additions and 126 deletions

View File

@ -31,7 +31,9 @@ import core, {
type Ref, type Ref,
type WorkspaceUuid, type WorkspaceUuid,
SocialIdType, SocialIdType,
type PersonUuid type PersonUuid,
platformNow,
platformNowDiff
} from '@hcengineering/core' } from '@hcengineering/core'
import { generateToken } from '@hcengineering/server-token' import { generateToken } from '@hcengineering/server-token'
import { connect } from '@hcengineering/server-tool' import { connect } from '@hcengineering/server-tool'
@ -214,7 +216,7 @@ export async function benchmark (
let timer: any let timer: any
if (isMainThread && monitorConnection !== undefined) { if (isMainThread && monitorConnection !== undefined) {
timer = setInterval(() => { timer = setInterval(() => {
const st = Date.now() const st = platformNow()
try { try {
const fetchUrl = endpoint.replace('ws:/', 'http:/') + '/api/v1/statistics?token=' + token const fetchUrl = endpoint.replace('ws:/', 'http:/') + '/api/v1/statistics?token=' + token
@ -269,7 +271,7 @@ export async function benchmark (
} }
}) })
.then((res) => { .then((res) => {
const cur = Date.now() - st const cur = platformNow() - st
opTime += cur opTime += cur
moment = cur moment = cur
ops++ ops++
@ -518,7 +520,7 @@ export async function testFindAll (endpoint: string, workspace: WorkspaceUuid, a
const connection = await connect(endpoint, workspace, account) const connection = await connect(endpoint, workspace, account)
try { try {
const client = new TxOperations(connection, core.account.System) const client = new TxOperations(connection, core.account.System)
const start = Date.now() const start = platformNow()
const res = await client.findAll( const res = await client.findAll(
recruit.class.Applicant, recruit.class.Applicant,
{}, {},
@ -529,7 +531,7 @@ export async function testFindAll (endpoint: string, workspace: WorkspaceUuid, a
} }
} }
) )
console.log('Find all', res.length, 'time', Date.now() - start) console.log('Find all', res.length, 'time', platformNow() - start)
} finally { } finally {
await connection.close() await connection.close()
} }
@ -550,7 +552,7 @@ export async function generateWorkspaceData (
throw new Error('User not found') throw new Error('User not found')
} }
const employees: PersonId[] = [emailSocialString] const employees: PersonId[] = [emailSocialString]
const start = Date.now() const start = platformNow()
for (let i = 0; i < 100; i++) { for (let i = 0; i < 100; i++) {
const socialString = await generateEmployee(client) const socialString = await generateEmployee(client)
employees.push(socialString) employees.push(socialString)
@ -566,7 +568,7 @@ export async function generateWorkspaceData (
await generateVacancy(client, employees) await generateVacancy(client, employees)
} }
} }
console.log('Generate', Date.now() - start) console.log('Generate', platformNowDiff(start))
} finally { } finally {
await connection.close() await connection.close()
} }

View File

@ -58,7 +58,9 @@ import core, {
generateId, generateId,
getObjectValue, getObjectValue,
toIdMap, toIdMap,
updateAttribute updateAttribute,
platformNow,
platformNowDiff
} from '@hcengineering/core' } from '@hcengineering/core'
import activity, { DOMAIN_ACTIVITY } from '@hcengineering/model-activity' import activity, { DOMAIN_ACTIVITY } from '@hcengineering/model-activity'
import { DOMAIN_SPACE } from '@hcengineering/model-core' import { DOMAIN_SPACE } from '@hcengineering/model-core'
@ -104,11 +106,10 @@ export async function cleanWorkspace (
for (const c of part) { for (const c of part) {
await op.remove(c) await op.remove(c)
} }
const t = Date.now() const t = platformNow()
console.log('remove:', part.map((it) => it.name).join(', ')) console.log('remove:', part.map((it) => it.name).join(', '))
await op.commit() await op.commit()
const t2 = Date.now() console.log('remove time:', platformNowDiff(t), filter.length)
console.log('remove time:', t2 - t, filter.length)
} }
} }
@ -122,10 +123,9 @@ export async function cleanWorkspace (
for (const c of part) { for (const c of part) {
await op.remove(c) await op.remove(c)
} }
const t = Date.now() const t = platformNow()
await op.commit() await op.commit()
const t2 = Date.now() console.log('remove time:', platformNowDiff(t), issues.length)
console.log('remove time:', t2 - t, issues.length)
} }
} }

View File

@ -23,7 +23,7 @@ import { ModelDb } from './memdb'
import type { DocumentQuery, FindOptions, FindResult, FulltextStorage, Storage, TxResult, WithLookup } from './storage' import type { DocumentQuery, FindOptions, FindResult, FulltextStorage, Storage, TxResult, WithLookup } from './storage'
import { SearchOptions, SearchQuery, SearchResult } from './storage' import { SearchOptions, SearchQuery, SearchResult } from './storage'
import { Tx, TxCUD, WorkspaceEvent, type TxWorkspaceEvent } from './tx' import { Tx, TxCUD, WorkspaceEvent, type TxWorkspaceEvent } from './tx'
import { toFindResult } from './utils' import { platformNow, platformNowDiff, toFindResult } from './utils'
/** /**
* @public * @public
@ -345,7 +345,7 @@ async function loadModel (
conn: ClientConnection, conn: ClientConnection,
persistence?: TxPersistenceStore persistence?: TxPersistenceStore
): Promise<{ mode: 'same' | 'addition' | 'upgrade', current: Tx[], addition: Tx[] }> { ): Promise<{ mode: 'same' | 'addition' | 'upgrade', current: Tx[], addition: Tx[] }> {
const t = Date.now() const t = platformNow()
const current = (await ctx.with('persistence-load', {}, () => persistence?.load())) ?? { const current = (await ctx.with('persistence-load', {}, () => persistence?.load())) ?? {
full: true, full: true,
@ -385,7 +385,7 @@ async function loadModel (
}) })
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
console.log('find' + (result.full ? 'full model' : 'model diff'), result.transactions.length, Date.now() - t) console.log('find' + (result.full ? 'full model' : 'model diff'), result.transactions.length, platformNowDiff(t))
} }
if (result.full) { if (result.full) {
return { mode: 'upgrade', current: result.transactions, addition: [] } return { mode: 'upgrade', current: result.transactions, addition: [] }

View File

@ -1,6 +1,6 @@
// Basic performance metrics suite. // Basic performance metrics suite.
import { generateId } from '../utils' import { generateId, platformNow, platformNowDiff } from '../utils'
import { childMetrics, newMetrics, updateMeasure } from './metrics' import { childMetrics, newMetrics, updateMeasure } from './metrics'
import { import {
FullParamsType, FullParamsType,
@ -61,7 +61,7 @@ export class MeasureMetricsContext implements MeasureContext {
metrics: Metrics metrics: Metrics
id?: string id?: string
st = Date.now() st = platformNow()
contextData: object = {} contextData: object = {}
private done (value?: number, override?: boolean): void { private done (value?: number, override?: boolean): void {
updateMeasure(this.metrics, this.st, this.params, this.fullParams, (spend) => {}, value, override) updateMeasure(this.metrics, this.st, this.params, this.fullParams, (spend) => {}, value, override)
@ -166,10 +166,10 @@ export class MeasureMetricsContext implements MeasureContext {
op: (ctx: MeasureContext) => T | Promise<T>, op: (ctx: MeasureContext) => T | Promise<T>,
fullParams?: ParamsType fullParams?: ParamsType
): Promise<T> { ): Promise<T> {
const st = Date.now() const st = platformNow()
const r = this.with(name, params, op, fullParams) const r = this.with(name, params, op, fullParams)
void r.finally(() => { void r.finally(() => {
this.logger.logOperation(name, Date.now() - st, { ...params, ...fullParams }) this.logger.logOperation(name, platformNowDiff(st), { ...params, ...fullParams })
}) })
return r return r
} }
@ -284,7 +284,7 @@ export function registerOperationLog (ctx: MeasureContext): { opLogMetrics?: Met
if (!operationProfiling) { if (!operationProfiling) {
return {} return {}
} }
const op: OperationLog = { start: Date.now(), ops: [], end: -1 } const op: OperationLog = { start: platformNow(), ops: [], end: -1 }
let opLogMetrics: Metrics | undefined let opLogMetrics: Metrics | undefined
if (ctx.id === undefined) { if (ctx.id === undefined) {
@ -305,7 +305,7 @@ export function updateOperationLog (opLogMetrics: Metrics | undefined, op: Opera
return return
} }
if (op !== undefined) { if (op !== undefined) {
op.end = Date.now() op.end = platformNow()
} }
// We should keep only longest one entry // We should keep only longest one entry
if (opLogMetrics?.opLog !== undefined) { if (opLogMetrics?.opLog !== undefined) {
@ -352,7 +352,7 @@ export function addOperation<T> (
if (opLog !== undefined) { if (opLog !== undefined) {
opEntry = { opEntry = {
op: name, op: name,
start: Date.now(), start: performance.now(),
params: {}, params: {},
end: -1 end: -1
} }
@ -361,7 +361,7 @@ export function addOperation<T> (
if (opEntry !== undefined && opLog !== undefined) { if (opEntry !== undefined && opLog !== undefined) {
void result.finally(() => { void result.finally(() => {
if (opEntry !== undefined && opLog !== undefined) { if (opEntry !== undefined && opLog !== undefined) {
opEntry.end = Date.now() opEntry.end = performance.now()
opEntry.params = { ...params, ...(typeof fullParams === 'function' ? fullParams() : fullParams) } opEntry.params = { ...params, ...(typeof fullParams === 'function' ? fullParams() : fullParams) }
opLog.ops.push(opEntry) opLog.ops.push(opEntry)
} }

View File

@ -1,6 +1,7 @@
// Basic performance metrics suite. // Basic performance metrics suite.
import { MetricsData } from '.' import { MetricsData } from '.'
import { platformNow } from '../utils'
import { FullParamsType, Metrics, ParamsType } from './types' import { FullParamsType, Metrics, ParamsType } from './types'
/** /**
@ -65,7 +66,7 @@ export function measure (
fullParams: FullParamsType | (() => FullParamsType) = {}, fullParams: FullParamsType | (() => FullParamsType) = {},
endOp?: (spend: number) => void endOp?: (spend: number) => void
): () => void { ): () => void {
const st = Date.now() const st = platformNow()
return () => { return () => {
updateMeasure(metrics, st, params, fullParams, endOp) updateMeasure(metrics, st, params, fullParams, endOp)
} }
@ -79,7 +80,7 @@ export function updateMeasure (
value?: number, value?: number,
override?: boolean override?: boolean
): void { ): void {
const ed = Date.now() const ed = platformNow()
const fParams = typeof fullParams === 'function' ? fullParams() : fullParams const fParams = typeof fullParams === 'function' ? fullParams() : fullParams
// Update params if required // Update params if required
@ -136,7 +137,7 @@ export function childMetrics (root: Metrics, path: string[]): Metrics {
/** /**
* @public * @public
*/ */
export function metricsAggregate (m: Metrics, limit: number = -1): Metrics { export function metricsAggregate (m: Metrics, limit: number = -1, roundMath: boolean = false): Metrics {
let ms = aggregateMetrics(m.measurements, limit) let ms = aggregateMetrics(m.measurements, limit)
// Use child overage, if there is no top level value specified. // Use child overage, if there is no top level value specified.
@ -237,7 +238,7 @@ function toString (name: string, m: Metrics, offset: number, length: number): st
* @public * @public
*/ */
export function metricsToString (metrics: Metrics, name = 'System', length: number): string { export function metricsToString (metrics: Metrics, name = 'System', length: number): string {
return toString(name, metricsAggregate(metrics, 50), 0, length) return toString(name, metricsAggregate(metrics, 50, true), 0, length)
} }
function printMetricsParamsRows ( function printMetricsParamsRows (
@ -287,5 +288,5 @@ function toStringRows (name: string, m: Metrics, offset: number): (number | stri
* @public * @public
*/ */
export function metricsToRows (metrics: Metrics, name = 'System'): (number | string)[][] { export function metricsToRows (metrics: Metrics, name = 'System'): (number | string)[][] {
return toStringRows(name, metricsAggregate(metrics, 50), 0) return toStringRows(name, metricsAggregate(metrics, 50, true), 0)
} }

View File

@ -1,6 +1,6 @@
import { Analytics } from '@hcengineering/analytics' import { Analytics } from '@hcengineering/analytics'
import { deepEqual } from 'fast-equals' import { deepEqual } from 'fast-equals'
import { DocumentUpdate, DOMAIN_MODEL, Hierarchy, MixinData, MixinUpdate, ModelDb, toFindResult } from '.' import { DocumentUpdate, DOMAIN_MODEL, Hierarchy, MixinData, MixinUpdate, ModelDb, platformNow, toFindResult } from '.'
import type { import type {
PersonId, PersonId,
AnyAttribute, AnyAttribute,
@ -481,10 +481,10 @@ export class ApplyOperations extends TxOperations {
this.notMatches.length === 0 && this.notMatches.length === 0 &&
this.measureName == null this.measureName == null
) { ) {
const st = Date.now() const st = platformNow()
// Individual update, no need for apply // Individual update, no need for apply
await this.ops.tx(this.txes[0]) await this.ops.tx(this.txes[0])
const time = Date.now() - st const time = platformNow() - st
this.txes = [] this.txes = []
return { return {
result: true, result: true,
@ -493,7 +493,7 @@ export class ApplyOperations extends TxOperations {
} }
} }
if (this.txes.length > 0) { if (this.txes.length > 0) {
const st = Date.now() const st = platformNow()
const aop = this.ops.txFactory.createTxApplyIf( const aop = this.ops.txFactory.createTxApplyIf(
core.space.Tx, core.space.Tx,
this.scope, this.scope,
@ -505,7 +505,7 @@ export class ApplyOperations extends TxOperations {
extraNotify extraNotify
) )
const result = (await this.ops.tx(aop)) as TxApplyResult const result = (await this.ops.tx(aop)) as TxApplyResult
const dnow = Date.now() const dnow = platformNow()
if (typeof window === 'object' && window !== null && this.measureName != null) { if (typeof window === 'object' && window !== null && this.measureName != null) {
console.log(`measure ${this.measureName}`, dnow - st, 'server time', result.serverTime) console.log(`measure ${this.measureName}`, dnow - st, 'server time', result.serverTime)
} }

View File

@ -928,3 +928,13 @@ export function pickPrimarySocialId (socialIds: SocialId[]): SocialId {
export function notEmpty<T> (id: T | undefined | null): id is T { export function notEmpty<T> (id: T | undefined | null): id is T {
return id !== undefined && id !== null && id !== '' return id !== undefined && id !== null && id !== ''
} }
/**
* Return a current performance timestamp
*/
export const platformNow: () => number = () => performance.now()
/**
* Return a diff with previous performance snapshot with 2 digits after . max.
*/
export const platformNowDiff = (old: number): number => Math.round((performance.now() - old) * 100) / 100

View File

@ -127,28 +127,28 @@ switch (args[0]) {
} }
case 'transpile': { case 'transpile': {
const filesToTranspile = collectFiles(join(process.cwd(), args[1])) const filesToTranspile = collectFiles(join(process.cwd(), args[1]))
let st = Date.now() let st = performance.now()
const before = {} const before = {}
const after = {} const after = {}
collectFileStats('lib', before) collectFileStats('lib', before)
performESBuild(filesToTranspile) performESBuild(filesToTranspile)
.then(() => { .then(() => {
console.log("Transpile time: ", Date.now() - st) console.log("Transpile time: ", Math.round((performance.now() - st) * 100) / 100)
collectFileStats('lib', after) collectFileStats('lib', after)
cleanNonModified(before, after) cleanNonModified(before, after)
}) })
break break
} }
case 'validate': { case 'validate': {
let st = Date.now() let st = performance.now()
validateTSC(st).then(() => { validateTSC(st).then(() => {
console.log("Validate time: ", Date.now() - st) console.log("Validate time: ", Math.round((performance.now() - st) * 100) / 100)
}) })
break break
} }
default: { default: {
let st = Date.now() let st = performance.now()
const filesToTranspile = collectFiles(join(process.cwd(), 'src')) const filesToTranspile = collectFiles(join(process.cwd(), 'src'))
Promise.all( Promise.all(
[ [
@ -157,7 +157,7 @@ switch (args[0]) {
] ]
) )
.then(() => { .then(() => {
console.log("Full build time: ", Date.now() - st) console.log("Full build time: ", Math.round((performance.now() - st) * 100) / 100)
}) })
break break
} }

View File

@ -77,7 +77,7 @@ for(const a of process.argv.slice(2)) {
args.push(a) args.push(a)
} }
} }
let st = Date.now() let st = performance.now()
execProcess( execProcess(
'svelte-check', 'svelte-check',
'svelte-check', [ 'svelte-check', [
@ -85,6 +85,6 @@ execProcess(
...args ...args
], useConsole) ], useConsole)
.then(() => { .then(() => {
console.log("Svelte check time: ", Date.now() - st) console.log("Svelte check time: ", Math.round((performance.now() - st) * 100) / 100)
}) })

View File

@ -55,6 +55,7 @@ import core, {
generateId, generateId,
getObjectValue, getObjectValue,
matchQuery, matchQuery,
platformNow,
reduceCalls, reduceCalls,
shouldShowArchived, shouldShowArchived,
toFindResult toFindResult
@ -187,7 +188,7 @@ export class LiveQuery implements WithTx, Client {
options?: FindOptions<T> options?: FindOptions<T>
): Query { ): Query {
const q = this.createQuery(_class, query, undefined, options) const q = this.createQuery(_class, query, undefined, options)
this.queue.set(q.id, { ...q, lastUsed: Date.now() }) this.queue.set(q.id, { ...q, lastUsed: platformNow() })
if (!(q.result instanceof Promise)) { if (!(q.result instanceof Promise)) {
q.result.clean() q.result.clean()
} }
@ -223,7 +224,7 @@ export class LiveQuery implements WithTx, Client {
q.result = await q.result q.result = await q.result
} }
if (this.removeFromQueue(q, false)) { if (this.removeFromQueue(q, false)) {
this.queue.set(q.id, { ...q, lastUsed: Date.now() }) this.queue.set(q.id, { ...q, lastUsed: platformNow() })
q.result.clean() q.result.clean()
} }
return toFindResult(q.result.getClone(), q.total) return toFindResult(q.result.getClone(), q.total)
@ -265,7 +266,7 @@ export class LiveQuery implements WithTx, Client {
q.result = await q.result q.result = await q.result
} }
if (this.removeFromQueue(q, false)) { if (this.removeFromQueue(q, false)) {
this.queue.set(q.id, { ...q, lastUsed: Date.now() }) this.queue.set(q.id, { ...q, lastUsed: platformNow() })
q.result.clean() q.result.clean()
} }
return q.result.getClone<WithLookup<T>>().shift() return q.result.getClone<WithLookup<T>>().shift()
@ -443,7 +444,7 @@ export class LiveQuery implements WithTx, Client {
if (!(q.result instanceof Promise)) { if (!(q.result instanceof Promise)) {
q.result.clean() q.result.clean()
} }
this.queue.set(q.id, { ...q, lastUsed: Date.now() }) this.queue.set(q.id, { ...q, lastUsed: platformNow() })
} }
} }
} }

View File

@ -35,7 +35,8 @@ import core, {
type ModelFilter, type ModelFilter,
type PluginConfiguration, type PluginConfiguration,
type Ref, type Ref,
type TxCUD type TxCUD,
platformNow
} from '@hcengineering/core' } from '@hcengineering/core'
import platform, { Severity, Status, getMetadata, getPlugins, setPlatformStatus } from '@hcengineering/platform' import platform, { Severity, Status, getMetadata, getPlugins, setPlatformStatus } from '@hcengineering/platform'
import { connect } from './connection' import { connect } from './connection'
@ -46,7 +47,7 @@ let dbRequest: IDBOpenDBRequest | undefined
let dbPromise: Promise<IDBDatabase | undefined> = Promise.resolve(undefined) let dbPromise: Promise<IDBDatabase | undefined> = Promise.resolve(undefined)
if (typeof localStorage !== 'undefined') { if (typeof localStorage !== 'undefined') {
const st = Date.now() const st = platformNow()
dbPromise = new Promise<IDBDatabase>((resolve) => { dbPromise = new Promise<IDBDatabase>((resolve) => {
dbRequest = indexedDB.open('model.db.persistence', 2) dbRequest = indexedDB.open('model.db.persistence', 2)
@ -58,7 +59,7 @@ if (typeof localStorage !== 'undefined') {
} }
dbRequest.onsuccess = function () { dbRequest.onsuccess = function () {
const db = (dbRequest as IDBOpenDBRequest).result const db = (dbRequest as IDBOpenDBRequest).result
console.log('init DB complete', Date.now() - st) console.log('init DB complete', platformNow() - st)
resolve(db) resolve(db)
} }
}) })

View File

@ -16,6 +16,8 @@
import core, { import core, {
DOMAIN_MODEL, DOMAIN_MODEL,
cutObjectArray, cutObjectArray,
platformNow,
platformNowDiff,
type Class, type Class,
type Client, type Client,
type Doc, type Doc,
@ -86,7 +88,7 @@ export class PresentationClientHook implements ClientHook {
query: DocumentQuery<T>, query: DocumentQuery<T>,
options?: FindOptions<T> options?: FindOptions<T>
): Promise<WithLookup<T> | undefined> { ): Promise<WithLookup<T> | undefined> {
const startTime = Date.now() const startTime = platformNow()
const isModel = client.getHierarchy().findDomain(_class) === DOMAIN_MODEL const isModel = client.getHierarchy().findDomain(_class) === DOMAIN_MODEL
const result = await client.findOne(_class, query, options) const result = await client.findOne(_class, query, options)
if (this.notifyEnabled && !isModel) { if (this.notifyEnabled && !isModel) {
@ -100,7 +102,7 @@ export class PresentationClientHook implements ClientHook {
' =>model', ' =>model',
client.getModel(), client.getModel(),
getMetadata(devmodel.metadata.DevModel), getMetadata(devmodel.metadata.DevModel),
Date.now() - startTime, platformNow() - startTime,
this.stackLine() this.stackLine()
) )
} }
@ -113,7 +115,7 @@ export class PresentationClientHook implements ClientHook {
query: DocumentQuery<T>, query: DocumentQuery<T>,
options?: FindOptions<T> options?: FindOptions<T>
): Promise<FindResult<T>> { ): Promise<FindResult<T>> {
const startTime = Date.now() const startTime = platformNow()
const isModel = client.getHierarchy().findDomain(_class) === DOMAIN_MODEL const isModel = client.getHierarchy().findDomain(_class) === DOMAIN_MODEL
const result = await client.findAll(_class, query, options) const result = await client.findAll(_class, query, options)
if (this.notifyEnabled && !isModel) { if (this.notifyEnabled && !isModel) {
@ -127,7 +129,7 @@ export class PresentationClientHook implements ClientHook {
' =>model', ' =>model',
client.getModel(), client.getModel(),
getMetadata(devmodel.metadata.DevModel), getMetadata(devmodel.metadata.DevModel),
Date.now() - startTime, platformNow() - startTime,
JSON.stringify(result).length, JSON.stringify(result).length,
this.stackLine() this.stackLine()
) )
@ -150,7 +152,7 @@ export class PresentationClientHook implements ClientHook {
} }
async tx (client: Client, tx: Tx): Promise<TxResult> { async tx (client: Client, tx: Tx): Promise<TxResult> {
const startTime = Date.now() const startTime = platformNow()
const result = await client.tx(tx) const result = await client.tx(tx)
if (this.notifyEnabled && (tx as any).objectClass !== core.class.BenchmarkDoc) { if (this.notifyEnabled && (tx as any).objectClass !== core.class.BenchmarkDoc) {
console.debug( console.debug(
@ -158,7 +160,7 @@ export class PresentationClientHook implements ClientHook {
testing ? JSON.stringify(cutObjectArray(tx)).slice(0, 160) : tx, testing ? JSON.stringify(cutObjectArray(tx)).slice(0, 160) : tx,
result, result,
getMetadata(devmodel.metadata.DevModel), getMetadata(devmodel.metadata.DevModel),
Date.now() - startTime, platformNowDiff(startTime),
this.stackLine() this.stackLine()
) )
} }

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { Class, Doc, Ref, toIdMap } from '@hcengineering/core' import { Class, Doc, platformNow, platformNowDiff, Ref, toIdMap } from '@hcengineering/core'
import { getEmbeddedLabel } from '@hcengineering/platform' import { getEmbeddedLabel } from '@hcengineering/platform'
import { Card, getClient } from '@hcengineering/presentation' import { Card, getClient } from '@hcengineering/presentation'
import tags, { TagCategory, TagElement, TagReference } from '@hcengineering/tags' import tags, { TagCategory, TagElement, TagReference } from '@hcengineering/tags'
@ -460,7 +460,7 @@
const client = getClient() const client = getClient()
for (const item of searchPlanElements) { for (const item of searchPlanElements) {
console.log('Apply', item.original.title) console.log('Apply', item.original.title)
const st = Date.now() const st = platformNow()
const ops = client.apply(undefined, 'optimize-skill') const ops = client.apply(undefined, 'optimize-skill')
let allRefs: TagReference[] = await client.findAll(tags.class.TagReference, { tag: item.original._id }) let allRefs: TagReference[] = await client.findAll(tags.class.TagReference, { tag: item.original._id })
@ -540,7 +540,7 @@
}) })
} }
} }
console.log('Apply:commit', item.original.title, Date.now() - st) console.log('Apply:commit', item.original.title, platformNowDiff(st))
await ops.commit(false) await ops.commit(false)
processed++ processed++
} }

View File

@ -158,7 +158,7 @@
attachedTo: generateId(), attachedTo: generateId(),
attachedToClass: time.class.ToDo, attachedToClass: time.class.ToDo,
collection: 'workslots', collection: 'workslots',
modifiedOn: Date.now(), modifiedOn: now,
modifiedBy: myAccount.primarySocialId modifiedBy: myAccount.primarySocialId
}) })
slots = slots slots = slots

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import core, { RateLimiter, concatLink, metricsAggregate, type Metrics } from '@hcengineering/core' import core, { RateLimiter, concatLink, metricsAggregate, platformNow, type Metrics } from '@hcengineering/core'
import login from '@hcengineering/login' import login from '@hcengineering/login'
import { getEmbeddedLabel, getMetadata } from '@hcengineering/platform' import { getEmbeddedLabel, getMetadata } from '@hcengineering/platform'
import presentation, { getClient, isAdminUser, uiContext } from '@hcengineering/presentation' import presentation, { getClient, isAdminUser, uiContext } from '@hcengineering/presentation'
@ -75,8 +75,8 @@
const rate = new RateLimiter(commandsToSendParallel) const rate = new RateLimiter(commandsToSendParallel)
const client = getClient() const client = getClient()
const doOp = async () => { const doOp = async (): Promise<void> => {
const st = Date.now() const st = platformNow()
active++ active++
await client.createDoc(core.class.BenchmarkDoc, core.space.Configuration, { await client.createDoc(core.class.BenchmarkDoc, core.space.Configuration, {
source: genData(dataSize), source: genData(dataSize),
@ -86,7 +86,7 @@
} }
}) })
active-- active--
const ed = Date.now() const ed = platformNow()
if (ed - st > maxTime) { if (ed - st > maxTime) {
maxTime = ed - st maxTime = ed - st
@ -132,12 +132,12 @@
document.body.appendChild(link) document.body.appendChild(link)
link.click() link.click()
document.body.removeChild(link) document.body.removeChild(link)
fetchStats(0) void fetchStats(0)
} }
let metrics: Metrics | undefined let metrics: Metrics | undefined
function update (tick: number) { function update (tick: number): void {
metrics = metricsAggregate(uiContext.metrics) metrics = metricsAggregate(uiContext.metrics)
} }
@ -183,8 +183,8 @@
</div> </div>
<div class="flex-col p-1"> <div class="flex-col p-1">
<div class="flex-row-center p-1"> <div class="flex-row-center p-1">
Command benchmark {avgTime / opss} Command benchmark {Math.round((avgTime / opss) * 100) / 100}
{maxTime} - {active} {Math.round(maxTime * 100) / 100} - {active}
</div> </div>
<div class="flex-row-center p-1"> <div class="flex-row-center p-1">
<div class="flex-row-center p-1"> <div class="flex-row-center p-1">
@ -230,7 +230,7 @@
void fetch(endpoint + `/api/v1/manage?token=${token}&operation=profile-start`, { void fetch(endpoint + `/api/v1/manage?token=${token}&operation=profile-start`, {
method: 'PUT' method: 'PUT'
}) })
fetchStats(0) void fetchStats(0)
}} }}
/> />
{:else} {:else}

View File

@ -15,14 +15,16 @@
Object.keys(metrics.params).length > 0 || Object.keys(metrics.params).length > 0 ||
(metrics.topResult?.length ?? 0) > 0 (metrics.topResult?.length ?? 0) > 0
const toTime = (value: number, digits = 10): number => Math.round(value * digits) / digits
function showAvg (name: string, time: number, ops: number): string { function showAvg (name: string, time: number, ops: number): string {
if (name.startsWith('#')) { if (name.startsWith('#')) {
return `➿ ${time}` return `➿ ${toTime(time)}`
} }
if (ops === 0) { if (ops === 0) {
return `⏱️ ${time}` return `⏱️ ${toTime(time)}`
} }
return `${Math.floor((time / ops) * 100) / 100}` return `${toTime(time / ops, 100)}`
} }
const getSorted = (v: Record<string, MetricsData>, sortingOrder: 'avg' | 'ops' | 'total') => { const getSorted = (v: Record<string, MetricsData>, sortingOrder: 'avg' | 'ops' | 'total') => {
if (sortingOrder === 'avg') { if (sortingOrder === 'avg') {
@ -87,7 +89,7 @@
</FixedColumn> </FixedColumn>
<FixedColumn key="time-full"> <FixedColumn key="time-full">
<span class="p-1"> <span class="p-1">
{metrics.value} {toTime(metrics.value)}
</span> </span>
</FixedColumn> </FixedColumn>
</div> </div>
@ -98,14 +100,14 @@
<Expandable> <Expandable>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<div class="flex-row-center flex-between flex-grow ml-2"> <div class="flex-row-center flex-between flex-grow ml-2">
Slowest result:{metrics.topResult[0].value} Slowest result:{toTime(metrics.topResult[0].value)}
</div> </div>
</svelte:fragment> </svelte:fragment>
{#each metrics.topResult ?? [] as r} {#each metrics.topResult ?? [] as r}
<Expandable> <Expandable>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<div class="flex-row-center flex-between flex-grow select-text"> <div class="flex-row-center flex-between flex-grow select-text">
Time:{r.value} Time:{toTime(r.value)}
</div> </div>
</svelte:fragment> </svelte:fragment>
<pre class="select-text"> <pre class="select-text">
@ -142,7 +144,7 @@
<FixedColumn key="time"> <FixedColumn key="time">
{showAvg(kk, vv.value, vv.operations)} {showAvg(kk, vv.value, vv.operations)}
</FixedColumn> </FixedColumn>
<FixedColumn key="time-full">{vv.value}</FixedColumn> <FixedColumn key="time-full">{toTime(vv.value)}</FixedColumn>
</div> </div>
</FixedColumn> </FixedColumn>
</svelte:fragment> </svelte:fragment>
@ -152,7 +154,7 @@
<Expandable> <Expandable>
<svelte:fragment slot="title"> <svelte:fragment slot="title">
<div class="flex-row-center flex-between flex-grow"> <div class="flex-row-center flex-between flex-grow">
Time:{r.value} Time:{toTime(r.value)}
</div> </div>
</svelte:fragment> </svelte:fragment>
<pre class="select-text"> <pre class="select-text">

View File

@ -60,7 +60,7 @@ const activeQueries = new Map<number, { time: number, cancel: () => void, query:
setInterval(() => { setInterval(() => {
for (const [k, v] of activeQueries.entries()) { for (const [k, v] of activeQueries.entries()) {
if (Date.now() - v.time > tickTimeout) { if (performance.now() - v.time > tickTimeout) {
console.log('query hang', k, v) console.log('query hang', k, v)
v.cancel() v.cancel()
activeQueries.delete(k) activeQueries.delete(k)
@ -88,17 +88,17 @@ async function handleSQLFind (
response.writeHead(403).end('Not allowed') response.writeHead(403).end('Not allowed')
return return
} }
const st = Date.now() const st = performance.now()
const query = sql.unsafe(json.query, json.params, { prepare: true }) const query = sql.unsafe(json.query, json.params, { prepare: true })
activeQueries.set(qid, { activeQueries.set(qid, {
time: Date.now(), time: performance.now(),
cancel: () => { cancel: () => {
query.cancel() query.cancel()
}, },
query: json.query query: json.query
}) })
const result = await query const result = await query
const qtime = Date.now() - st const qtime = performance.now() - st
console.log('query', json.query, qtime, result.length) console.log('query', json.query, qtime, result.length)
await toResponse(compression, result, response, qtime) await toResponse(compression, result, response, qtime)
} catch (err: any) { } catch (err: any) {

View File

@ -61,7 +61,8 @@ import core, {
type TxRemoveDoc, type TxRemoveDoc,
type TxResult, type TxResult,
type TxUpdateDoc, type TxUpdateDoc,
type WithLookup type WithLookup,
platformNow
} from '@hcengineering/core' } from '@hcengineering/core'
import { import {
type DbAdapter, type DbAdapter,
@ -647,7 +648,7 @@ abstract class MongoAdapterBase implements DbAdapter {
options: ServerFindOptions<T>, options: ServerFindOptions<T>,
stTime: number stTime: number
): Promise<FindResult<T>> { ): Promise<FindResult<T>> {
const st = Date.now() const st = platformNow()
const pipeline: any[] = [] const pipeline: any[] = []
const tquery = this.translateQuery(clazz, query, options) const tquery = this.translateQuery(clazz, query, options)
@ -760,7 +761,7 @@ abstract class MongoAdapterBase implements DbAdapter {
) )
total = arr?.[0]?.total ?? 0 total = arr?.[0]?.total ?? 0
} }
const edTime = Date.now() const edTime = platformNow()
if (edTime - stTime > 1000 || st - stTime > 1000) { if (edTime - stTime > 1000 || st - stTime > 1000) {
ctx.error('aggregate', { ctx.error('aggregate', {
time: edTime - stTime, time: edTime - stTime,
@ -892,11 +893,11 @@ abstract class MongoAdapterBase implements DbAdapter {
query: DocumentQuery<T>, query: DocumentQuery<T>,
options?: ServerFindOptions<T> options?: ServerFindOptions<T>
): Promise<FindResult<T>> { ): Promise<FindResult<T>> {
const stTime = Date.now() const stTime = platformNow()
const mongoQuery = this.translateQuery(_class, query, options) const mongoQuery = this.translateQuery(_class, query, options)
const fQuery = { ...mongoQuery.base, ...mongoQuery.lookup } const fQuery = { ...mongoQuery.base, ...mongoQuery.lookup }
return addOperation(ctx, 'find-all', {}, async () => { return addOperation(ctx, 'find-all', {}, async () => {
const st = Date.now() const st = platformNow()
let result: FindResult<T> let result: FindResult<T>
const domain = options?.domain ?? this.hierarchy.getDomain(_class) const domain = options?.domain ?? this.hierarchy.getDomain(_class)
if ( if (
@ -994,7 +995,7 @@ abstract class MongoAdapterBase implements DbAdapter {
throw e throw e
} }
const edTime = Date.now() const edTime = platformNow()
if (edTime - st > 1000 || st - stTime > 1000) { if (edTime - st > 1000 || st - stTime > 1000) {
ctx.error('FindAll', { ctx.error('FindAll', {
time: edTime - st, time: edTime - st,
@ -1222,8 +1223,8 @@ class MongoAdapter extends MongoAdapterBase {
return undefined return undefined
}) })
const stTime = Date.now() const stTime = platformNow()
const st = Date.now() const st = stTime
let promises: Promise<any>[] = [] let promises: Promise<any>[] = []
for (const [domain, txs] of byDomain) { for (const [domain, txs] of byDomain) {
if (domain === undefined) { if (domain === undefined) {
@ -1319,7 +1320,7 @@ class MongoAdapter extends MongoAdapterBase {
'find-result', 'find-result',
{}, {},
async (ctx) => { async (ctx) => {
const st = Date.now() const st = platformNow()
const docs = await addOperation( const docs = await addOperation(
ctx, ctx,
'find-result', 'find-result',

View File

@ -1,4 +1,4 @@
import { concatLink } from '@hcengineering/core' import { concatLink, platformNow } from '@hcengineering/core'
import type postgres from 'postgres' import type postgres from 'postgres'
import type { ParameterOrJSON } from 'postgres' import type { ParameterOrJSON } from 'postgres'
import { convertArrayParams, doFetchTypes, getPrepare } from './utils' import { convertArrayParams, doFetchTypes, getPrepare } from './utils'
@ -50,7 +50,7 @@ class GreenClient implements DBClient {
for (let attempt = 0; attempt < maxRetries; attempt++) { for (let attempt = 0; attempt < maxRetries; attempt++) {
try { try {
const st = Date.now() const st = platformNow()
const response = await fetch(this.endpoint, { const response = await fetch(this.endpoint, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -84,7 +84,7 @@ class GreenClient implements DBClient {
return await response.json() return await response.json()
} finally { } finally {
const qtime = response.headers.get('querytime') const qtime = response.headers.get('querytime')
const time = Date.now() - st const time = platformNow() - st
console.info({ console.info({
message: `green query: ${time} ${qtime ?? 0}`, message: `green query: ${time} ${qtime ?? 0}`,
query, query,

View File

@ -24,6 +24,8 @@ import core, {
generateId, generateId,
type MeasureContext, type MeasureContext,
type MixinUpdate, type MixinUpdate,
platformNow,
platformNowDiff,
type Projection, type Projection,
type Ref, type Ref,
systemAccountUuid, systemAccountUuid,
@ -78,7 +80,7 @@ export async function createTables (
return return
} }
const mapped = filtered.map((p) => translateDomain(p)) const mapped = filtered.map((p) => translateDomain(p))
const t = Date.now() const t = platformNow()
loadedTables = loadedTables =
loadedTables.size === 0 loadedTables.size === 0
? new Set( ? new Set(
@ -96,7 +98,7 @@ export async function createTables (
).map((it) => it.table_name) ).map((it) => it.table_name)
) )
: loadedTables : loadedTables
console.log('load-table', Date.now() - t) console.log('load-table', platformNowDiff(t))
const domainsToLoad = mapped.filter((it) => loadedTables.has(it)) const domainsToLoad = mapped.filter((it) => loadedTables.has(it))
if (domainsToLoad.length > 0) { if (domainsToLoad.length > 0) {

View File

@ -40,7 +40,9 @@ import core, {
type WorkspaceDataId, type WorkspaceDataId,
type PersonUuid, type PersonUuid,
Data, Data,
Version Version,
platformNow,
platformNowDiff
} from '@hcengineering/core' } from '@hcengineering/core'
import { getClient as getAccountClient, isWorkspaceLoginInfo } from '@hcengineering/account-client' import { getClient as getAccountClient, isWorkspaceLoginInfo } from '@hcengineering/account-client'
import { unknownError, type Status } from '@hcengineering/platform' import { unknownError, type Status } from '@hcengineering/platform'
@ -984,7 +986,7 @@ class TSessionManager implements SessionManager {
ws: ConnectionSocket, ws: ConnectionSocket,
workspace: WorkspaceUuid workspace: WorkspaceUuid
): ClientSessionCtx { ): ClientSessionCtx {
const st = Date.now() const st = platformNow()
return { return {
ctx, ctx,
pipeline, pipeline,
@ -993,7 +995,7 @@ class TSessionManager implements SessionManager {
sendResponse(ctx, service, ws, { sendResponse(ctx, service, ws, {
id: reqId, id: reqId,
result: msg, result: msg,
time: Date.now() - st, time: platformNowDiff(st),
bfst: Date.now(), bfst: Date.now(),
queue: service.requests.size queue: service.requests.size
}), }),
@ -1006,7 +1008,7 @@ class TSessionManager implements SessionManager {
id: reqId, id: reqId,
result: msg, result: msg,
error, error,
time: Date.now() - st, time: platformNowDiff(st),
bfst: Date.now(), bfst: Date.now(),
queue: service.requests.size queue: service.requests.size
}) })
@ -1046,7 +1048,7 @@ class TSessionManager implements SessionManager {
// Calculate total number of clients // Calculate total number of clients
const reqId = generateId() const reqId = generateId()
const st = Date.now() const st = platformNow()
return userCtx return userCtx
.with('🧭 handleRequest', {}, async (ctx) => { .with('🧭 handleRequest', {}, async (ctx) => {
if (request.time != null) { if (request.time != null) {

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
// //
import { AccountClient } from '@hcengineering/account-client'
import core, { import core, {
Branding, Branding,
coreId, coreId,
@ -26,19 +27,20 @@ import core, {
MeasureContext, MeasureContext,
MigrationState, MigrationState,
ModelDb, ModelDb,
platformNow,
platformNowDiff,
systemAccountUuid, systemAccountUuid,
Tx, Tx,
TxOperations, TxOperations,
WorkspaceUuid,
WorkspaceIds, WorkspaceIds,
WorkspaceUuid,
type Client, type Client,
type PersonInfo,
type Ref, type Ref,
type WithLookup, type WithLookup
type PersonInfo
} from '@hcengineering/core' } from '@hcengineering/core'
import { consoleModelLogger, MigrateOperation, ModelLogger, tryMigrate } from '@hcengineering/model' import { consoleModelLogger, MigrateOperation, ModelLogger, tryMigrate } from '@hcengineering/model'
import { DomainIndexHelperImpl, Pipeline, StorageAdapter, type DbAdapter } from '@hcengineering/server-core' import { DomainIndexHelperImpl, Pipeline, StorageAdapter, type DbAdapter } from '@hcengineering/server-core'
import { AccountClient } from '@hcengineering/account-client'
import { InitScript, WorkspaceInitializer } from './initializer' import { InitScript, WorkspaceInitializer } from './initializer'
import toolPlugin from './plugin' import toolPlugin from './plugin'
import { MigrateClientImpl } from './upgrade' import { MigrateClientImpl } from './upgrade'
@ -164,10 +166,10 @@ export async function updateModel (
try { try {
let i = 0 let i = 0
for (const op of migrateOperations) { for (const op of migrateOperations) {
const st = Date.now() const st = platformNow()
await op[1].upgrade(migrateState, async () => connection as any, logger) await op[1].upgrade(migrateState, async () => connection as any, logger)
const tdelta = Date.now() - st const tdelta = platformNowDiff(st)
if (tdelta > 0) { if (tdelta > 0.5) {
logger.log('Create', { name: op[0], time: tdelta }) logger.log('Create', { name: op[0], time: tdelta })
} }
i++ i++
@ -272,14 +274,14 @@ export async function upgradeModel (
} }
const preMigrate = op[1].preMigrate const preMigrate = op[1].preMigrate
const t = Date.now() const t = platformNow()
try { try {
await ctx.with(op[0], {}, (ctx) => preMigrate(preMigrateClient, logger)) await ctx.with(op[0], {}, (ctx) => preMigrate(preMigrateClient, logger))
} catch (err: any) { } catch (err: any) {
logger.error(`error during pre-migrate: ${op[0]} ${err.message}`, err) logger.error(`error during pre-migrate: ${op[0]} ${err.message}`, err)
throw err throw err
} }
logger.log('pre-migrate:', { workspaceId: wsIds, operation: op[0], time: Date.now() - t }) logger.log('pre-migrate:', { workspaceId: wsIds, operation: op[0], time: platformNowDiff(t) })
await progress(((100 / migrateOperations.length) * i * 10) / 100) await progress(((100 / migrateOperations.length) * i * 10) / 100)
i++ i++
} }
@ -317,11 +319,11 @@ export async function upgradeModel (
let i = 0 let i = 0
for (const op of migrateOperations) { for (const op of migrateOperations) {
try { try {
const t = Date.now() const t = platformNow()
await ctx.with(op[0], {}, () => op[1].migrate(migrateClient, logger)) await ctx.with(op[0], {}, () => op[1].migrate(migrateClient, logger))
const tdelta = Date.now() - t const tdelta = platformNowDiff(t)
if (tdelta > 0) { if (tdelta > 0) {
logger.log('migrate:', { workspaceId: wsIds, operation: op[0], time: Date.now() - t }) logger.log('migrate:', { workspaceId: wsIds, operation: op[0], time: tdelta })
} }
} catch (err: any) { } catch (err: any) {
logger.error(`error during migrate: ${op[0]} ${err.message}`, err) logger.error(`error during migrate: ${op[0]} ${err.message}`, err)

View File

@ -13,14 +13,19 @@
// limitations under the License. // limitations under the License.
// //
import {
getClient as getAccountClientRaw,
isWorkspaceLoginInfo,
type AccountClient
} from '@hcengineering/account-client'
import { Analytics } from '@hcengineering/analytics' import { Analytics } from '@hcengineering/analytics'
import { import {
generateId, generateId,
systemAccountUuid, systemAccountUuid,
type WorkspaceUuid,
type MeasureContext, type MeasureContext,
type Tx, type Tx,
type WorkspaceIds type WorkspaceIds,
type WorkspaceUuid
} from '@hcengineering/core' } from '@hcengineering/core'
import platform, { Severity, Status, UNAUTHORIZED, unknownStatus } from '@hcengineering/platform' import platform, { Severity, Status, UNAUTHORIZED, unknownStatus } from '@hcengineering/platform'
import { RPCHandler, type Response } from '@hcengineering/rpc' import { RPCHandler, type Response } from '@hcengineering/rpc'
@ -34,11 +39,6 @@ import {
type BlobResponse, type BlobResponse,
type WebsocketData type WebsocketData
} from '@hcengineering/server' } from '@hcengineering/server'
import {
getClient as getAccountClientRaw,
isWorkspaceLoginInfo,
type AccountClient
} from '@hcengineering/account-client'
import { import {
LOGGING_ENABLED, LOGGING_ENABLED,
pingConst, pingConst,
@ -51,7 +51,7 @@ import {
} from '@hcengineering/server-core' } from '@hcengineering/server-core'
import { decodeToken, type Token } from '@hcengineering/server-token' import { decodeToken, type Token } from '@hcengineering/server-token'
import cors from 'cors' import cors from 'cors'
import express, { type NextFunction, type Request, type Response as ExpressResponse } from 'express' import express, { type Response as ExpressResponse, type NextFunction, type Request } from 'express'
import http, { type IncomingMessage } from 'http' import http, { type IncomingMessage } from 'http'
import os from 'os' import os from 'os'
import { WebSocketServer, type RawData, type WebSocket } from 'ws' import { WebSocketServer, type RawData, type WebSocket } from 'ws'
@ -641,15 +641,11 @@ function createWebsocketClientSocket (
}, },
send: (ctx: MeasureContext, msg, binary, _compression) => { send: (ctx: MeasureContext, msg, binary, _compression) => {
const smsg = rpcHandler.serialize(msg, binary) const smsg = rpcHandler.serialize(msg, binary)
ctx.measure('send-data', smsg.length)
const st = Date.now()
if (ws.readyState !== ws.OPEN || cs.isClosed) { if (ws.readyState !== ws.OPEN || cs.isClosed) {
return return
} }
const handleErr = (err?: Error): void => { const handleErr = (err?: Error): void => {
ctx.measure('msg-send-delta', Date.now() - st)
if (err != null) { if (err != null) {
if (!`${err.message}`.includes('WebSocket is not open')) { if (!`${err.message}`.includes('WebSocket is not open')) {
ctx.error('send error', { err }) ctx.error('send error', { err })

View File

@ -3,6 +3,8 @@
import { import {
generateId, generateId,
NoMetricsContext, NoMetricsContext,
platformNow,
platformNowDiff,
WorkspaceUuid, WorkspaceUuid,
type Account, type Account,
type Class, type Class,
@ -216,11 +218,11 @@ export class Transactor extends DurableObject<Env> {
s.context.measure('receive-data', buff?.length ?? 0) s.context.measure('receive-data', buff?.length ?? 0)
// processRequest(s.session, cs, s.context, s.workspaceId, buff, handleRequest) // processRequest(s.session, cs, s.context, s.workspaceId, buff, handleRequest)
const request = cs.readRequest(buff, s.session.binaryMode) const request = cs.readRequest(buff, s.session.binaryMode)
const st = Date.now() const st = platformNow()
const r = this.sessionManager.handleRequest(this.measureCtx, s.session, cs, request, this.workspace) const r = this.sessionManager.handleRequest(this.measureCtx, s.session, cs, request, this.workspace)
this.ctx.waitUntil( this.ctx.waitUntil(
r.finally(() => { r.finally(() => {
const time = Date.now() - st const time = platformNowDiff(st)
console.log({ console.log({
message: `handle-request: ${request.method} time: ${time}`, message: `handle-request: ${request.method} time: ${time}`,
method: request.method, method: request.method,