Commit Graph

2564 Commits

Author SHA1 Message Date
Bartosz Taudul
1f4dbd1b2e Parallelize background jobs. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
a48e804e96 Don't reconstruct mem alloc plot in no-statistics builds. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
ac84e77333 Ghost zones display prototype. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
4e4ee2ff2c Add number of call stack samples to thread tooltip. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
77d30adee9 Add per-thread ghost zones switch. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
6daa429b69 Add hidden ghost zones indicator. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
4384b812f1 Smaller nested checkboxes. 2020-03-19 00:35:18 +01:00
Bartosz Taudul
335866be88 Add UI to control ghost zones drawing.
Disabled for now, will be needed in future.
2020-03-19 00:35:18 +01:00
Bartosz Taudul
adb45ed5df Allow checking if ghost zones are ready. 2020-03-17 00:16:39 +01:00
Bartosz Taudul
2f674833b2 Add ghost zones display to view options. 2020-03-16 23:05:07 +01:00
Bartosz Taudul
eb5f7a27e7 Match ghost zones by symbol address. 2020-03-16 23:05:07 +01:00
Bartosz Taudul
b89874850f Pack frame identifiers in ghost zones. 2020-03-16 23:05:07 +01:00
Bartosz Taudul
ead597bacc Display count of ghost zones. 2020-03-16 23:05:07 +01:00
Bartosz Taudul
452341059b Build ghost zones tree. 2020-03-16 23:05:06 +01:00
Bartosz Taudul
693db74380 Add CallstackFrameId comparator. 2020-03-16 23:05:06 +01:00
Bartosz Taudul
377ed48416 Don't over-reserve map. 2020-03-16 23:05:06 +01:00
Bartosz Taudul
aeb3bc410b Pack FrameImage struct. 2020-03-16 23:05:06 +01:00
Bartosz Taudul
c06ea4a3e8 Fix layout. 2020-03-16 23:04:50 +01:00
Bartosz Taudul
b8cc3f59d6 Count number of input and compressed frame image bytes. 2020-03-14 14:35:57 +01:00
Bartosz Taudul
0776dddc35 Display image compression ratio in bits per pixel. 2020-03-14 13:10:15 +01:00
Bartosz Taudul
20a7bf2b23 There are no parents for mid-stack frames. 2020-03-14 02:06:39 +01:00
Bartosz Taudul
1bb7d05ba0 Display time percentage in statistics menu. 2020-03-14 01:47:18 +01:00
Bartosz Taudul
5046664b8b Use "self time" consistently in the UI. 2020-03-14 01:38:46 +01:00
Bartosz Taudul
4631d884d6 Cleanup samples vector. 2020-03-10 21:46:24 +01:00
Bartosz Taudul
09d54cf9d9 Display custom lock names. 2020-03-08 13:59:31 +01:00
Bartosz Taudul
e7240cb77d Custom lock name transfer. 2020-03-08 13:47:38 +01:00
Bartosz Taudul
9668234903 Allow requesting reconnect on trace discard. 2020-03-06 22:11:17 +01:00
Bartosz Taudul
d25614d50f Allow address/port retrieval from View. 2020-03-06 22:11:00 +01:00
Bartosz Taudul
50123298a7 Unify texture compression implementations. 2020-03-02 02:08:14 +01:00
Bartosz Taudul
aa0bf47ec3 Extract texture compression functionality. 2020-03-02 02:00:35 +01:00
Bartosz Taudul
0df309b45c Forward declare LockType. 2020-03-02 01:58:48 +01:00
Bartosz Taudul
abd44069ae Fix off-by-one. 2020-03-01 14:04:10 +01:00
Bartosz Taudul
c36ed4b8b8 Boring warning fixes. 2020-03-01 01:48:20 +01:00
Bartosz Taudul
8f9ba5d54a Rearrange UI. 2020-03-01 01:32:31 +01:00
Bartosz Taudul
5887c9d12c Remove unused variable. 2020-03-01 01:28:56 +01:00
Bartosz Taudul
e93b574c5d Fill-in missing image name. 2020-03-01 01:27:21 +01:00
Bartosz Taudul
83316f1299 Fix pointer fixup. 2020-02-29 23:40:21 +01:00
Bartosz Taudul
d1ff99d6e3 Callstack frame map must not be touched by statistics. 2020-02-29 19:49:33 +01:00
Bartosz Taudul
8d5755521e Fix no statistics build. 2020-02-29 19:31:51 +01:00
Bartosz Taudul
de3a48f958 Better symbol information. 2020-02-29 19:28:42 +01:00
Bartosz Taudul
07756476b0 Allow viewing global entry stats of a callstack. 2020-02-29 18:59:01 +01:00
Bartosz Taudul
39361f71a1 Allow GetSymbolStats() to fail gracefully. 2020-02-29 18:59:01 +01:00
Bartosz Taudul
9b53792f20 Add call stack sample parents window. 2020-02-29 18:59:01 +01:00
Bartosz Taudul
2589b45af0 Add accessors for new data. 2020-02-29 18:39:45 +01:00
Bartosz Taudul
bc14ca86f3 Count proper number of parent stacks. 2020-02-29 17:58:17 +01:00
Bartosz Taudul
c18584fdbc Iterator may be invalidated. 2020-02-29 17:08:02 +01:00
Bartosz Taudul
4843a1d458 Collect parent call stacks for symbols. 2020-02-29 16:41:22 +01:00
Bartosz Taudul
90f5ae536c Display count of parent call stacks and frames. 2020-02-29 16:32:33 +01:00
Bartosz Taudul
6cc4de8d28 Construct parent call stacks for sampled stack traces. 2020-02-29 16:24:15 +01:00
Bartosz Taudul
935eb4cc61 Use xxh3 for VarArray hashing. 2020-02-29 15:31:05 +01:00
Bartosz Taudul
bdc86f5338 Process postponed samples when new frame data is available. 2020-02-29 14:12:04 +01:00
Bartosz Taudul
0d112e20a5 Don't perform unnecessary hashmap search. 2020-02-29 13:58:11 +01:00
Bartosz Taudul
3412d2232f Postpone processing incomplete sampled callstacks. 2020-02-29 13:45:50 +01:00
Bartosz Taudul
7947087694 Print frame image compression ration. 2020-02-29 00:49:42 +01:00
Bartosz Taudul
49a0072bab Use correct wording. 2020-02-27 23:11:45 +01:00
Bartosz Taudul
5f48f8a3aa Allow hiding symbols with unknown location. 2020-02-27 19:45:41 +01:00
Bartosz Taudul
fea3444625 Use percent print wrapper in more places. 2020-02-27 17:20:34 +01:00
Bartosz Taudul
4fa049188b Add total time percentage for entries in sampling statistics. 2020-02-27 17:05:56 +01:00
Bartosz Taudul
e438e1c53d Add another percent print helper. 2020-02-27 17:05:48 +01:00
Bartosz Taudul
c5e8739435 Live update of sample statistics data. 2020-02-27 16:48:50 +01:00
Bartosz Taudul
8aa70211c0 Display inline functions. 2020-02-27 15:28:58 +01:00
Bartosz Taudul
bc18862dc6 Allow displaying instruction location. 2020-02-27 15:10:50 +01:00
Bartosz Taudul
7dd929a39e Preserve symbol call location. 2020-02-27 15:07:29 +01:00
Bartosz Taudul
2e5ce52086 Implement reading 7 elements. 2020-02-27 15:07:29 +01:00
Bartosz Taudul
17e7add105 By default show self times in statistics menu. 2020-02-27 14:20:19 +01:00
Bartosz Taudul
be5793987e Don't send symbol name. 2020-02-27 12:49:48 +01:00
Bartosz Taudul
9d718eb1e8 Preserve inlined symbol names. 2020-02-27 12:39:05 +01:00
Bartosz Taudul
374ddbe2a6 Replace tabs with radio buttons. 2020-02-27 12:24:28 +01:00
Bartosz Taudul
8173f24515 Add filter to sampling statistics. 2020-02-27 02:31:30 +01:00
Bartosz Taudul
27466fc56b Add callstack sampling statistics. 2020-02-27 02:08:20 +01:00
Bartosz Taudul
852e37c8dd Calculate callstack sample data on trace load. 2020-02-27 01:22:36 +01:00
Bartosz Taudul
8288f7c6b7 No need to pack ZoneThreadData. 2020-02-27 01:00:41 +01:00
Bartosz Taudul
c99537c402 Provide default value for sourceLocationZonesReady. 2020-02-27 00:26:58 +01:00
Bartosz Taudul
75312c7bb6 Display count of symbols. 2020-02-26 23:02:39 +01:00
Bartosz Taudul
a35795f793 Use more appropriate name. 2020-02-26 23:02:34 +01:00
Bartosz Taudul
4511a4de8c Save/load symbol information. 2020-02-26 22:53:18 +01:00
Bartosz Taudul
847069a59d Expose symbol source location data. 2020-02-26 22:46:02 +01:00
Bartosz Taudul
26cee8acf0 Perform symbol information queries. 2020-02-26 22:35:15 +01:00
Bartosz Taudul
02c99fca67 Enable display of symbol address in callstack window. 2020-02-26 19:16:27 +01:00
Bartosz Taudul
8f36ee2c89 Display module name in callstack window. 2020-02-26 01:04:51 +01:00
Bartosz Taudul
eb7e8162ff Handle module names on server side. 2020-02-26 00:55:43 +01:00
Bartosz Taudul
d6c0720f8a Save/load sampling period. 2020-02-25 23:46:16 +01:00
Bartosz Taudul
af58649113 Store symbol addresses. 2020-02-25 23:42:59 +01:00
Bartosz Taudul
ca894be51d Store sampling period on server. 2020-02-25 23:13:28 +01:00
Bartosz Taudul
4695f60937 Fix display of kernel addresses. 2020-02-24 23:04:53 +01:00
Bartosz Taudul
9e1c24f93e Add icon to filter entry boxes. 2020-02-24 01:33:12 +01:00
Bartosz Taudul
2e3b13ced5 Optional frame image display in messages list. 2020-02-24 01:29:57 +01:00
Bartosz Taudul
d63a15a570 Don't init unused memory on vector realloc.
Warning, this change may break things in unexpected ways!
2020-02-23 20:20:19 +01:00
Bartosz Taudul
d150e688f5 Simpler vector init. 2020-02-23 19:47:09 +01:00
Bartosz Taudul
00d91cb9ab Optimize slab allocation. 2020-02-23 19:43:00 +01:00
Bartosz Taudul
085e1fd43f Deduplicate code. 2020-02-23 19:16:33 +01:00
Bartosz Taudul
37d9a20b4a Use caret right to indicate inlined frames, instead of "--". 2020-02-23 16:08:00 +01:00
Bartosz Taudul
7f5e23f2ac Handle one more case of duplicate samples. 2020-02-23 15:57:36 +01:00
Bartosz Taudul
625d380f7a Return value is not used. 2020-02-23 15:53:23 +01:00
Bartosz Taudul
759fd15c03 Don't load vector size twice. 2020-02-23 15:35:08 +01:00
Bartosz Taudul
31d2bc1740 Fix typo. 2020-02-23 11:49:01 +01:00
Bartosz Taudul
358de714c8 Don't use "???" external thread name. 2020-02-23 11:39:51 +01:00
Bartosz Taudul
2ec3813cb3 Collapse multiple callstack samples. 2020-02-23 00:24:04 +01:00
Bartosz Taudul
5e2390604d Use proper check for "draw stack samples" option visibility. 2020-02-22 23:20:59 +01:00
Bartosz Taudul
90277953c7 Replace duplicate samples. 2020-02-22 21:36:27 +01:00
Bartosz Taudul
6532f622cb Mute color of unknown call frames. 2020-02-22 21:17:36 +01:00
Bartosz Taudul
4273939cf5 Local threads must have at least one zone captured. 2020-02-22 18:52:38 +01:00
Bartosz Taudul
d4f9810006 Draw callstack sample data. 2020-02-22 18:52:38 +01:00
Bartosz Taudul
b425374cb7 Add callstack samples drawing option. 2020-02-22 18:52:38 +01:00
Bartosz Taudul
597911e5a8 Save/load callstack samples. 2020-02-22 18:52:38 +01:00
Bartosz Taudul
ca39c9877e Display number of callstack samples. 2020-02-22 18:52:37 +01:00
Bartosz Taudul
437771ea85 Process callstack sample data. 2020-02-22 18:52:37 +01:00
Bartosz Taudul
ba0715b295 Replace remaining manual children checks with HasChildren(). 2020-02-21 00:36:45 +01:00
Bartosz Taudul
ecc9369da2 Return zone extra during allocation. 2020-02-20 23:39:40 +01:00
Bartosz Taudul
4bf0af321f Wrapper for allocation and retrieval of zone extra. 2020-02-20 23:37:55 +01:00
Bartosz Taudul
217c16de20 Display exact start and end time for CPU data. 2020-02-20 23:21:54 +01:00
Bartosz Taudul
c5dbd749e7 Combine ContextSwitchCpu writes. 2020-02-20 02:09:09 +01:00
Bartosz Taudul
54573fb970 Combine ContextSwitchData writes. 2020-02-20 02:05:23 +01:00
Bartosz Taudul
d96fcc95c2 Update list of tracy callstack frames. 2020-02-20 00:31:38 +01:00
Bartosz Taudul
b138db9c4d Display mode in find zone menu. 2020-02-19 23:33:39 +01:00
Bartosz Taudul
b26f642c6e Change "average" to "mean". 2020-02-19 23:29:18 +01:00
Bartosz Taudul
d4f99e4459 Perform cheaper check first. 2020-02-19 22:43:37 +01:00
Bartosz Taudul
25f6c5f884 Disable charconv on gcc/clang.
Because there's no way to check whether libstdc++ and libc++ finally
decided to implement the standard fully.
2020-02-13 19:22:08 +01:00
Bartosz Taudul
3140dbb34a Size is never zero at start. 2020-02-13 18:41:32 +01:00
Bartosz Taudul
c870b10387 Offset in just-read block is always zero. 2020-02-13 18:39:46 +01:00
Bartosz Taudul
26584b00c3 Issue just one read call per zone.
Separate reads are issued only for first and last of children.
2020-02-13 18:11:54 +01:00
Bartosz Taudul
ebf2c3ad5b No need to check if file has ended. 2020-02-13 15:41:20 +01:00
Bartosz Taudul
4d892cbae9 Preload next block size. 2020-02-13 15:37:37 +01:00
Bartosz Taudul
232379c72c Optimize reading CPU data. 2020-02-13 01:14:12 +01:00
Bartosz Taudul
c03b8b72da Optimize reading context switches. 2020-02-13 01:12:01 +01:00
Bartosz Taudul
3bb0f33dcc Optimize reading plot data. 2020-02-13 01:04:40 +01:00
Bartosz Taudul
c0a2e9b3f7 Ditto during capture. 2020-02-13 00:54:54 +01:00
Bartosz Taudul
cc0f1f514c Store memory event time and thread data together. 2020-02-13 00:52:29 +01:00
Bartosz Taudul
f9b19631c0 Read memory data in one go. 2020-02-13 00:37:54 +01:00
Bartosz Taudul
51e04673c6 8-element reader wrapper. 2020-02-13 00:35:20 +01:00
Bartosz Taudul
8e825d91e0 Keep refTime in a register. 2020-02-12 20:59:36 +01:00
Bartosz Taudul
39d24d0d4a Set start and srcloc in one go. 2020-02-12 20:46:56 +01:00
Bartosz Taudul
5c6bfcbeee Add combined start + srcloc setter for ZoneEvent. 2020-02-12 20:46:56 +01:00
Bartosz Taudul
354115ef9b Reduce granularity of zone reading progress updates. 2020-02-12 20:03:14 +01:00
Bartosz Taudul
1492536bdb Handle FileReadError. 2020-02-12 19:53:37 +01:00
Bartosz Taudul
eb79507501 Read files using mmap. 2020-02-12 19:43:05 +01:00
Bartosz Taudul
3b345aab37 FileRead::IsEOF() is no longer used. 2020-02-12 19:27:15 +01:00
Bartosz Taudul
cc805b7b74 Add mmap() wrapper. 2020-02-12 19:24:30 +01:00
Bartosz Taudul
fa1747bdb2 Faster total zone count calculation during loading. 2020-02-12 19:15:46 +01:00
Bartosz Taudul
e88df069bd Load zone child number along with zone data. 2020-02-12 02:14:21 +01:00
Bartosz Taudul
925909aa3a Wrapper for reading 6 elements at once. 2020-02-12 02:13:50 +01:00
Bartosz Taudul
1655bf284f More Int24/Int48 optimizations. 2020-02-12 02:00:26 +01:00
Bartosz Taudul
f562ff780c Don't care about atomic increments of counters. 2020-02-12 00:53:03 +01:00
Bartosz Taudul
88f3e554da Read all CPU zone variables at once. 2020-02-12 00:36:59 +01:00
Bartosz Taudul
5227bc3549 Read all GPU zone variables at once. 2020-02-12 00:34:09 +01:00
Bartosz Taudul
6cab3dcd3a Helper for reading 5 variables. 2020-02-12 00:32:00 +01:00
Bartosz Taudul
00ab76fa19 Discard scratch buffer tricks for better performance. 2020-02-12 00:29:45 +01:00
Bartosz Taudul
e0ec98d766 Keep ztime in register. 2020-02-11 23:20:38 +01:00
Bartosz Taudul
86644ecda0 Store intermediate results in registers, not in memory. 2020-02-11 02:35:50 +01:00
Bartosz Taudul
caace1ce11 Directly access memory, omitting shift.
As always, clang generated the right code here anyways...
2020-02-11 02:24:40 +01:00
Bartosz Taudul
5a995d804b Draw zig-zag as a single stroke. 2020-02-10 23:34:33 +01:00
Bartosz Taudul
06cd57fe6e Delay rounding h/2. 2020-02-10 23:24:58 +01:00
Bartosz Taudul
d80e7cc025 Remove unnecessary round() calls. 2020-02-10 23:20:35 +01:00
Bartosz Taudul
eff040dca6 Optimize drawing zig-zags. 2020-02-10 22:53:59 +01:00
Bartosz Taudul
ad3aa73085 Change order of background tasks.
Now tasks are performed in the following order:
- Context switch based CPU usage graph.
- Memory allocations plot.
- Zone statistics.

This prioritizes appearance of the most notable things first.
2020-02-10 22:31:10 +01:00
Bartosz Taudul
6f4a10be04 Optimize Int48 reconstruction. 2020-02-10 01:38:45 +01:00
Bartosz Taudul
76afef9117 Direct checks for context switch end validity. 2020-02-10 01:26:31 +01:00
Bartosz Taudul
ae0392a0e5 Don't needlessly convert doubles to integers. 2020-02-10 01:05:42 +01:00
Bartosz Taudul
d0c2a26ced Fix continuous frames tooltips.
At high zoom-out levels frame tooltip will be always displayed now for
continuous frame sets. This greatly helps with scrubbing to an
appropriate location, basing of frame images.
2020-02-10 00:41:18 +01:00
Bartosz Taudul
ffdd5290bf Clip wait regions display. 2020-02-10 00:12:34 +01:00
Bartosz Taudul
53e5eb749d Compress frame images using zstd.
Memory usage and trace load times:

!comp         587 MB,  439 ms  ->    541 MB,  523 ms    (92%, 119%)
android-vk    197 MB,  136 ms  ->    188 MB,  178 ms    (95%, 130%)
big2         4463 MB,  2.93 s  ->   4198 MB,  3.65 s    (94%, 124%)
fi            483 MB,  346 ms  ->    416 MB,  409 ms    (86%, 118%)
fi-big       3307 MB,  3.15 s  ->   2985 MB,  3.53 s    (90%, 112%)
large       19.74 GB, 10.05 s  ->  19.28 GB, 11.16 s    (97%, 110%)
2020-02-09 21:22:12 +01:00
Bartosz Taudul
ec5c7cf8a7 Reading zstd compressed traces. 2020-02-08 16:14:43 +01:00
Bartosz Taudul
145514687c Add zstd compression to FileWrite. 2020-02-08 16:14:43 +01:00
Bartosz Taudul
dd650e08ec Display saved trace size. 2020-02-08 13:07:02 +01:00
Bartosz Taudul
6f554d7f00 Gather file compression statistics. 2020-02-08 12:57:35 +01:00
Bartosz Taudul
068e752aa7 No charconv for MSVC < 16.4.
https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=vs-2019#note_charconv
2020-02-06 00:37:27 +01:00
Bartosz Taudul
db408df395 Explain combined values in trace info window. 2020-02-05 23:49:10 +01:00
Bartosz Taudul
7425cd7112 Also display non-user plot data count. 2020-02-05 23:41:53 +01:00
Bartosz Taudul
1bad607e6c Replace "2x" with "2×". 2020-02-05 23:37:03 +01:00
Bartosz Taudul
8624bb95ba Fix double separator in options, if no GPU zones are available. 2020-02-05 23:32:59 +01:00
Bartosz Taudul
9556878b23 Display appropriate notification when there's no message data. 2020-02-05 23:30:52 +01:00
Bartosz Taudul
9fc9f71666 Properly initialize callstack frame tree. 2020-02-05 23:16:18 +01:00
Bartosz Taudul
0bb6162a01 Allow sorting memory data listings. 2020-02-05 17:08:41 +01:00
Bartosz Taudul
9aecd43f24 Display exact time in find zone range limit information. 2020-02-03 19:34:51 +01:00
Bartosz Taudul
eca27b9d12 Display exact time, where appropriate. 2020-02-02 15:13:20 +01:00
Bartosz Taudul
e9be4934c4 Display plot item time. 2020-02-02 15:13:20 +01:00
Bartosz Taudul
b1342a10b0 Exact time printing functionality. 2020-02-02 15:13:20 +01:00
Bartosz Taudul
b418c55e89 Verify tiny int printing input. 2020-02-02 14:31:59 +01:00
Bartosz Taudul
182efc0b04 Limit timeline view to <-5,5> days range. 2020-02-02 14:11:42 +01:00
Bartosz Taudul
8627a31912 Maximum time range is 1.6 days. 2020-02-02 14:11:42 +01:00
Bartosz Taudul
ea4b64909f Fix 32-bit short_ptr. 2020-02-02 02:36:28 +01:00
Bartosz Taudul
b55fa19f72 Fix division by zero. 2020-02-01 18:01:24 +01:00
Bartosz Taudul
555203c46a Don't display unknown frames if there's no callstack frames. 2020-02-01 17:49:27 +01:00
Bartosz Taudul
024182b6a0 Fit trace description entry field to window width. 2020-02-01 17:36:51 +01:00
Bartosz Taudul
d680fa6cd6 Clip memory allocation lists. 2020-01-31 19:18:20 +01:00
Bartosz Taudul
a84eec1aef Clip found zones list. 2020-01-31 19:07:20 +01:00
Bartosz Taudul
f86fbe7fd5 Allow no-nonsense access to internal short_ptr pointer. 2020-01-31 19:06:21 +01:00
Bartosz Taudul
5f91b48e0c Clip child zone list submissions. 2020-01-31 18:58:31 +01:00
Bartosz Taudul
4a6bc284af Optimize "string (percentage)" printing. 2020-01-31 18:26:28 +01:00
Bartosz Taudul
ec8c661b38 Remove unneeded sprintfs. 2020-01-31 18:26:28 +01:00
Bartosz Taudul
87989a5f09 Again with this non-conformance stupidity! 2020-01-31 18:09:25 +01:00
Bartosz Taudul
289637384d Perform less work if printing integers. 2020-01-31 02:32:12 +01:00
Bartosz Taudul
1475635382 Use std::to_chars() in RealToString(). 2020-01-31 02:02:47 +01:00
Bartosz Taudul
f017b27ae2 RealToString() is always called with separator set to true. 2020-01-31 01:43:24 +01:00
Bartosz Taudul
3050f19e0b Leverage std::to_chars. 2020-01-31 01:30:33 +01:00
Bartosz Taudul
36fb1f96e2 Custom float-printing function. 2020-01-31 01:19:08 +01:00
Bartosz Taudul
9a5104dacf Extract and pass a value, which will be changing. 2020-01-30 01:57:49 +01:00
Bartosz Taudul
c04824890d Add border to frame range highlight. 2020-01-29 02:17:13 +01:00
Bartosz Taudul
a218ca4412 Use correct format specifier. 2020-01-28 22:01:39 +01:00
Bartosz Taudul
7b0483dc16 Fix typo. 2020-01-28 22:00:07 +01:00