-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GR-29472] Add a simple sinatra benchmark
PullRequest: truffleruby/2511
- Loading branch information
Showing
176 changed files
with
19,091 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
Based on https://github.com/benchmark-driver/sinatra/blob/master/driver.yml | ||
|
||
Gems were vendored using: | ||
``` | ||
bundle install --standalone | ||
``` | ||
|
||
with this Gemfile: | ||
``` | ||
source 'https://rubygems.org' | ||
gem 'sinatra' | ||
``` | ||
|
||
Then moving `bundle/ruby/version/gems` to just `bundle/gems`, | ||
and keeping only `lib`, `bin` and licenses. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
path = File.expand_path('..', __FILE__) | ||
kernel = (class << ::Kernel; self; end) | ||
[kernel, ::Kernel].each do |k| | ||
if k.private_method_defined?(:gem_original_require) | ||
private_require = k.private_method_defined?(:require) | ||
k.send(:remove_method, :require) | ||
k.send(:define_method, :require, k.instance_method(:gem_original_require)) | ||
k.send(:private, :require) if private_require | ||
end | ||
end | ||
$:.unshift File.expand_path("#{path}/../gems/ruby2_keywords-0.0.4/lib") | ||
$:.unshift File.expand_path("#{path}/../gems/mustermann-1.1.1/lib") | ||
$:.unshift File.expand_path("#{path}/../gems/rack-2.2.3/lib") | ||
$:.unshift File.expand_path("#{path}/../gems/rack-protection-2.1.0/lib") | ||
$:.unshift File.expand_path("#{path}/../gems/tilt-2.0.10/lib") | ||
$:.unshift File.expand_path("#{path}/../gems/sinatra-2.1.0/lib") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
Copyright (c) 2013-2017 Konstantin Haase | ||
Copyright (c) 2016-2017 Zachary Scott | ||
|
||
Permission is hereby granted, free of charge, to any person | ||
obtaining a copy of this software and associated documentation | ||
files (the "Software"), to deal in the Software without | ||
restriction, including without limitation the rights to use, | ||
copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following | ||
conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. |
134 changes: 134 additions & 0 deletions
134
bench/sinatra/bundle/gems/mustermann-1.1.1/lib/mustermann.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
# frozen_string_literal: true | ||
require 'mustermann/pattern' | ||
require 'mustermann/composite' | ||
require 'mustermann/concat' | ||
require 'thread' | ||
|
||
# Namespace and main entry point for the Mustermann library. | ||
# | ||
# Under normal circumstances the only external API entry point you should be using is {Mustermann.new}. | ||
module Mustermann | ||
# Type to use if no type is given. | ||
# @api private | ||
DEFAULT_TYPE = :sinatra | ||
|
||
# Creates a new pattern based on input. | ||
# | ||
# * From {Mustermann::Pattern}: returns given pattern. | ||
# * From String: creates a pattern from the string, depending on type option (defaults to {Mustermann::Sinatra}) | ||
# * From Regexp: creates a {Mustermann::Regular} pattern. | ||
# * From Symbol: creates a {Mustermann::Sinatra} pattern with a single named capture named after the input. | ||
# * From an Array or multiple inputs: creates a new pattern from each element, combines them to a {Mustermann::Composite}. | ||
# * From anything else: Will try to call to_pattern on it or raise a TypeError. | ||
# | ||
# Note that if the input is a {Mustermann::Pattern}, Regexp or Symbol, the type option is ignored and if to_pattern is | ||
# called on the object, the type will be handed on but might be ignored by the input object. | ||
# | ||
# If you want to enforce the pattern type, you should create them via their expected class. | ||
# | ||
# @example creating patterns | ||
# require 'mustermann' | ||
# | ||
# Mustermann.new("/:name") # => #<Mustermann::Sinatra:"/example"> | ||
# Mustermann.new("/{name}", type: :template) # => #<Mustermann::Template:"/{name}"> | ||
# Mustermann.new(/.*/) # => #<Mustermann::Regular:".*"> | ||
# Mustermann.new(:name, capture: :word) # => #<Mustermann::Sinatra:":name"> | ||
# Mustermann.new("/", "/*.jpg", type: :shell) # => #<Mustermann::Composite:(shell:"/" | shell:"/*.jpg")> | ||
# | ||
# @example using custom #to_pattern | ||
# require 'mustermann' | ||
# | ||
# class MyObject | ||
# def to_pattern(**options) | ||
# Mustermann.new("/:name", **options) | ||
# end | ||
# end | ||
# | ||
# Mustermann.new(MyObject.new, type: :rails) # => #<Mustermann::Rails:"/:name"> | ||
# | ||
# @example enforcing type | ||
# require 'mustermann/sinatra' | ||
# | ||
# Mustermann::Sinatra.new("/:name") | ||
# | ||
# @param [String, Pattern, Regexp, Symbol, #to_pattern, Array<String, Pattern, Regexp, Symbol, #to_pattern>] | ||
# input The representation of the pattern | ||
# @param [Hash] options The options hash | ||
# @return [Mustermann::Pattern] pattern corresponding to string. | ||
# @raise (see []) | ||
# @raise (see Mustermann::Pattern.new) | ||
# @raise [TypeError] if the passed object cannot be converted to a pattern | ||
# @see file:README.md#Types_and_Options "Types and Options" in the README | ||
def self.new(*input, type: DEFAULT_TYPE, operator: :|, **options) | ||
type ||= DEFAULT_TYPE | ||
input = input.first if input.size < 2 | ||
case input | ||
when Pattern then input | ||
when Regexp then self[:regexp].new(input, **options) | ||
when String then self[type].new(input, **options) | ||
when Symbol then self[:sinatra].new(input.inspect, **options) | ||
when Array then input.map { |i| new(i, type: type, **options) }.inject(operator) | ||
else | ||
pattern = input.to_pattern(type: type, **options) if input.respond_to? :to_pattern | ||
raise TypeError, "#{input.class} can't be coerced into Mustermann::Pattern" if pattern.nil? | ||
pattern | ||
end | ||
end | ||
|
||
@mutex ||= Mutex.new | ||
@types ||= {} | ||
|
||
# Maps a type to its factory. | ||
# | ||
# @example | ||
# Mustermann[:sinatra] # => Mustermann::Sinatra | ||
# | ||
# @param [Symbol] name a pattern type identifier | ||
# @raise [ArgumentError] if the type is not supported | ||
# @return [Class, #new] pattern factory | ||
def self.[](name) | ||
return name if name.respond_to? :new | ||
@types.fetch(normalized = normalized_type(name)) do | ||
@mutex.synchronize do | ||
error = try_require "mustermann/#{normalized}" | ||
@types.fetch(normalized) { raise ArgumentError, "unsupported type %p#{" (#{error.message})" if error}" % name } | ||
end | ||
end | ||
end | ||
|
||
# @return [LoadError, nil] | ||
# @!visibility private | ||
def self.try_require(path) | ||
require(path) | ||
nil | ||
rescue LoadError => error | ||
raise(error) unless error.path == path | ||
error | ||
end | ||
|
||
# @!visibility private | ||
def self.register(name, type) | ||
@types[normalized_type(name)] = type | ||
end | ||
|
||
# @!visibility private | ||
def self.normalized_type(type) | ||
type.to_s.gsub('-', '_').downcase | ||
end | ||
|
||
# @!visibility private | ||
def self.extend_object(object) | ||
return super unless defined? ::Sinatra::Base and object.is_a? Class and object < ::Sinatra::Base | ||
require 'mustermann/extension' | ||
object.register Extension | ||
end | ||
end | ||
|
||
# :nocov: | ||
begin | ||
require 'mustermann/visualizer' if defined?(Pry) or defined?(IRB) | ||
rescue LoadError => error | ||
raise error unless error.path == 'mustermann/visualizer' | ||
$stderr.puts(error.message) if caller_locations[1].absolute_path =~ %r{/lib/pry/|/irb/|^\((?:irb|pry)\)$} | ||
end | ||
# :nocov: |
45 changes: 45 additions & 0 deletions
45
bench/sinatra/bundle/gems/mustermann-1.1.1/lib/mustermann/ast/boundaries.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# frozen_string_literal: true | ||
require 'mustermann/ast/translator' | ||
|
||
module Mustermann | ||
module AST | ||
# Make sure #start and #stop is set on every node and within its parents #start and #stop. | ||
# @!visibility private | ||
class Boundaries < Translator | ||
# @return [Mustermann::AST::Node] the ast passed as first argument | ||
# @!visibility private | ||
def self.set_boundaries(ast, string: nil, start: 0, stop: string.length) | ||
new.translate(ast, start, stop) | ||
ast | ||
end | ||
|
||
translate(:node) do |start, stop| | ||
t.set_boundaries(node, start, stop) | ||
t(payload, node.start, node.stop) | ||
end | ||
|
||
translate(:with_look_ahead) do |start, stop| | ||
t.set_boundaries(node, start, stop) | ||
t(head, node.start, node.stop) | ||
t(payload, node.start, node.stop) | ||
end | ||
|
||
translate(Array) do |start, stop| | ||
each do |subnode| | ||
t(subnode, start, stop) | ||
start = subnode.stop | ||
end | ||
end | ||
|
||
translate(Object) { |*| node } | ||
|
||
# Checks that a node is within the given boundaries. | ||
# @!visibility private | ||
def set_boundaries(node, start, stop) | ||
node.start = start if node.start.nil? or node.start < start | ||
node.stop = node.start + node.min_size if node.stop.nil? or node.stop < node.start | ||
node.stop = stop if node.stop > stop | ||
end | ||
end | ||
end | ||
end |
159 changes: 159 additions & 0 deletions
159
bench/sinatra/bundle/gems/mustermann-1.1.1/lib/mustermann/ast/compiler.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# frozen_string_literal: true | ||
require 'mustermann/ast/translator' | ||
|
||
module Mustermann | ||
# @see Mustermann::AST::Pattern | ||
module AST | ||
# Regexp compilation logic. | ||
# @!visibility private | ||
class Compiler < Translator | ||
raises CompileError | ||
|
||
# Trivial compilations | ||
translate(Array) { |**o| map { |e| t(e, **o) }.join } | ||
translate(:node) { |**o| t(payload, **o) } | ||
translate(:separator) { |**o| Regexp.escape(payload) } | ||
translate(:optional) { |**o| "(?:%s)?" % t(payload, **o) } | ||
translate(:char) { |**o| t.encoded(payload, **o) } | ||
|
||
translate :union do |**options| | ||
"(?:%s)" % payload.map { |e| "(?:%s)" % t(e, **options) }.join(?|) | ||
end | ||
|
||
translate :expression do |greedy: true, **options| | ||
t(payload, allow_reserved: operator.allow_reserved, greedy: greedy && !operator.allow_reserved, | ||
parametric: operator.parametric, separator: operator.separator, **options) | ||
end | ||
|
||
translate :with_look_ahead do |**options| | ||
lookahead = each_leaf.inject("") do |ahead, element| | ||
ahead + t(element, skip_optional: true, lookahead: ahead, greedy: false, no_captures: true, **options).to_s | ||
end | ||
lookahead << (at_end ? '$' : '/') | ||
t(head, lookahead: lookahead, **options) + t(payload, **options) | ||
end | ||
|
||
# Capture compilation is complex. :( | ||
# @!visibility private | ||
class Capture < NodeTranslator | ||
register :capture | ||
|
||
# @!visibility private | ||
def translate(**options) | ||
return pattern(**options) if options[:no_captures] | ||
"(?<#{name}>#{translate(no_captures: true, **options)})" | ||
end | ||
|
||
# @return [String] regexp without the named capture | ||
# @!visibility private | ||
def pattern(capture: nil, **options) | ||
case capture | ||
when Symbol then from_symbol(capture, **options) | ||
when Array then from_array(capture, **options) | ||
when Hash then from_hash(capture, **options) | ||
when String then from_string(capture, **options) | ||
when nil then from_nil(**options) | ||
else capture | ||
end | ||
end | ||
|
||
private | ||
def qualified(string, greedy: true, **options) "#{string}#{qualifier || "+#{?? unless greedy}"}" end | ||
def with_lookahead(string, lookahead: nil, **options) lookahead ? "(?:(?!#{lookahead})#{string})" : string end | ||
def from_hash(hash, **options) pattern(capture: hash[name.to_sym], **options) end | ||
def from_array(array, **options) Regexp.union(*array.map { |e| pattern(capture: e, **options) }) end | ||
def from_symbol(symbol, **options) qualified(with_lookahead("[[:#{symbol}:]]", **options), **options) end | ||
def from_string(string, **options) Regexp.new(string.chars.map { |c| t.encoded(c, **options) }.join) end | ||
def from_nil(**options) qualified(with_lookahead(default(**options), **options), **options) end | ||
def default(**options) constraint || "[^/\\?#]" end | ||
end | ||
|
||
# @!visibility private | ||
class Splat < Capture | ||
register :splat, :named_splat | ||
# splats are always non-greedy | ||
# @!visibility private | ||
def pattern(**options) | ||
constraint || ".*?" | ||
end | ||
end | ||
|
||
# @!visibility private | ||
class Variable < Capture | ||
register :variable | ||
|
||
# @!visibility private | ||
def translate(**options) | ||
return super(**options) if explode or not options[:parametric] | ||
# Remove this line after fixing broken compatibility between 2.1 and 2.2 | ||
options.delete(:parametric) if options.has_key?(:parametric) | ||
parametric super(parametric: false, **options) | ||
end | ||
|
||
# @!visibility private | ||
def pattern(parametric: false, separator: nil, **options) | ||
register_param(parametric: parametric, separator: separator, **options) | ||
pattern = super(**options) | ||
pattern = parametric(pattern) if parametric | ||
pattern = "#{pattern}(?:#{Regexp.escape(separator)}#{pattern})*" if explode and separator | ||
pattern | ||
end | ||
|
||
# @!visibility private | ||
def parametric(string) | ||
"#{Regexp.escape(name)}(?:=#{string})?" | ||
end | ||
|
||
# @!visibility private | ||
def qualified(string, **options) | ||
prefix ? "#{string}{1,#{prefix}}" : super(string, **options) | ||
end | ||
|
||
# @!visibility private | ||
def default(allow_reserved: false, **options) | ||
allow_reserved ? '[\w\-\.~%\:/\?#\[\]@\!\$\&\'\(\)\*\+,;=]' : '[\w\-\.~%]' | ||
end | ||
|
||
# @!visibility private | ||
def register_param(parametric: false, split_params: nil, separator: nil, **options) | ||
return unless explode and split_params | ||
split_params[name] = { separator: separator, parametric: parametric } | ||
end | ||
end | ||
|
||
# @return [String] Regular expression for matching the given character in all representations | ||
# @!visibility private | ||
def encoded(char, uri_decode: true, space_matches_plus: true, **options) | ||
return Regexp.escape(char) unless uri_decode | ||
encoded = escape(char, escape: /./) | ||
list = [escape(char), encoded.downcase, encoded.upcase].uniq.map { |c| Regexp.escape(c) } | ||
if char == " " | ||
list << encoded('+') if space_matches_plus | ||
list << " " | ||
end | ||
"(?:%s)" % list.join("|") | ||
end | ||
|
||
# Compiles an AST to a regular expression. | ||
# @param [Mustermann::AST::Node] ast the tree | ||
# @return [Regexp] corresponding regular expression. | ||
# | ||
# @!visibility private | ||
def self.compile(ast, **options) | ||
new.compile(ast, **options) | ||
end | ||
|
||
# Compiles an AST to a regular expression. | ||
# @param [Mustermann::AST::Node] ast the tree | ||
# @return [Regexp] corresponding regular expression. | ||
# | ||
# @!visibility private | ||
def compile(ast, except: nil, **options) | ||
except &&= "(?!#{translate(except, no_captures: true, **options)}\\Z)" | ||
Regexp.new("#{except}#{translate(ast, **options)}") | ||
end | ||
end | ||
|
||
private_constant :Compiler | ||
end | ||
end |
Oops, something went wrong.