]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - scripts/benchmark.ts
Fix benchmark
[github/Chocobozzz/PeerTube.git] / scripts / benchmark.ts
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 function buildAPHeader () {
38 return {
39 Accept: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
40 }
41 }
42
43 async function run () {
44 console.log('Preparing server...')
45
46 await prepare()
47
48 const tests = [
49 {
50 title: 'AP - account peertube',
51 path: '/accounts/peertube',
52 headers: buildAPHeader(),
53 expecter: (body, status) => {
54 return status === 200 && body.startsWith('{"type":')
55 }
56 },
57 {
58 title: 'AP - video',
59 path: '/videos/watch/' + video.uuid,
60 headers: buildAPHeader(),
61 expecter: (body, status) => {
62 return status === 200 && body.startsWith('{"type":"Video"')
63 }
64 },
65 {
66 title: 'Misc - webfinger peertube',
67 path: '/.well-known/webfinger?resource=acct:peertube@' + server.host,
68 expecter: (body, status) => {
69 return status === 200 && body.startsWith('{"subject":')
70 }
71 },
72 {
73 title: 'API - unread notifications',
74 path: '/api/v1/users/me/notifications?start=0&count=0&unread=true',
75 headers: buildAuthorizationHeader(),
76 expecter: (_body, status) => {
77 return status === 200
78 }
79 },
80 {
81 title: 'API - me',
82 path: '/api/v1/users/me',
83 headers: buildAuthorizationHeader(),
84 expecter: (body, status) => {
85 return status === 200 && body.startsWith('{"id":')
86 }
87 },
88 {
89 title: 'API - videos list',
90 path: '/api/v1/videos',
91 expecter: (body, status) => {
92 return status === 200 && body.startsWith('{"total":10')
93 }
94 },
95 {
96 title: 'API - video get',
97 path: '/api/v1/videos/' + video.uuid,
98 expecter: (body, status) => {
99 return status === 200 && body.startsWith('{"id":')
100 }
101 },
102 {
103 title: 'API - video captions',
104 path: '/api/v1/videos/' + video.uuid + '/captions',
105 expecter: (body, status) => {
106 return status === 200 && body.startsWith('{"total":4')
107 }
108 },
109 {
110 title: 'API - video threads',
111 path: '/api/v1/videos/' + video.uuid + '/comment-threads',
112 expecter: (body, status) => {
113 return status === 200 && body.startsWith('{"total":10')
114 }
115 },
116 {
117 title: 'API - video replies',
118 path: '/api/v1/videos/' + video.uuid + '/comment-threads/' + threadId,
119 expecter: (body, status) => {
120 return status === 200 && body.startsWith('{"comment":{')
121 }
122 },
123 {
124 title: 'HTML - video watch',
125 path: '/videos/watch/' + video.uuid,
126 expecter: (body, status) => {
127 return status === 200 && body.includes('<title>my super')
128 }
129 },
130 {
131 title: 'HTML - video embed',
132 path: '/videos/embed/' + video.uuid,
133 expecter: (body, status) => {
134 return status === 200 && body.includes('embed')
135 }
136 },
137 {
138 title: 'HTML - homepage',
139 path: '/',
140 expecter: (_body, status) => {
141 return status === 200
142 }
143 },
144 {
145 title: 'API - config',
146 path: '/api/v1/config',
147 expecter: (body, status) => {
148 return status === 200 && body.startsWith('{"instance":')
149 }
150 }
151 ]
152
153 const finalResult: any[] = []
154
155 for (const test of tests) {
156 console.log('Running against %s.', test.path)
157 const testResult = await runBenchmark(test)
158
159 Object.assign(testResult, { title: test.title, path: test.path })
160 finalResult.push(testResult)
161
162 console.log(autocannon.printResult(testResult))
163 }
164
165 if (outfile) await writeJson(outfile, finalResult)
166 }
167
168 function runBenchmark (options: {
169 path: string
170 headers?: { [ id: string ]: string }
171 expecter: Function
172 }) {
173 const { path, expecter, headers } = options
174
175 return new Promise((res, rej) => {
176 autocannon({
177 url: server.url + path,
178 connections: 20,
179 headers,
180 pipelining: 1,
181 duration: 10,
182 requests: [
183 {
184 onResponse: (status, body) => {
185 if (expecter(body, status) !== true) {
186 console.error('Expected result failed.', { body, status })
187 throw new Error('Invalid expectation')
188 }
189 }
190 }
191 ]
192 }, (err, result) => {
193 if (err) return rej(err)
194
195 return res(result)
196 })
197 })
198 }
199
200 async function prepare () {
201 server = await flushAndRunServer(1, {
202 rates_limit: {
203 api: {
204 max: 5_000_000
205 }
206 }
207 })
208 await setAccessTokensToServers([ server ])
209
210 const videoAttributes = {
211 name: 'my super video',
212 category: 2,
213 nsfw: true,
214 licence: 6,
215 language: 'fr',
216 privacy: VideoPrivacy.PUBLIC,
217 support: 'please give me a coffee',
218 description: 'my super description'.repeat(10),
219 tags: [ 'tag1', 'tag2', 'tag3' ]
220 }
221
222 for (let i = 0; i < 10; i++) {
223 Object.assign(videoAttributes, { name: 'my super video ' + i })
224 await uploadVideo(server.url, server.accessToken, videoAttributes)
225 }
226
227 const resVideos = await getVideosList(server.url)
228 video = resVideos.body.data.find(v => v.name === 'my super video 1')
229
230 for (let i = 0; i < 10; i++) {
231 const text = 'my super first comment'
232 const res = await addVideoCommentThread(server.url, server.accessToken, video.id, text)
233 threadId = res.body.comment.id
234
235 const text1 = 'my super answer to thread 1'
236 const childCommentRes = await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text1)
237 const childCommentId = childCommentRes.body.comment.id
238
239 const text2 = 'my super answer to answer of thread 1'
240 await addVideoCommentReply(server.url, server.accessToken, video.id, childCommentId, text2)
241
242 const text3 = 'my second answer to thread 1'
243 await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text3)
244 }
245
246 for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
247 await createVideoCaption({
248 url: server.url,
249 accessToken: server.accessToken,
250 language: caption,
251 videoId: video.id,
252 fixture: 'subtitle-good2.vtt'
253 })
254 }
255
256 return { server, video, threadId }
257 }