startup-time 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a9ba80fb5d1e63389c3ca3b8b3dc3b0a8cc338504f6a23c810d14335e0e044f5
4
+ data.tar.gz: 8e199bbea99112e8dc993d6c3500bad99048cb72fd8f6bd96c498da40ee9b20d
5
+ SHA512:
6
+ metadata.gz: 9de0b24fbd653e0d52e95b39838d2af9258de9fbd0e2e16f75827413c37d4ed86522da5f74b531fd71404faf9cc1f73d3bfe5afd19ded0be2eb0960b220d297c
7
+ data.tar.gz: a2432428c758ccc48fa0e7616c88fa61e0acd73abab6ec4751d4f3cb2cc93f4fe7efed31c58f611c4e6173d2aa993ff13e6053b1559945a34e036d8e92d12de1
@@ -0,0 +1,6 @@
1
+ ## 1.0.0 - 2019-02-21
2
+
3
+ - gemify
4
+ - add tests for Deno, GraalVM JavaScript, Nim, and TruffleRuby
5
+ - add --json option to render the results as a JSON array
6
+ - add changelog
@@ -0,0 +1,192 @@
1
+ The Artistic License 2.0
2
+ ========================
3
+
4
+ _Copyright © 2000-2006, The Perl Foundation._
5
+
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ ### Preamble
10
+
11
+ This license establishes the terms under which a given free software
12
+ Package may be copied, modified, distributed, and/or redistributed.
13
+ The intent is that the Copyright Holder maintains some artistic
14
+ control over the development of that Package while still keeping the
15
+ Package available as open source and free software.
16
+
17
+ You are always permitted to make arrangements wholly outside of this
18
+ license directly with the Copyright Holder of a given Package. If the
19
+ terms of this license do not permit the full use that you propose to
20
+ make of the Package, you should contact the Copyright Holder and seek
21
+ a different licensing arrangement.
22
+
23
+ ### Definitions
24
+
25
+ “Copyright Holder” means the individual(s) or organization(s)
26
+ named in the copyright notice for the entire Package.
27
+
28
+ “Contributor” means any party that has contributed code or other
29
+ material to the Package, in accordance with the Copyright Holder's
30
+ procedures.
31
+
32
+ “You” and “your” means any person who would like to copy,
33
+ distribute, or modify the Package.
34
+
35
+ “Package” means the collection of files distributed by the
36
+ Copyright Holder, and derivatives of that collection and/or of
37
+ those files. A given Package may consist of either the Standard
38
+ Version, or a Modified Version.
39
+
40
+ “Distribute” means providing a copy of the Package or making it
41
+ accessible to anyone else, or in the case of a company or
42
+ organization, to others outside of your company or organization.
43
+
44
+ “Distributor Fee” means any fee that you charge for Distributing
45
+ this Package or providing support for this Package to another
46
+ party. It does not mean licensing fees.
47
+
48
+ “Standard Version” refers to the Package if it has not been
49
+ modified, or has been modified only in ways explicitly requested
50
+ by the Copyright Holder.
51
+
52
+ “Modified Version” means the Package, if it has been changed, and
53
+ such changes were not explicitly requested by the Copyright
54
+ Holder.
55
+
56
+ “Original License” means this Artistic License as Distributed with
57
+ the Standard Version of the Package, in its current version or as
58
+ it may be modified by The Perl Foundation in the future.
59
+
60
+ “Source” form means the source code, documentation source, and
61
+ configuration files for the Package.
62
+
63
+ “Compiled” form means the compiled bytecode, object code, binary,
64
+ or any other form resulting from mechanical transformation or
65
+ translation of the Source form.
66
+
67
+ ### Permission for Use and Modification Without Distribution
68
+
69
+ **(1)** You are permitted to use the Standard Version and create and use
70
+ Modified Versions for any purpose without restriction, provided that
71
+ you do not Distribute the Modified Version.
72
+
73
+ ### Permissions for Redistribution of the Standard Version
74
+
75
+ **(2)** You may Distribute verbatim copies of the Source form of the
76
+ Standard Version of this Package in any medium without restriction,
77
+ either gratis or for a Distributor Fee, provided that you duplicate
78
+ all of the original copyright notices and associated disclaimers. At
79
+ your discretion, such verbatim copies may or may not include a
80
+ Compiled form of the Package.
81
+
82
+ **(3)** You may apply any bug fixes, portability changes, and other
83
+ modifications made available from the Copyright Holder. The resulting
84
+ Package will still be considered the Standard Version, and as such
85
+ will be subject to the Original License.
86
+
87
+ ### Distribution of Modified Versions of the Package as Source
88
+
89
+ **(4)** You may Distribute your Modified Version as Source (either gratis
90
+ or for a Distributor Fee, and with or without a Compiled form of the
91
+ Modified Version) provided that you clearly document how it differs
92
+ from the Standard Version, including, but not limited to, documenting
93
+ any non-standard features, executables, or modules, and provided that
94
+ you do at least ONE of the following:
95
+
96
+ * **(a)** make the Modified Version available to the Copyright Holder
97
+ of the Standard Version, under the Original License, so that the
98
+ Copyright Holder may include your modifications in the Standard
99
+ Version.
100
+ * **(b)** ensure that installation of your Modified Version does not
101
+ prevent the user installing or running the Standard Version. In
102
+ addition, the Modified Version must bear a name that is different
103
+ from the name of the Standard Version.
104
+ * **(c)** allow anyone who receives a copy of the Modified Version to
105
+ make the Source form of the Modified Version available to others
106
+ under
107
+ * **(i)** the Original License or
108
+ * **(ii)** a license that permits the licensee to freely copy,
109
+ modify and redistribute the Modified Version using the same
110
+ licensing terms that apply to the copy that the licensee
111
+ received, and requires that the Source form of the Modified
112
+ Version, and of any works derived from it, be made freely
113
+ available in that license fees are prohibited but Distributor
114
+ Fees are allowed.
115
+
116
+ ### Distribution of Compiled Forms of the Standard Version
117
+ ### or Modified Versions without the Source
118
+
119
+ **(5)** You may Distribute Compiled forms of the Standard Version without
120
+ the Source, provided that you include complete instructions on how to
121
+ get the Source of the Standard Version. Such instructions must be
122
+ valid at the time of your distribution. If these instructions, at any
123
+ time while you are carrying out such distribution, become invalid, you
124
+ must provide new instructions on demand or cease further distribution.
125
+ If you provide valid instructions or cease distribution within thirty
126
+ days after you become aware that the instructions are invalid, then
127
+ you do not forfeit any of your rights under this license.
128
+
129
+ **(6)** You may Distribute a Modified Version in Compiled form without
130
+ the Source, provided that you comply with Section 4 with respect to
131
+ the Source of the Modified Version.
132
+
133
+ ### Aggregating or Linking the Package
134
+
135
+ **(7)** You may aggregate the Package (either the Standard Version or
136
+ Modified Version) with other packages and Distribute the resulting
137
+ aggregation provided that you do not charge a licensing fee for the
138
+ Package. Distributor Fees are permitted, and licensing fees for other
139
+ components in the aggregation are permitted. The terms of this license
140
+ apply to the use and Distribution of the Standard or Modified Versions
141
+ as included in the aggregation.
142
+
143
+ **(8)** You are permitted to link Modified and Standard Versions with
144
+ other works, to embed the Package in a larger work of your own, or to
145
+ build stand-alone binary or bytecode versions of applications that
146
+ include the Package, and Distribute the result without restriction,
147
+ provided the result does not expose a direct interface to the Package.
148
+
149
+ ### Items That are Not Considered Part of a Modified Version
150
+
151
+ **(9)** Works (including, but not limited to, modules and scripts) that
152
+ merely extend or make use of the Package, do not, by themselves, cause
153
+ the Package to be a Modified Version. In addition, such works are not
154
+ considered parts of the Package itself, and are not subject to the
155
+ terms of this license.
156
+
157
+ ### General Provisions
158
+
159
+ **(10)** Any use, modification, and distribution of the Standard or
160
+ Modified Versions is governed by this Artistic License. By using,
161
+ modifying or distributing the Package, you accept this license. Do not
162
+ use, modify, or distribute the Package, if you do not accept this
163
+ license.
164
+
165
+ **(11)** If your Modified Version has been derived from a Modified
166
+ Version made by someone other than you, you are nevertheless required
167
+ to ensure that your Modified Version complies with the requirements of
168
+ this license.
169
+
170
+ **(12)** This license does not grant you the right to use any trademark,
171
+ service mark, tradename, or logo of the Copyright Holder.
172
+
173
+ **(13)** This license includes the non-exclusive, worldwide,
174
+ free-of-charge patent license to make, have made, use, offer to sell,
175
+ sell, import and otherwise transfer the Package with respect to any
176
+ patent claims licensable by the Copyright Holder that are necessarily
177
+ infringed by the Package. If you institute patent litigation
178
+ (including a cross-claim or counterclaim) against any party alleging
179
+ that the Package constitutes direct or contributory patent
180
+ infringement, then this Artistic License to you shall terminate on the
181
+ date that such litigation is filed.
182
+
183
+ **(14)** **Disclaimer of Warranty:**
184
+
185
+ THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
186
+ IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
187
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
188
+ NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
189
+ LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
190
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
191
+ DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
192
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,121 @@
1
+ # startup-time
2
+
3
+ [![Build Status](https://travis-ci.org/chocolateboy/startup-time.svg)](https://travis-ci.org/chocolateboy/startup-time)
4
+ [![Gem Version](https://img.shields.io/gem/v/startup-time.svg)](https://rubygems.org/gems/startup-time)
5
+
6
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
7
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
8
+
9
+ - [NAME](#name)
10
+ - [USAGE](#usage)
11
+ - [INSTALLATION](#installation)
12
+ - [DESCRIPTION](#description)
13
+ - [Why?](#why)
14
+ - [Example Output](#example-output)
15
+ - [PREREQUISITES](#prerequisites)
16
+ - [Further Reading](#further-reading)
17
+ - [See Also](#see-also)
18
+ - [Author](#author)
19
+ - [Version](#version)
20
+ - [Copyright and License](#copyright-and-license)
21
+
22
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
23
+
24
+ ## NAME
25
+
26
+ startup-time - a command-line benchmarking tool which measures the startup times of programs in various languages
27
+
28
+ ## USAGE
29
+
30
+ ```sh
31
+ # run all available tests
32
+ $ startup-time
33
+
34
+ # only run the "fast" tests
35
+ $ startup-time --only fast
36
+
37
+ # run all but the "slow" tests
38
+ $ startup-time --omit slow
39
+
40
+ # only run the JVM tests (e.g. Java, Scala etc.)
41
+ $ startup-time --only jvm
42
+
43
+ # only run tests which finish quickly
44
+ $ startup-time --only fast --omit slow-compile
45
+
46
+ # increase the number of times each test is run (default: 10)
47
+ $ startup-time --rounds 100
48
+ ```
49
+
50
+ ## INSTALLATION
51
+
52
+ ```sh
53
+ $ gem install startup-time
54
+ ```
55
+
56
+ ## DESCRIPTION
57
+
58
+ A command-line tool which measures how long it takes to execute ["Hello, world!"](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program) programs written in various languages. It records the fastest time for each program and prints a sorted table of the times after each run. Apart from the [prerequisites](#prerequisites) listed below, the tool doesn't require any of the tested languages to be installed: if a compiler/interpreter is not available, the test is skipped.
59
+
60
+ ### Why?
61
+
62
+ To determine which languages are practical (or impractical) to use for command-line interface (CLI) programs. Anything under
63
+ [100 milliseconds](https://www.nngroup.com/articles/response-times-3-important-limits/) is perceived as instantaneous. Anything over that is perceived as delayed, which can tangibly impair productivity and flow, and even risk breaking the user's train of thought.
64
+
65
+ ### Example Output
66
+
67
+ Test Time (ms)
68
+ C (gcc) 0.33
69
+ Nim 0.45
70
+ LuaJIT 0.62
71
+ Rust 0.63
72
+ Kotlin Native (konan) 0.66
73
+ Go 0.75
74
+ Lua 1.00
75
+ Haskell (GHC) 1.17
76
+ C++ (g++) 1.24
77
+ Perl 1.75
78
+ Java Native (GraalVM) 1.95
79
+ Crystal 2.20
80
+ Bash 3.37
81
+ JavaScript (Deno) 11.18
82
+ Python 3 26.41
83
+ JavaScript (GraalVM) 35.58
84
+ Java 56.40
85
+ Python 2 57.00
86
+ JavaScript (Node.js) 71.61
87
+ Ruby 77.30
88
+ Ruby (TruffleRuby) 91.28
89
+ Kotlin 103.02
90
+ Scala 801.21
91
+
92
+ ## PREREQUISITES
93
+
94
+ - Ruby >= 2.4
95
+
96
+ ## Further Reading
97
+
98
+ - [Response Times: The 3 Important Limits](https://www.nngroup.com/articles/response-times-3-important-limits/)
99
+ - [100 milliseconds](http://cogsci.stackexchange.com/questions/1664/what-is-the-threshold-where-actions-are-perceived-as-instant)
100
+ - [The Great Startup Problem](http://mail.openjdk.java.net/pipermail/mlvm-dev/2014-August/005866.html)
101
+
102
+ ## See Also
103
+
104
+ - [gnustavo/startup-times](https://github.com/gnustavo/startup-times) - a script to investigate the startup times of several programming languages
105
+ - [jwiegley/helloworld](https://github.com/jwiegley/helloworld) - a comparison of "Hello, world" startup times in various languages
106
+ - [sharkdp/hyperfine](https://github.com/sharkdp/hyperfine) - a command-line benchmarking tool
107
+
108
+ ## Author
109
+
110
+ [chocolateboy](mailto:chocolate@cpan.org)
111
+
112
+ ## Version
113
+
114
+ 1.0.0
115
+
116
+ ## Copyright and License
117
+
118
+ Copyright © 2015-2019 by chocolateboy
119
+
120
+ This benchmark game is free software; you can redistribute it and/or modify it under the
121
+ terms of the [Artistic License 2.0](http://www.opensource.org/licenses/artistic-license-2.0.php).
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'cli-pasta'
6
+ require_relative '../lib/startup_time'
7
+
8
+ StartupTime::App.new.run
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'startup_time/version'
4
+ require_relative 'startup_time/services'
5
+ require_relative 'startup_time/util'
6
+ require_relative 'startup_time/app'
7
+ require_relative 'startup_time/builder'
8
+ require_relative 'startup_time/options'
9
+ require_relative 'startup_time/registry'
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark'
4
+ require 'komenda'
5
+ require 'shellwords' # for Array#shelljoin
6
+ require 'tty/table'
7
+
8
+ module StartupTime
9
+ # StartupTime::App - the entry point for the app.
10
+ # selects an action based on the command-line options and runs it.
11
+ class App
12
+ EXPECTED_OUTPUT = /\AHello, world!\r?\n\z/
13
+
14
+ include Util # for `which`
15
+ include Services.mixin %i[builder ids_to_groups options selected_tests]
16
+
17
+ def initialize(args = ARGV)
18
+ @options = Options.new(args)
19
+ @verbosity = @options.verbosity
20
+ @times = []
21
+
22
+ # provide/publish the Options instance we've just created so it's
23
+ # available to other components
24
+ Services.once(:options) { @options }
25
+ end
26
+
27
+ # run the command corresponding to the command-line options:
28
+ # either an auxiliary command (e.g. clean the build dir
29
+ # or print a help message) or the default command, which runs
30
+ # the selected benchmark-tests
31
+ def run
32
+ if @verbosity == :verbose
33
+ # used by StartupTime::App#time to dump the command line
34
+ require 'shellwords'
35
+ end
36
+
37
+ case @options.action
38
+ when :clean
39
+ builder.clean!
40
+ when :help
41
+ puts @options.usage
42
+ when :show_ids
43
+ puts render_ids_to_groups
44
+ when :version
45
+ puts VERSION
46
+ else
47
+ benchmark
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ # run the selected benchmark tests:
54
+ #
55
+ # 1) ensure everything in the build directory is up to date
56
+ # 2) run the tests in random order and time each one
57
+ # 3) sort the results from the fastest to the slowest
58
+ # 4) display the results in the specified format (default: ASCII table)
59
+ def benchmark
60
+ builder.build!
61
+
62
+ selected_tests.entries.shuffle.each do |id, test|
63
+ time(id, test)
64
+ end
65
+
66
+ sorted = @times.sort_by { |result| result[:time] }
67
+
68
+ if options.format == :json
69
+ require 'json'
70
+ puts sorted.to_json
71
+ elsif !sorted.empty?
72
+ pairs = sorted.map { |result| [result[:name], '%.02f' % result[:time]] }
73
+ table = TTY::Table.new(['Test', 'Time (ms)'], pairs)
74
+ puts unless @verbosity == :quiet
75
+ puts table.render(:basic, alignments: %i[left right])
76
+ end
77
+ end
78
+
79
+ # an ASCII table representation of the mapping from test IDs (e.g. "scala")
80
+ # to group IDs (e.g. "compiled, jvm, slow")
81
+ def render_ids_to_groups
82
+ table = TTY::Table.new(%w[Test Groups], ids_to_groups)
83
+ table.render
84
+ end
85
+
86
+ # takes a test ID and a test spec and measures how long it takes to execute
87
+ # the test if either:
88
+ #
89
+ # - its interpreter exists
90
+ # - it's a compiled executable (i.e. its compiler exists)
91
+ #
92
+ # otherwise, skip the test
93
+ def time(id, test)
94
+ args = Array(test[:command])
95
+
96
+ if args.size == 1 # native executable
97
+ cmd = File.absolute_path(args.first)
98
+ return unless File.exist? cmd
99
+ else # interpreter + source
100
+ cmd = which(args.first)
101
+ return unless cmd
102
+ end
103
+
104
+ argv0 = args.shift
105
+ command = [cmd, *args]
106
+
107
+ # make sure the command produces the expected output
108
+ result = Komenda.run(command)
109
+ output = result.output
110
+
111
+ if result.error?
112
+ abort "error running #{id} (#{result.status}): #{output}"
113
+ end
114
+
115
+ unless output.match?(EXPECTED_OUTPUT)
116
+ abort "invalid output for #{id}: #{output.inspect}"
117
+ end
118
+
119
+ times = []
120
+
121
+ unless @verbosity == :quiet
122
+ if @verbosity == :verbose
123
+ puts "#{id}: #{command.shelljoin}"
124
+ else
125
+ print '.'
126
+ end
127
+ end
128
+
129
+ @options.rounds.times do
130
+ times << Benchmark.realtime do
131
+ system([cmd, argv0], *args, out: File::NULL)
132
+ end
133
+ end
134
+
135
+ @times << {
136
+ id: id,
137
+ name: test[:name],
138
+ time: (times.min * 1000).truncate(2)
139
+ }
140
+ end
141
+ end
142
+ end