aboutsummaryrefslogtreecommitdiff
path: root/doc/dev/metrics/heap_and_download_size.md
blob: 484a57312e9f82823ded38712d32786d50d0ce43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
# Project 101 measurements: Heap usage, download size.

This describes the initial measurement strategy for certain Project 101
metrics.  Namely, we are trying to find:

> 1. Amount of non-mapped memory allocated when used for example workloads.
> 2. The size of the client library for Tor and Arti.

There are lots of ways to measure each of these.  For now I'll aim for
reproducibility and simplicity, at the expense of having to make certain
simplifying assumptions.  As we refine our implementations, we should
also improve our measurements here to better reflect reality.

As we do so, we will ensure our methodology remains reproducible, so
that we can show how much of our changed size is an artifact of our
methodology, and how much of it is real improvements or regressions.

## Configuration files

Please make sure your `~/.arti-testing.toml` file contains the following:

```toml
[storage]

cache_dir = "${USER_HOME}/.arti_testing/cache"
state_dir = "${USER_HOME}/.arti_testing/state"
```

## Memory usage

We're looking specifically at non-mapped memory: That is, heap memory
that isn't backed by a file on "disk".  We're concerned about peak
memory demand, memory can be scarce on cheap devices.

There are many possible loads we could look at here. We will add more
loads in the future, but for now, we'll focus on two cases:

1. Bootstrapping a directory from scratch and making a connection to
   `www.torproject.org`.

2. Starting with a cached directory and making a connection to
   `www.torproject.org`.

These tests are better measures for the efficiency of our directory
storage implementation than they are for our data paths, but that is
reasonable for now: Directory size accounts for the largest portion of
client heap usage right now.

To run these tests, we clear our `${USER_HOME}/.arti-testing/cache` directory,
and run the following command _twice_.  (The first time will download the
directory, the second will use the cache.)

```
valgrind --tool=massif ./target/release/arti-testing connect \
  -c ~/.arti-testing.toml \
  --target www.torproject.org:80
```

The results for 20 July 2022 were:

```
Bootstrapping: 20.3 MiB
Cached: 14.7 MiB
```

The results for 30 September 2022 were (Arti: 0d985b0d):

```
Bootstrapping: 18.9 MiB
Cached: 14.4 MiB
```

The results for 25 October 2022 were (Arti: 547d476e0e):

```
Bootstrapping: 18.2 MiB
Cached: 13.6 MiB
```

The results for  25 January 2023 were (Arti: 3b2848f904):

```
Bootstrapping: 20.7 MiB
Cached: 14.0 MiB
```

The results for 11 April 2023 were (Arti: 2bcd89615):

```
Bootstrapping: 19.8 MiB
Cached: 13.8 MiB
```

The results for 6 July 2023 were (Arti: 1ae06399d03):

```
Bootstrapping: 19.5 MiB
Cached: 13.7 MiB
```

The results for 24 October 2023 were (Arti: 99d8b3a16c283ce6):

```
Bootstrapping: 26.3 MiB
Cached: 21.4 MiB
```

Results as of 18 December 2023 (Arti: 4577399b985f3)

```
Bootstrapping: 28.3 MiB
Cached: 22.0 MiB
```

The results for 30 April 2024 were (Arti: b30ca794cbfe):

```
Bootstrapping: 29.1 MiB
Cached: 23.3 MiB
```

The results for 30 June 2024 were (Arti: dba7b7206eb71):

```
Bootstrapping: 27.4 MiB
Cached: 21.5 MiB
```

The results for 30 September 2024 were (Arti: cf0b8292f71c):

```
Bootstrapping: 28.5 MiB
Cached: 22.2 MiB
```

The results for 31 December 2024 were (Arti: 99f1ba647f08):

```
Bootstrapping: 27.9 MiB
Cached: 22.4 MiB
```

The results for 30 June 2025 were (Arti: ee8e66f6b0db6):

```
Bootstrapping: 27.6 MiB
Cached: 22.9 MiB
```

The results for 30 September 2025 were (Arti: e630b2641e91):

```
Bootstrapping: 26.8 MiB
Cached: 22.5 MiB
```

To simulate (almost) the same process with C Tor, run Tor under `massif`
with a new data directory, then kill it with ctrl-C:

```
 rm -rf newdir
 valgrind --tool=massif src/app/tor --datadir newdir
 (Wait for bootstrap)
 <Ctrl-C>
```

The results for 20 July 2022 were:

```
Bootstrapping: 18.8 MiB
Cached: 21.9 MiB
```

The results for 30 September 2022 were (Tor: 18b5630a7c):

```
Bootstrapping: 18.5 MiB
Cached: 21.4 MiB
```

The results for 25 October 2022 were (Tor: 2033cc7b5e):

```
Bootstrapping: 18.4 MiB
Cached: 19.9 MiB
```

The results for 25 January 2023 were (Tor: 21109ba5d):

```
Bootstrapping: 18.5 MiB
Cached: 19.8 MiB
```

The results for 11 April 2023 were (Tor: 447775a5e):

```
Bootstrapping: 18.5 MiB
Cached: 19.6 MiB
```

The results for 6 July 2023 were (Tor: 05624b578152f3b):

```
Bootstrapping: 18.4 MiB
Cached: 19.4 MiB
```

The results for 24 October 2023 were (Tor: 2a1fc47d8683fa7):

```
Bootstrapping: 19.1 MiB
Cached: 19.9 MiB
```

The results for 18 December 2023 were (Tor: 0cccc7223c52512):

```
Bootstrapping: 21.2 MiB
Cached: 21.8 MiB
```

The results for 30 April 2024 were (Tor: 51ef4ce09438):

```
Bootstrapping: 23.2 MiB
Cached: 22.8 MiB
```

The results for 30 June 2024 were (Tor: 8bb8ac2d9aba72):

```
Bootstrapping: 22.1 MiB
Cached: 21.7 MiB
```

The results for 30 September 2024 were (Tor: 0d87dc1ee79):

```
Bootstrapping: 23.4 MiB
Cached: 22.9 MiB
```

The results for 31 December 2024 were (Tor: a789ab32f2191):

```
Bootstrapping: 22.8 MiB
Cached: 22.1 MiB
```

The results for 30 June 2025 were (Tor: b2790caacc1):

```
Bootstrapping: 23.1 MiB
Cached: 22.7 MiB
```

The results for 30 September 2025 were (Tor: 0b2071003):

```
Bootstrapping: 22.9 MiB
Cached: 22.5 MiB
```

(This does not yet take into account making a request, but again, the
memory requirements there are negligible in comparison to loading the
directory.)

### Analysis

I'm fairly happy with these results: Arti has not been optimized very
heavily, whereas we've been trying to make Tor use less memory for years
and years.  Looking at the profiles, I see several places where I think
we have a good chance at making Arti use even less RAM.


## Library size

### Preliminaries

With C Tor, download size has been a barrier to mobile adoption, so
we're trying to keep the download size for Arti smaller.

There are some barriers to doing an apples-to-apples comparison with
these two programs at present:

1. Arti does not currently support being built as a shared library: only
   in a static form that gets linked into a binary.

2. Arti currently builds with LTO[^LTO] to a much higher degree than C
   Tor, giving it a compiler advantage that C Tor could easily adopt.

3. Arti and C Tor have different sets of dependencies that may or may
   not be installed on different platforms, and may or may not be
   _required_ on different platforms.


So we'll work under these assumptions and limitations:

1. We're primarily interested in compressed download size.  We'll use
   gzip for compression, since it delivers performance comparable to
   that used for mobile platform archive formats.

2. We don't intend to ship with full debugging symbols, but we do want
   to ship with enough debugging information for stack traces to work.
   We approximate this compromise with `strip --strip-debug`.

3. We'll compile for x86_64 (since that's what we're using for
   development), and assume that binaries compiled for or other CPUs
   (notably ARM64) will not be too different—or at least, that they will
   exhibit similar savings (or not).

4. We'll disable all optional features in C Tor that clients do not use.

5. We'll look at binary size for now, instead of library size. (This
   approach disadvantages Arti, since Tor has no code that is discarded
   when building as a library, and Arti has a bunch of code that is
   CLI-only.)

6. We'll link statically to as many dependencies as we can among those
   not present on Android, and choose smaller dependencies when there
   are alternatives.  (This approach simulates having to ship
   dependencies along with the main binary, to better approximate total
   download size.)

7. We'll use Clang as our C compiler (since it uses the same LLVM
   backend as the Rust compiler).

### Process with Arti

```
./maint/binary_size -p arti \
    --no-default-features \
    --features=tokio,rustls,static-sqlite
```

Note that we are linking statically with SQLite, and using RustTLS
instead of OpenSSL in order to save download size.


Result as of 20 July 2022:

```
   "arti.gz": 4076384 bytes
```

Results for 30 September 2022 were (Arti: 0d985b0d):

```
   "arti.gz": 3918795 bytes
```

Results as of 25 October 2022 (Arti: 547d476e0e):

```
   "arti.gz": 3937197 bytes
```

Results as of 25 January 2023 (Arti: 3b2848f904):

```
   "arti.gz": 3668559 bytes
```

Results as of 11 April 2023 (Arti: 2bcd89615):

```
   "arti.gz": 3747298 bytes
```

Results as of 6 July 2023 (Arti: 1ae06399d03):

```
   "arti.gz": 3723582 bytes
```

Results as of 24 October 2023 (Arti: 99d8b3a16c283ce6)

```
   "arti.gz": 6741218 bytes
```

Results as of 18 December 2023 (Arti: 4577399b985f3)

```
   "arti.gz": 3992937 bytes
```

Results as of 30 April 2024 (Arti: b30ca794cbfe)

```
   "arti.gz": 4049193 bytes
```

Results as of 30 June 2024 (Arti: dba7b7206eb71)

```
   "arti.gz": 4173380 bytes
```

Results as of 30 September 2024 (Arti: cf0b8292f71c)

```
   "arti.gz": 4048432 bytes
```

Results as of 31 December 2024 (Arti: 99f1ba647f08)

```
   "arti.gz": 4172555 bytes
```

Results as of 30 June 2025 (Arti: ee8e66f6b0db6)

```
   "arti.gz": 4274926 bytes
```

Results as of 30 September 2025 (Arti: e630b2641e91)

Alex notes: new laptop and new Debian version.

```
   "arti.gz": 4273388 bytes
```

### Process with C Tor


```
./configure \
   CC=clang \
   --enable-static-libevent --with-libevent-dir=${STATIC_LIBEVENT_DIR} \
   --enable-static-openssl --with-openssl-dir=${STATIC_OPENSSL_DIR} \
   --disable-module-relay \
   --disable-module-dirauth \
   --disable-systemd

make clean
make src/app/tor
strip --strip-debug src/app/tor
gzip -9 -c src/app/tor | wc -c
```

Note that this process includes Libevent and Openssl linked statically
with Tor: These aren't part of the download size on most Unix-like
operating systems, but they do have to be downloaded on Android,
Windows, and OSX.

Result (20 July 2022)

```
3646863 bytes
```

Results (30 September 2022) with Tor: 18b5630a7c:

```
3647161 bytes
```

Results (25 October 2022) with Tor: 2033cc7b5e:

```
3648355 bytes
```

Results (25 January 2023) with Tor: 21109ba5d:

```
3647837 bytes
```

Results (11 April 2023) with Tor: 447775a5e:

```
3646434 bytes
```

The results for 6 July 2023 were (Tor: 05624b578152f3b):

```
3504633 bytes
```

The results of 24 October 2023 were (Tor: 2a1fc47d8683fa7):

```
3976434 bytes
```

The results of 18 December 2023 were (Tor: 0cccc7223c52512):

```
3984528 bytes
```

The results for 30 April 2024 were (Tor: 51ef4ce09438):

```
4001484 bytes
```

The results for 30 June 2024 were (Tor: 8bb8ac2d9aba72):

```
4001228 bytes
```

The results for 30 September 2024 were (Tor: 0d87dc1ee79):

```
4001072 bytes
```

The results for 31 December 2024 were (Tor: a789ab32f2191):

```
4001216 bytes
```

The results for 30 June 2025 were (Tor: b2790caacc1):

```
4005344 bytes
```

The results for 30 September 2025 were (Tor: 0b2071003):

Alex notes: new laptop and new Debian version.

```
4007468 bytes
```

[^LTO]: Link-time optimization: a technique where the compiler optimizes
    the whole program as a single unit, to take advantage of properties
    that cannot be found while compiling a single module.

### Analysis

The Arti download currently stands bigger than the Tor download.  But
for a number of caveats, see the initial list of assumptions above.

Note in particular Android is a worst-case scenario for download size,
since neither Arti nor Tor can use Android's built-in TLS
implementations, and so both need to include a TLS library.  (OpenSSL is
the best option with Tor; Rustls is the smallest with Arti.)  I expect
that it will be fairly easy to deliver an Arti download that's smaller
than Tor on Windows, iOS, or OSX, if we are not there already.

There are several avenues for trying to make Arti's download size
smaller in the future.  Most of them come down to identifying the
largest libraries used by Arti, and replacing them with smaller
alternatives.

Some small part of the current download size of Arti is an artifact of
comparing Arti's binary size to Tor's binary size, and not looking at
library sizes directly. I expect that once we are able to compare both
programs built as a library, we'll see a some modest savings there.

I think that as we continue development, we'll expect to see some
savings in Arti if as we find initial low-hanging fruit to eliminate,
and some regressions as we add more missing features.  I do not think we
will achieve a smaller download than C _on Android_ without major
engineering.

## Methodologies

We use the Valgrind tool, massif, to extract heap information over the
execution duration of the program. We use the `massif-visualizer` tool to
extract peak values from the massif results.

Since there is variance in these results that are outside of our control here,
such as difference between paths through the Tor network, it is important that
when running these tests that you run the experiments multiple times and take
the median value.