Commit Graph

613 Commits

Author SHA1 Message Date
Weijia Wang
254058109f tools: add 'spaced-comment' into eslint rules
PR-URL: https://github.com/nodejs/node/pull/19596
Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
2018-04-01 22:33:13 +08:00
Ruben Bridgewater
f4e5f969ba buffer: improve write(U)Int functions
This improves the performance of some write functions by around 5-15%.

PR-URL: https://github.com/nodejs/node/pull/19289
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-03-24 16:50:01 +01:00
Brian White
b41ed29b80 stream: improve stream creation performance
PR-URL: https://github.com/nodejs/node/pull/19401
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
2018-03-23 13:39:16 +01:00
Brian White
3c61b87e59 assert: improve assert()/assert.ok() performance
PR-URL: https://github.com/nodejs/node/pull/19292
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yuta Hiroto <hello@hiroppy.me>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
2018-03-15 12:57:35 -04:00
Anna Henningsen
e136903700 benchmark: remove excessive value from http2 benchmark
`requests = 1000000` took about 10 minutes per run for me
and doesn’t seem to add much value on its own.

PR-URL: https://github.com/nodejs/node/pull/18936
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2018-03-15 12:53:22 +01:00
Sergey Golovin
f3257dd3ea benchmark: fix benchmark for url
Rename different parameters with the same names to make it possible
to run tests for url benchmarks.

PR-URL: https://github.com/nodejs/node/pull/19084
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Khaidi Chu <i@2333.moe>
Reviewed-By: Shingo Inoue <leko.noor@gmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-03-11 03:56:17 +01:00
Rich Trott
3c31bfff65 benchmark,lib,test,tools: use consistent quotes
In preparation for a linting rule, use consistent quotation for
properties in objects.

PR-URL: https://github.com/nodejs/node/pull/19156
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Teddy Katz <teddy.katz@gmail.com>
Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Roman Reiss <me@silverwind.io>
2018-03-07 19:06:44 -08:00
Сковорода Никита Андреевич
8ed44ff1c4 test,benchmark: use new Buffer API where appropriate
For tests / benchmarks that are creating Buffer instances for
any reason other than to test Buffer constructor, use the new
Buffer.alloc/Buffer.from API instead of the deprecated API.

PR-URL: https://github.com/nodejs/node/pull/18980
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
2018-03-04 12:50:15 +01:00
Ruben Bridgewater
81aaab75ca benchmark: remove noAssert argument
This removes the `noAssert` argument and also adds some more tests.

PR-URL: https://github.com/nodejs/node/pull/18395
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
2018-03-02 19:29:47 +00:00
Ruben Bridgewater
341770fedf lib: improve normalize encoding performance
This focuses on the common case by making sure they are prioritized.
It also changes some typeof checks to test for undefined since
that is faster and it adds a benchmark.

PR-URL: https://github.com/nodejs/node/pull/18790
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2018-03-02 02:09:25 +00:00
Ruben Bridgewater
876836b135 benchmark: rename file
PR-URL: https://github.com/nodejs/node/pull/18790
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2018-03-02 02:09:25 +00:00
Ruben Bridgewater
e9ec9ff269 benchmark: add buffer fill benchmark
PR-URL: https://github.com/nodejs/node/pull/18790
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2018-03-02 02:09:24 +00:00
Weijia Wang
3cef3e61d6 url: reduce deplicated codes in autoEscapeStr
PR-URL: https://github.com/nodejs/node/pull/18613
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
2018-02-23 15:46:05 +08:00
Ruben Bridgewater
8be96579ae tools: enable eslint one-var rule
PR-URL: https://github.com/nodejs/node/pull/18831
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matheus Marchini <matheus@sthima.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
2018-02-22 14:56:15 +00:00
Ruben Bridgewater
684c1bb42d tools: enable eslint strict key-spacing
PR-URL: https://github.com/nodejs/node/pull/18831
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matheus Marchini <matheus@sthima.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
2018-02-22 14:56:12 +00:00
Gus Caplan
6934792eb3 lint: move eslint to new plugin system
PR-URL: https://github.com/nodejs/node/pull/18566
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
2018-02-20 13:13:22 -06:00
Michaël Zasso
513d939720 fs: move fs.promises API to fs/promises
PR-URL: https://github.com/nodejs/node/pull/18777
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
2018-02-17 10:15:20 +01:00
Ruben Bridgewater
463d1a490f test,benchmark,doc: enable dot-notation rule
This enables the eslint dot-notation rule for all code instead of
only in /lib.

PR-URL: https://github.com/nodejs/node/pull/18749
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matheus Marchini <matheus@sthima.com>
2018-02-16 19:37:43 +01:00
Seth Brenith
862389b0aa http: simplify checkInvalidHeaderChar
In the spirit of [17399](https://github.com/nodejs/node/pull/17399),
we can also simplify checkInvalidHeaderChar to use regex matching
instead of a loop. This makes it faster on long matches and slower
on short matches or non-matches. This change also includes some
sample data from an AcmeAir benchmark run, as a rough proxy for
real-world data.

PR-URL: https://github.com/nodejs/node/pull/18381
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
2018-02-16 19:27:28 +01:00
Ruben Bridgewater
15bb8437fd tools: add assert.doesNotThrow eslint rule
Prohibit the usage of `assert.doesNotThrow()`.

PR-URL: https://github.com/nodejs/node/pull/18669
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2018-02-16 16:54:57 +01:00
Anna Henningsen
0e7b61229a src: refactor WriteWrap and ShutdownWraps
Encapsulate stream requests more:

- `WriteWrap` and `ShutdownWrap` classes are now tailored to the
  streams on which they are used. In particular, for most streams
  these are now plain `AsyncWrap`s and do not carry the overhead
  of unused libuv request data.
- Provide generic `Write()` and `Shutdown()` methods that wrap
  around the actual implementations, and make *usage* of streams
  easier, rather than implementing; for example, wrap objects
  don’t need to be provided by callers anymore.
- Use `EmitAfterWrite()` and `EmitAfterShutdown()` handlers to
  call the corresponding JS handlers, rather than always trying
  to call them. This makes usage of streams by other C++ code
  easier and leaner.

Also fix up some tests that were previously not actually testing
asynchronicity when the comments indicated that they would.

PR-URL: https://github.com/nodejs/node/pull/18676
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-14 10:00:29 +01:00
Anatoli Papirovski
0f9efef05d timers: refactor timer list processing
Instead of using kOnTimeout index to track a special list
processing function, just pass in a function to C++ at
startup that executes all handles and determines which
function to call.

This change improves the performance of unpooled timeouts
by roughly 20%, as well as makes the unref/ref processing
easier to follow.

PR-URL: https://github.com/nodejs/node/pull/18582
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
2018-02-09 14:59:07 -05:00
Mathias Buus
da97a47c44 benchmark: add stream.pipe benchmarks
PR-URL: https://github.com/nodejs/node/pull/18617
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
2018-02-09 09:47:40 +01:00
Ruben Bridgewater
809af1fe8a benchmark: improve compare output
The current output uses JSON.stringify to escape the config values.
This switches to util.inspect to have a better readable output.

PR-URL: https://github.com/nodejs/node/pull/18597
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2018-02-08 11:38:25 -05:00
James M Snell
329fc78e49 fs: add initial set of fs.promises APIs
Initial set of fs.promises APIs with documentation and one
benchmark.

PR-URL: https://github.com/nodejs/node/pull/18297
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2018-02-05 20:31:04 -08:00
Anatoli Papirovski
5c2c412f21 test: add test for tls benchmarks
PR-URL: https://github.com/nodejs/node/pull/18489
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-04 08:14:44 -05:00
James M Snell
84cc8329f7 benchmark: spread operator benchmark
Benchmark comparing `util._extend()`, `Object.assign()`,
and the spread operator for object assignment.

`util._extend()` still wins currently.

PR-URL: https://github.com/nodejs/node/pull/18442
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Weijia Wang <starkwang@126.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
2018-02-01 07:35:54 -08:00
Joyee Cheung
d3841ec872 benchmark: shorten config name in http benchmark
Shorten the config name in check_invalid_header_char so it would
not result in long lines that make the benchmark result hard to read.

PR-URL: https://github.com/nodejs/node/pull/18452
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Weijia Wang <starkwang@126.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
2018-02-01 12:02:54 +01:00
Joyee Cheung
54b3a685c1 benchmark: cut down http benchmark run time
PR-URL: https://github.com/nodejs/node/pull/18379
Reviewed-By: Jon Moss <me@jonathanmoss.me>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
2018-02-01 11:43:30 +01:00
Jamie Davis
67a4ce1c6e fs: partition readFile against pool exhaustion
Problem:

Node implements fs.readFile as:
- a call to stat, then
- a C++ -> libuv request to read the entire file using the stat size

Why is this bad?
The effect is to place on the libuv threadpool a potentially-large
read request, occupying the libuv thread until it completes.
While readFile certainly requires buffering the entire file contents,
it can partition the read into smaller buffers
(as is done on other read paths)
along the way to avoid threadpool exhaustion.

If the file is relatively large or stored on a slow medium, reading
the entire file in one shot seems particularly harmful,
and presents a possible DoS vector.

Solution:

Partition the read into multiple smaller requests.

Considerations:

1. Correctness

I don't think partitioning the read like this raises
any additional risk of read-write races on the FS.
If the application is concurrently readFile'ing and modifying the file,
it will already see funny behavior. Though libuv uses preadv where
available, this doesn't guarantee read atomicity in the presence of
concurrent writes.

2. Performance

Downside: Partitioning means that a single large readFile will
  require into many "out and back" requests to libuv,
  introducing overhead.
Upside: In between each "out and back", other work pending on the
  threadpool can take a turn.

In short, although partitioning will slow down a large request,
it will lead to better throughput if the threadpool is handling
more than one type of request.

Fixes: https://github.com/nodejs/node/issues/17047

PR-URL: https://github.com/nodejs/node/pull/17054
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
2018-02-01 11:11:48 +01:00
Ruben Bridgewater
1b6cb94761 benchmark: refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:49:04 +01:00
Ruben Bridgewater
c713f079f1 benchmark: (timers) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:49:03 +01:00
Ruben Bridgewater
1178670cca benchmark: (http(2)) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:49:03 +01:00
Ruben Bridgewater
2072f343ad benchmark: (es) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:49:02 +01:00
Ruben Bridgewater
1a8ed225b2 benchmark: (url) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:49:01 +01:00
Ruben Bridgewater
39ae0b9800 benchmark: (crypto) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:49:00 +01:00
Ruben Bridgewater
794e489eea benchmark: (buffer) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:48:59 +01:00
Ruben Bridgewater
cd7b2c434c benchmark: (assert) refactor
PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:48:58 +01:00
Ruben Bridgewater
f951c9a9f0 benchmark: fix variables not being set
Due to the destructuring the outer variables were not set anymore.

PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:48:57 +01:00
Ruben Bridgewater
d4015b8995 benchmark: fix platform in basename-win32
It should say `win32` and not `posix`.

PR-URL: https://github.com/nodejs/node/pull/18320
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-02-01 10:48:56 +01:00
Rich Trott
bf6ce47259 test: move tmpdir to submodule of common
Move tmpdir functionality to its own module (common/tmpdir).

PR-URL: https://github.com/nodejs/node/pull/17856
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
2018-01-31 22:11:07 -08:00
Joyee Cheung
98d1110721 benchmark: implement duration in http test double
PR-URL: https://github.com/nodejs/node/pull/18380
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
2018-01-29 17:46:14 +08:00
Andreas Madsen
368517c0dc benchmark: make compare.R easier to understand
PR-URL: https://github.com/nodejs/node/pull/18373
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
2018-01-29 13:26:34 +08:00
Seth Brenith
aba6bc34a1 http: switch on string values
Long ago, V8 was much faster switching on string lengths than values.
That is no longer the case, so we can simplify a couple of methods.

PR-URL: https://github.com/nodejs/node/pull/18351
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Jon Moss <me@jonathanmoss.me>
2018-01-26 16:24:50 -05:00
Ruben Bridgewater
6394c8d99d benchmark: use destructuring
This applies to all `async_hooks`, `dns`, `cluster`, `domain` and
`module` benchmarks.

PR-URL: https://github.com/nodejs/node/pull/18250
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-01-23 01:29:34 +01:00
Ruben Bridgewater
b2966043c9 benchmark: (dgram) use destructuring
PR-URL: https://github.com/nodejs/node/pull/18250
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-01-23 01:29:33 +01:00
Ruben Bridgewater
d49580d812 benchmark: (child_process) use destructuring
PR-URL: https://github.com/nodejs/node/pull/18250
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-01-23 01:29:32 +01:00
Ruben Bridgewater
8e3d7623a5 benchmark: (buffers) use destructuring
PR-URL: https://github.com/nodejs/node/pull/18250
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-01-23 01:29:31 +01:00
Ruben Bridgewater
896397b5dc benchmark: (events) use destructuring
PR-URL: https://github.com/nodejs/node/pull/18250
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-01-23 01:29:30 +01:00
Ruben Bridgewater
ed91f58414 benchmark: (es) use destructuring
PR-URL: https://github.com/nodejs/node/pull/18250
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-01-23 01:29:30 +01:00