aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/benchmark.ts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/benchmark.ts')
-rw-r--r--scripts/benchmark.ts234
1 files changed, 234 insertions, 0 deletions
diff --git a/scripts/benchmark.ts b/scripts/benchmark.ts
new file mode 100644
index 000000000..69d902b5c
--- /dev/null
+++ b/scripts/benchmark.ts
@@ -0,0 +1,234 @@
1import { registerTSPaths } from '../server/helpers/register-ts-paths'
2registerTSPaths()
3
4import * as autocannon from 'autocannon'
5import {
6 addVideoCommentReply,
7 addVideoCommentThread,
8 createVideoCaption,
9 flushAndRunServer,
10 getVideosList,
11 killallServers,
12 ServerInfo,
13 setAccessTokensToServers,
14 uploadVideo
15} from '@shared/extra-utils'
16import { Video, VideoPrivacy } from '@shared/models'
17import { writeJson } from 'fs-extra'
18
19let server: ServerInfo
20let video: Video
21let threadId: number
22
23const outfile = process.argv[2]
24
25run()
26 .catch(err => console.error(err))
27 .finally(() => {
28 if (server) killallServers([ server ])
29 })
30
31function buildAuthorizationHeader () {
32 return {
33 Authorization: 'Bearer ' + server.accessToken
34 }
35}
36
37async function run () {
38 console.log('Preparing server...')
39
40 await prepare()
41
42 const tests = [
43 {
44 title: 'API - unread notifications',
45 path: '/api/v1/users/me/notifications?start=0&count=0&unread=true',
46 headers: buildAuthorizationHeader(),
47 expecter: (_client, statusCode) => {
48 return statusCode === 200
49 }
50 },
51 {
52 title: 'API - me',
53 path: '/api/v1/users/me',
54 headers: buildAuthorizationHeader(),
55 expecter: (client, statusCode) => {
56 const body = client.resData[0].body
57
58 return statusCode === 200 && body.startsWith('{"id":')
59 }
60 },
61 {
62 title: 'API - videos list',
63 path: '/api/v1/videos',
64 expecter: (client, statusCode) => {
65 const body = client.resData[0].body
66
67 return statusCode === 200 && body.startsWith('{"total":10')
68 }
69 },
70 {
71 title: 'API - video get',
72 path: '/api/v1/videos/' + video.uuid,
73 expecter: (client, statusCode) => {
74 const body = client.resData[0].body
75
76 return statusCode === 200 && body.startsWith('{"id":')
77 }
78 },
79 {
80 title: 'API - video captions',
81 path: '/api/v1/videos/' + video.uuid + '/captions',
82 expecter: (client, statusCode) => {
83 const body = client.resData[0].body
84
85 return statusCode === 200 && body.startsWith('{"total":4')
86 }
87 },
88 {
89 title: 'API - video threads',
90 path: '/api/v1/videos/' + video.uuid + '/comment-threads',
91 expecter: (client, statusCode) => {
92 const body = client.resData[0].body
93
94 return statusCode === 200 && body.startsWith('{"total":10')
95 }
96 },
97 {
98 title: 'API - video replies',
99 path: '/api/v1/videos/' + video.uuid + '/comment-threads/' + threadId,
100 expecter: (client, statusCode) => {
101 const body = client.resData[0].body
102
103 return statusCode === 200 && body.startsWith('{"comment":{')
104 }
105 },
106 {
107 title: 'HTML - video watch',
108 path: '/videos/watch/' + video.uuid,
109 expecter: (client, statusCode) => {
110 const body = client.resData[0].body
111
112 return statusCode === 200 && body.includes('<title>my super')
113 }
114 },
115 {
116 title: 'HTML - homepage',
117 path: '/',
118 expecter: (_client, statusCode) => {
119 return statusCode === 200
120 }
121 },
122 {
123 title: 'API - config',
124 path: '/api/v1/config',
125 expecter: (client, statusCode) => {
126 const body = client.resData[0].body
127
128 return statusCode === 200 && body.startsWith('{"instance":')
129 }
130 }
131 ]
132
133 const finalResult: any[] = []
134
135 for (const test of tests) {
136 console.log('Running against %s.', test.path)
137 const testResult = await runBenchmark(test)
138
139 Object.assign(testResult, { title: test.title, path: test.path })
140 finalResult.push(testResult)
141
142 console.log(autocannon.printResult(testResult))
143 }
144
145 if (outfile) await writeJson(outfile, finalResult)
146}
147
148function runBenchmark (options: {
149 path: string
150 headers?: { [ id: string ]: string }
151 expecter: Function
152}) {
153 const { path, expecter, headers } = options
154
155 return new Promise((res, rej) => {
156 const instance = autocannon({
157 url: server.url + path,
158 connections: 20,
159 headers,
160 pipelining: 1,
161 duration: 10
162 }, (err, result) => {
163 if (err) return rej(err)
164
165 return res(result)
166 })
167
168 instance.on('response', (client, statusCode) => {
169 if (expecter(client, statusCode) !== true) {
170 console.error('Expected result failed.', { data: client.resData })
171 process.exit(-1)
172 }
173 })
174 })
175}
176
177async function prepare () {
178 server = await flushAndRunServer(1, {
179 rates_limit: {
180 api: {
181 max: 5_000_000
182 }
183 }
184 })
185 await setAccessTokensToServers([ server ])
186
187 const videoAttributes = {
188 name: 'my super video',
189 category: 2,
190 nsfw: true,
191 licence: 6,
192 language: 'fr',
193 privacy: VideoPrivacy.PUBLIC,
194 support: 'please give me a coffee',
195 description: 'my super description'.repeat(10),
196 tags: [ 'tag1', 'tag2', 'tag3' ]
197 }
198
199 for (let i = 0; i < 10; i++) {
200 Object.assign(videoAttributes, { name: 'my super video ' + i })
201 await uploadVideo(server.url, server.accessToken, videoAttributes)
202 }
203
204 const resVideos = await getVideosList(server.url)
205 video = resVideos.body.data.find(v => v.name === 'my super video 1')
206
207 for (let i = 0; i < 10; i++) {
208 const text = 'my super first comment'
209 const res = await addVideoCommentThread(server.url, server.accessToken, video.id, text)
210 threadId = res.body.comment.id
211
212 const text1 = 'my super answer to thread 1'
213 const childCommentRes = await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text1)
214 const childCommentId = childCommentRes.body.comment.id
215
216 const text2 = 'my super answer to answer of thread 1'
217 await addVideoCommentReply(server.url, server.accessToken, video.id, childCommentId, text2)
218
219 const text3 = 'my second answer to thread 1'
220 await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text3)
221 }
222
223 for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
224 await createVideoCaption({
225 url: server.url,
226 accessToken: server.accessToken,
227 language: caption,
228 videoId: video.id,
229 fixture: 'subtitle-good2.vtt'
230 })
231 }
232
233 return { server, video, threadId }
234}