require 'singleton'
module Stopwatch
if defined?(ActiveRecord) && defined?(ActiveRecord::ConnectionAdapters)
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
def log_with_watcher(sql, name = "SQL", binds = [], &block)
Stopwatch.instance.event("sql '#{name}'.") do
log_without_watcher(sql, name, binds, &block)
end
end
alias_method_chain :log, :watcher
end
end
if defined?(ActionController)
ActionController::Base.class_eval do
def render_with_watcher(*args, &block)
Stopwatch.instance.event("render.") do
render_without_watcher(*args, &block)
end
end
alias_method_chain :render, :watcher
end
end
def self.watch(&block)
watcher = Watcher.instance
running = watcher.running
watcher.start
response = yield watcher
watcher.stop unless running
response
end
def self.instance
Stopwatch::Watcher.instance
end
def self.reset
Stopwatch::Watcher.instance.reset
end
class Split
attr_reader :time, :message
def initialize(time, message)
@time = time
@message = message
end
end
class Event
attr_reader :duration, :message
def initialize(duration, message)
@duration = duration
@message = message
end
end
class Tally
attr_reader :duration, :message, :count
def initialize(message)
@message = message
@duration = 0.0
@count = 0.0
end
def add(event)
@duration += event.duration
@count += 1
end
end
class Watcher
include Singleton
attr_reader :running, :splits, :events
def initialize
@running = false
@splits = []
@events = []
end
def start
return if @running
reset
@running = true
@start = Time.now
puts "\n[stopwatch @time=#{human_time(0.0)}] started."
end
def stop
@stop = Time.now
@running = false
puts "[stopwatch @time=#{human_time(@stop - @start)}] stopped."
end
def reset
@running = false
@splits = []
@events = []
end
def split(message)
split_time = Time.now
@splits.push Split.new(split_time, message)
end
def event(message)
start = Time.now
result = yield
stop = Time.now
duration = stop - start
@events.push Event.new(duration, message) if @running
result
end
def report
report_splits
report_events
end
private
def report_splits
last_time = nil
@splits.each do |split|
time = split.time
message = split.message
elapsed = last_time ? time - last_time : time - @start
last_time = time
puts "[stopwatch @time=#{human_time(elapsed)}] split #{message} "
end unless @splits.empty?
end
def report_events
tallies = {}
@events.each do |event|
tallies[event.message] = Tally.new(event.message) unless tallies[event.message]
tallies[event.message].add(event)
end
tallies.each do |key,tally|
puts "[stopwatch @time=#{human_time(tally.duration)}] event #{tally.message} (#{tally.count.to_i})"
end
end
def human_time(time)
"%.2fms" % (time * 1_000)
end
end
end
require "test/unit"
require File.expand_path(File.join(File.dirname(__FILE__), "stopwatch"))
class TestStopwatch Test::Unit::TestCase
class ExampleLogger
include Singleton
def log(message)
p message
end
def self.alias_method_chain(target, feature)
alias_method "#{target}_without_#{feature}", target
alias_method target, "#{target}_with_#{feature}"
end
end
ExampleLogger.class_eval do
def log_with_test(message, &block)
Stopwatch.instance.event("a") do
log_without_test(message, &block)
end
end
alias_method_chain :log, :test
end
def setup
Stopwatch.reset
end
def test_watch
assert(!Stopwatch.instance.running)
Stopwatch.watch do
assert(Stopwatch.instance.running)
end
assert(!Stopwatch.instance.running)
end
def test_splits
Stopwatch.watch do |watcher|
watcher.split("a")
watcher.split("b")
watcher.split("c")
end
assert_equal(Stopwatch.instance.splits.size, 3)
assert_equal(Stopwatch.instance.splits.collect { |split| split.message }, ["a", "b", "c"])
end
def test_nested
Stopwatch.watch do |watcher|
watcher.split("a")
Stopwatch.watch do |watcher|
watcher.split("b")
end
assert(Stopwatch.instance.running)
end
assert_equal(Stopwatch.instance.splits.size, 2)
assert_equal(Stopwatch.instance.splits.collect { |split| split.message }, ["a", "b"])
end
def test_split_report
Stopwatch.watch do |watcher|
watcher.split("a")
watcher.split("b")
watcher.split("c")
watcher.report
end
end
def test_events
Stopwatch.watch do |watcher|
ExampleLogger.instance.log("message")
Stopwatch.instance.event("b") do
end
end
assert_equal(Stopwatch.instance.events.size, 2)
assert_equal(Stopwatch.instance.events.collect { |event| event.message }, ["a", "b"])
end
def test_no_events
Stopwatch.watch do |watcher|
end
ExampleLogger.instance.log("message")
Stopwatch.instance.event("b") do
end
assert_equal(Stopwatch.instance.events.size, 0)
end
end
require 'test/unit'
class Trie
def initialize()
@root = TrieNode.new
@entry_count = 0
end
def empty?
@entry_count == 0;
end
def size
@entry_count
end
def add(key, value)
return if key.nil? || key.empty?
current_node = @root
key.each_char { |character|
next_node = current_node.get(character)
next_node = current_node.add(character) unless next_node
current_node = next_node
}
current_node
current_node.value = value
@entry_count += 1
end
def contains(str)
# todo...
end
def find(string)
results = []
(0..string.length-1).each { |start_index|
start_index
current_node = @root
(start_index..string.length-1).each { |i|
ch = string[i].chr
current_node = current_node.get(ch)
break if current_node.nil?
results.push current_node.values if current_node.values?
}
}
results
end
class TrieNode
def initialize()
@children = Hash.new
end
def value=(value)
if (@values.nil?)
@values = Array.new
end
@values.push value
end
def get(character)
@children[character]
end
def add(character)
node = TrieNode.new
@children[character] = node
node
end
def values
@values
end
def values?
!@values.nil?
end
end
end
class TriTest Test::Unit::TestCase
def test_empty?
trie = Trie.new
assert(trie.empty?)
trie.add("key", "value")
assert(!trie.empty?)
end
def test_size
trie = Trie.new
trie.add("key", "value")
assert_equal(1, trie.size)
end
def test_ignores_nil_or_empty_string
trie = Trie.new
trie.add("", "value")
trie.add(nil, "value")
assert(trie.empty?)
end
def test_find
trie = Trie.new
trie.add("key", "value")
assert_equal(1, trie.find("key").size)
trie.add("keys", "value")
assert_equal(2, trie.find("keys").size)
end
def test_allows_duplicates
trie = Trie.new
trie.add("key", "value")
trie.add("key", "value")
assert(!trie.empty?)
end
end
source /usr/local/etc/bash_completion.d/git-completion.bash
alias gits="git status"
git add -p
[alias]
staged = diff --cached
[color]
status = auto
branch = auto
diff = auto
…couldn’t resist making a few changes to mizuno including an abstract handler, jmx suport, and slf4j logging. It’s just a placeholder for now…still fleshing out some new ideas.
module Mizuno
class HttpServer
include_class 'org.eclipse.jetty.server.Server'
include_class 'org.eclipse.jetty.servlet.ServletContextHandler'
include_class 'org.eclipse.jetty.servlet.ServletHolder'
include_class 'org.eclipse.jetty.util.thread.QueuedThreadPool'
include_class 'org.eclipse.jetty.servlet.DefaultServlet'
include_class 'org.eclipse.jetty.jmx.MBeanContainer'
include_class 'org.eclipse.jetty.server.Server'
include_class 'java.lang.management.ManagementFactory'
include_class 'javax.management.MBeanServer'
include_class 'org.slf4j.Logger'
include_class 'org.slf4j.LoggerFactory'
@@logger = LoggerFactory.getLogger("HttpServer")
def self.run(app, options = {})
options = Hash[options.map { |option| [option[0].to_s.downcase.to_sym, option[1]] }]
port = options[:port].to_i
thread_pool = QueuedThreadPool.new
thread_pool.min_threads = 5
thread_pool.max_threads = 50
rack_handler = RackHandler.new
rack_handler.rackup(app)
@server = Server.new(port)
@container = MBeanContainer.new(ManagementFactory.getPlatformMBeanServer)
@server.container.addEventListener(@container)
@server.set_thread_pool(thread_pool)
@server.set_handler(rack_handler)
@server.start
@@logger.info("Started jetty on port {}.", port)
trap("SIGINT") { @server.stop and exit }
@server.join unless options[:embedded]
end
def self.stop
@server.stop
@@logger.info("Stopper jetty.")
end
end
end
Rack::Handler.register 'mizuno', 'Mizuno::HttpServer'