diff options
Diffstat (limited to 'scripts/benchmark.ts')
-rw-r--r-- | scripts/benchmark.ts | 234 |
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 @@ | |||
1 | import { registerTSPaths } from '../server/helpers/register-ts-paths' | ||
2 | registerTSPaths() | ||
3 | |||
4 | import * as autocannon from 'autocannon' | ||
5 | import { | ||
6 | addVideoCommentReply, | ||
7 | addVideoCommentThread, | ||
8 | createVideoCaption, | ||
9 | flushAndRunServer, | ||
10 | getVideosList, | ||
11 | killallServers, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers, | ||
14 | uploadVideo | ||
15 | } from '@shared/extra-utils' | ||
16 | import { Video, VideoPrivacy } from '@shared/models' | ||
17 | import { writeJson } from 'fs-extra' | ||
18 | |||
19 | let server: ServerInfo | ||
20 | let video: Video | ||
21 | let threadId: number | ||
22 | |||
23 | const outfile = process.argv[2] | ||
24 | |||
25 | run() | ||
26 | .catch(err => console.error(err)) | ||
27 | .finally(() => { | ||
28 | if (server) killallServers([ server ]) | ||
29 | }) | ||
30 | |||
31 | function buildAuthorizationHeader () { | ||
32 | return { | ||
33 | Authorization: 'Bearer ' + server.accessToken | ||
34 | } | ||
35 | } | ||
36 | |||
37 | async 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 | |||
148 | function 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 | |||
177 | async 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 | } | ||