Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
edf0455
[benchmark] add benchmark endpoint and cdp runtime benchmark implemen…
raiden-staging Nov 20, 2025
19d3e61
[benchmark] instrument wrapper to capture and export container startu…
raiden-staging Nov 20, 2025
b04eaf7
[benchmark] benchmarks: use fixed-duration component benchmarks and r…
raiden-staging Nov 20, 2025
699e65b
[benchmark] remove ffmpeg-downloader stage from chromium-headful dock…
raiden-staging Nov 20, 2025
d47c864
[benchmark] remove screenshot benchmark support and related converter…
raiden-staging Nov 20, 2025
dd52dc8
[benchmark] integrate neko websocket trigger and client for webrtc be…
raiden-staging Nov 20, 2025
6687d31
[benchmark] adjust unikernel scripts and trim openapi benchmark docs
raiden-staging Nov 20, 2025
7e510b7
[benchmark] lower vcpu count to 2 for chromium-headful unikernel
raiden-staging Nov 20, 2025
6081afd
[benchmark] benchmarks: switch from websocket neko trigger to reading…
raiden-staging Nov 20, 2025
a8f96f1
[benchmark] add webrtc stats collector and stream benchmark payloads …
raiden-staging Nov 20, 2025
0f109e1
[benchmark] wrap benchmark webrtc stats into payload field when sendi…
raiden-staging Nov 20, 2025
d61b629
[benchmark] bench: make cdp scenarios session-aware and switch to gen…
raiden-staging Nov 20, 2025
6de4399
[benchmark] refactor cdp runtime benchmark to benchmark endpoints ind…
raiden-staging Nov 20, 2025
a3a9f74
[benchmark] refactor cdp runtime benchmark and implement mixed-worklo…
raiden-staging Nov 20, 2025
8609538
[benchmark] refactor cdp runtime benchmark: create and attach a new p…
raiden-staging Nov 20, 2025
97aadb4
[benchmark] cdp: remove flatten from Target.attachToTarget and add ve…
raiden-staging Nov 20, 2025
16e110e
[benchmark] simplify cdp benchmark by removing target creation/attach…
raiden-staging Nov 20, 2025
d667530
[benchmark] fetch page websocket url from /json instead of /json/version
raiden-staging Nov 20, 2025
20e54f2
[benchmark] run mixed cdp workload with per-worker websocket connections
raiden-staging Nov 20, 2025
5fc9607
[benchmark] refactor cdp runtime benchmark: session-based workers, de…
raiden-staging Nov 20, 2025
5867512
[benchmark] timebox scenarios and record per-scenario duration
raiden-staging Nov 20, 2025
8ad7301
[benchmark] run scenarios in multiple rounds and increase default ben…
raiden-staging Nov 20, 2025
a0a51c1
[benchmark] simplify cdp runtime benchmark and session lifecycle
raiden-staging Nov 20, 2025
10199f0
[benchmark] make cdp runtime benchmark sequential and run iterations …
raiden-staging Nov 20, 2025
5682cac
[benchmark] support per-scenario duration/iterations/timeouts and rew…
raiden-staging Nov 20, 2025
5a7a7a8
[benchmark] record attempt_count and duration_seconds in cdp scenario…
raiden-staging Nov 20, 2025
69121c9
[benchmark] benchmarks/cdp: track cdp events, add scenario type and n…
raiden-staging Nov 20, 2025
caaf5ce
[benchmark] include scenario type and event metrics in cdp benchmark …
raiden-staging Nov 20, 2025
3b5cb7d
[benchmark] sync with latest
raiden-staging Nov 20, 2025
c1be70f
[benchmark] update neko base version
raiden-staging Nov 20, 2025
9f88acf
[benchmark] mem tracking , phases deltas , system metrics
raiden-staging Nov 20, 2025
78fbc17
[benchmark] NaN guards
raiden-staging Nov 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ RUN --mount=type=cache,target=/tmp/cache/ffmpeg,sharing=locked,id=$CACHEIDPREFIX
rm -rf /tmp/ffmpeg*
EOT

FROM ghcr.io/onkernel/neko/base:3.0.8-v1.3.0 AS neko
FROM ghcr.io/onkernel/neko/base:3.0.8-v1.3.1 AS neko
# ^--- now has event.SYSTEM_PONG with legacy support to keepalive
FROM node:22-bullseye-slim AS node-22
FROM docker.io/ubuntu:22.04
Expand Down
31 changes: 31 additions & 0 deletions images/chromium-headful/client/src/neko/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import {
SignalCandidatePayload,
SignalOfferPayload,
SignalAnswerMessage,
BenchmarkWebRTCStatsPayload,
} from './messages'

import { WebRTCStatsCollector } from './webrtc-stats-collector'

export interface BaseEvents {
info: (...message: any[]) => void
warn: (...message: any[]) => void
Expand All @@ -28,6 +31,22 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
protected _state: RTCIceConnectionState = 'disconnected'
protected _id = ''
protected _candidates: RTCIceCandidate[] = []
protected _webrtcStatsCollector: WebRTCStatsCollector

constructor() {
super()

// Initialize WebRTC stats collector
this._webrtcStatsCollector = new WebRTCStatsCollector((stats: BenchmarkWebRTCStatsPayload) => {
// Send stats to server via WebSocket
if (this.connected) {
this._ws!.send(JSON.stringify({
event: EVENT.BENCHMARK.WEBRTC_STATS,
payload: stats,
}))
}
})
}

get id() {
return this._id
Expand Down Expand Up @@ -88,6 +107,9 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
this._ws_heartbeat = undefined
}

// Stop WebRTC stats collection
this._webrtcStatsCollector.stop()

if (this._ws) {
// reset all events
this._ws.onmessage = () => {}
Expand Down Expand Up @@ -241,18 +263,27 @@ export abstract class BaseClient extends EventEmitter<BaseEvents> {
break
case 'connected':
this.onConnected()
// Start WebRTC stats collection
if (this._peer) {
this._webrtcStatsCollector.start(this._peer)
this.emit('debug', 'started WebRTC stats collection')
}
break
case 'disconnected':
this[EVENT.RECONNECTING]()
// Stop stats collection on disconnection
this._webrtcStatsCollector.stop()
break
// https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling#ice_connection_state
// We don't watch the disconnected signaling state here as it can indicate temporary issues and may
// go back to a connected state after some time. Watching it would close the video call on any temporary
// network issue.
case 'failed':
this._webrtcStatsCollector.stop()
this.onDisconnected(new Error('peer failed'))
break
case 'closed':
this._webrtcStatsCollector.stop()
this.onDisconnected(new Error('peer closed'))
break
}
Expand Down
6 changes: 6 additions & 0 deletions images/chromium-headful/client/src/neko/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ export const EVENT = {
RELEASE: 'admin/release',
GIVE: 'admin/give',
},
BENCHMARK: {
WEBRTC_STATS: 'benchmark/webrtc_stats',
},
} as const

export type Events = typeof EVENT
Expand All @@ -82,6 +85,7 @@ export type WebSocketEvents =
| ScreenEvents
| BroadcastEvents
| AdminEvents
| BenchmarkEvents

export type ControlEvents =
| typeof EVENT.CONTROL.LOCKED
Expand Down Expand Up @@ -122,3 +126,5 @@ export type AdminEvents =
| typeof EVENT.ADMIN.CONTROL
| typeof EVENT.ADMIN.RELEASE
| typeof EVENT.ADMIN.GIVE

export type BenchmarkEvents = typeof EVENT.BENCHMARK.WEBRTC_STATS
59 changes: 59 additions & 0 deletions images/chromium-headful/client/src/neko/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export type WebSocketPayloads =
| BroadcastStatusPayload
| BroadcastCreatePayload
| SystemPongPayload
| BenchmarkWebRTCStatsPayload

export interface WebSocketMessage {
event: WebSocketEvents | string
Expand Down Expand Up @@ -278,3 +279,61 @@ export type AdminLockResource = 'login' | 'control' | 'file_transfer'
export interface AdminLockPayload {
resource: AdminLockResource
}

/*
BENCHMARK PAYLOADS
*/
export interface BenchmarkWebRTCStatsPayload {
timestamp: string
connection_state: string
ice_connection_state: string
frame_rate_fps: {
target: number
achieved: number
min: number
max: number
}
frame_latency_ms: {
p50: number
p95: number
p99: number
}
bitrate_kbps: {
video: number
audio: number
total: number
}
packets: {
video_received: number
video_lost: number
audio_received: number
audio_lost: number
loss_percent: number
}
frames: {
received: number
dropped: number
decoded: number
corrupted: number
key_frames_decoded: number
}
jitter_ms: {
video: number
audio: number
}
network: {
rtt_ms: number
available_outgoing_bitrate_kbps: number
bytes_received: number
bytes_sent: number
}
codecs: {
video: string
audio: string
}
resolution: {
width: number
height: number
}
concurrent_viewers: number
}
Loading
Loading