Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/spec/reports/
/tmp/
/vendor/bundle
/vendor/speedscope
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ source "https://rubygems.org"
gemspec

gem "rake", "~> 13.0"
gem "rubyzip"
gem "standard"
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ GEM
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (1.13.0)
rubyzip (3.2.2)
stackprof (0.2.17)
standard (1.35.1)
language_server-protocol (~> 3.17.0.2)
Expand All @@ -72,6 +73,7 @@ PLATFORMS
DEPENDENCIES
rake (~> 13.0)
rspec
rubyzip
singed!
standard

Expand Down
51 changes: 51 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,55 @@
# frozen_string_literal: true

require "bundler/gem_tasks"
require "open-uri"
require "fileutils"
require "tmpdir"
require "zip"
require_relative "lib/singed/speedscope"

namespace :speedscope do
destination_dir = File.expand_path("vendor/speedscope", __dir__)

desc "Download and unpack speedscope into vendor/speedscope"
task vendor: destination_dir

directory destination_dir do
version = Singed::Speedscope::VERSION
url = "https://github.com/jlfwong/speedscope/releases/download/v#{version}/speedscope-#{version}.zip"

unzip_dir = File.expand_path("..", destination_dir) # speedscope dir is in the archive
FileUtils.mkdir_p(destination_dir)

tmp_zip = File.join(Dir.tmpdir, "speedscope-#{version}.zip")

puts "Downloading speedscope from #{url}"
URI.parse(url).open do |remote|
File.open(tmp_zip, "wb") do |file|
IO.copy_stream(remote, file)
end
end

puts "Vendoring speedscope into #{unzip_dir}"
Zip::File.open(tmp_zip) do |zip_file|
zip_file.each do |entry|
destination = File.join(unzip_dir, entry.name)
if entry.directory?
FileUtils.mkdir_p(destination)
else
FileUtils.mkdir_p(File.dirname(destination))
entry.extract(destination_directory: unzip_dir)
end
end
end
end

desc "Remove the unpacked speedscope directory"
task :clobber do
FileUtils.rm_rf(destination_dir)
end
end

Rake::Task[:build].enhance ["speedscope:vendor"]
Rake::Task[:clobber].enhance ["speedscope:clobber"]

task default: %i[]
1 change: 1 addition & 0 deletions lib/singed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def filter_line(line)
autoload :Flamegraph, "singed/flamegraph"
autoload :Report, "singed/report"
autoload :RackMiddleware, "singed/rack_middleware"
autoload :Speedscope, "singed/speedscope"
end

require "singed/kernel_ext"
Expand Down
4 changes: 2 additions & 2 deletions lib/singed/flamegraph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ def save
end

def open
system open_command
Singed::Speedscope.open(@filename)
end

def open_command
@open_command ||= "npx speedscope #{@filename}"
Singed::Speedscope.open_command(@filename)
end

def self.generate_filename(label: nil, time: Time.now) # rubocop:disable Rails/TimeZone
Expand Down
1 change: 0 additions & 1 deletion lib/singed/kernel_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ def flamegraph(label = nil, open: true, ignore_gc: false, interval: 1000, io: $s
bright_red = "\e[91m"
none = "\e[0m"
if open
# use npx, so we don't have to add it as a dependency
io.puts "🔥📈 #{bright_red}Captured flamegraph, opening with#{none}: #{fg.open_command}"
fg.open
else
Expand Down
79 changes: 79 additions & 0 deletions lib/singed/speedscope.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# frozen_string_literal: true
Comment thread
Envek marked this conversation as resolved.
Outdated

require "rbconfig"
require "tmpdir"

module Singed
module Speedscope
VERSION = "1.24.0"

class << self
def bundled_index_html
File.join(File.expand_path("../..", __dir__), "vendor", "speedscope", "index.html")
end

def open_command(profile_path)
if File.exist?(bundled_index_html)
"#{os_open_command} file://#{bundled_index_html}#localProfilePath=#{profile_path}"
else
"npx speedscope #{profile_path}"
end
end

def open(profile_path)
profile_path = profile_path.to_s

if File.exist?(bundled_index_html)
open_with_bundled_speedscope(profile_path)
else
open_with_npx(profile_path)
end
end

private

def open_with_npx(profile_path)
system("npx", "speedscope", profile_path)
end

# Based on speedscope CLI code (MIT license)
# See https://github.com/jlfwong/speedscope/blob/3613918de0dd55a263d0d04f85b0c8c2039c7bee/bin/cli.mjs
def open_with_bundled_speedscope(profile_path)
source_buffer = File.binread(profile_path)
filename = File.basename(profile_path)

source_base64 = [source_buffer].pack("m0")
js_source = "speedscope.loadFileFromBase64(#{filename.inspect}, #{source_base64.inspect})"

file_prefix = "speedscope-#{Time.now.to_i}-#{Process.pid}"
js_path = File.join(Dir.tmpdir, "#{file_prefix}.js")
File.write(js_path, js_source)

url_to_open = "file://#{File.expand_path(bundled_index_html)}#localProfilePath=#{js_path}"

# See https://github.com/jlfwong/speedscope/blob/3613918de0dd55a263d0d04f85b0c8c2039c7bee/bin/cli.mjs#L96-L105
host_os = RbConfig::CONFIG["host_os"]
if host_os =~ /mswin|mingw|cygwin/ || host_os =~ /darwin/
html_path = File.join(Dir.tmpdir, "#{file_prefix}.html")
File.write(html_path, "<script>window.location=#{url_to_open.inspect}</script>")
url_to_open = "file://#{html_path}"
end

system os_open_command, url_to_open
end

def os_open_command
case host_os = RbConfig::CONFIG["host_os"]
when /mswin|mingw|cygwin/
"start"
when /darwin/
"open"
when /linux|bsd/
"xdg-open"
else
raise "Unsupported OS to open browser: #{host_os}"
end
end
end
end
end
2 changes: 1 addition & 1 deletion singed.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
"homepage_uri" => "https://github.com/rubyatscale/singed"
}

spec.files = Dir["README.md", "*.gemspec", "lib/**/*", "exe/**/*"]
spec.files = Dir["README.md", "*.gemspec", "lib/**/*", "exe/**/*", "vendor/speedscope/**/*"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
Expand Down