Skip to content

Commit

Permalink
Showing 10 changed files with 196 additions and 2 deletions.
12 changes: 12 additions & 0 deletions core/src/main/java/org/jruby/Main.java
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.SafePropertyAccessor;
import org.jruby.util.cli.Options;
import org.jruby.util.cli.OutputStrings;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
@@ -183,6 +184,8 @@ public static class Status {
* @param args command-line args, provided by the JVM.
*/
public static void main(String[] args) {
printTruffleTimeMetric("before-main");

doGCJCheck();

Main main;
@@ -217,6 +220,8 @@ public static void main(String[] args) {

System.exit(1);
}

printTruffleTimeMetric("after-main");
}

public Status run(String[] args) {
@@ -531,6 +536,13 @@ protected static int handleRaiseException(RaiseException rj) {
}
}

public static void printTruffleTimeMetric(String id) {
if (Options.TRUFFLE_METRICS_TIME.load()) {
final long millis = System.currentTimeMillis();
System.err.printf("%s %d.%03d%n", id, millis / 1000, millis % 1000);
}
}

private final RubyInstanceConfig config;
}

9 changes: 8 additions & 1 deletion core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -79,7 +79,6 @@
import org.jruby.common.RubyWarnings;
import org.jruby.compiler.JITCompiler;
import org.jruby.embed.Extension;
import org.jruby.exceptions.JumpException;
import org.jruby.exceptions.MainExitException;
import org.jruby.exceptions.RaiseException;
import org.jruby.exceptions.Unrescuable;
@@ -549,7 +548,9 @@ public void runFromMain(InputStream inputStream, String filename) {
return;
}

Main.printTruffleTimeMetric("before-parse");
ParseResult parseResult = parseFromMain(filename, inputStream);
Main.printTruffleTimeMetric("after-parse");

// if no DATA, we're done with the stream, shut it down
if (fetchGlobalConstant("DATA") == null) {
@@ -843,7 +844,9 @@ public IRubyObject runInterpreter(ThreadContext context, Node rootNode, IRubyObj
if (getInstanceConfig().getCompileMode() == CompileMode.TRUFFLE) {
assert rootNode instanceof RootNode;
assert self == getTopSelf();
Main.printTruffleTimeMetric("before-run");
getTruffleContext().execute((RootNode) rootNode);
Main.printTruffleTimeMetric("after-run");
return getNil();
} else {
return Interpreter.getInstance().execute(this, rootNode, self);
@@ -891,6 +894,8 @@ public TruffleContextInterface getTruffleContext() {
}

private TruffleContextInterface loadTruffleContext() {
Main.printTruffleTimeMetric("before-load-truffle-context");

final Class<?> clazz;

try {
@@ -910,6 +915,8 @@ private TruffleContextInterface loadTruffleContext() {

truffleContext.initialize();

Main.printTruffleTimeMetric("after-load-truffle-context");

return truffleContext;
}

2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -149,6 +149,8 @@ public class Options {
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_CLONED = bool(TRUFFLE, "truffle.call.method_missing_always_cloned", true, "Always clone #method_missing call targets.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_INLINED = bool(TRUFFLE, "truffle.call.method_missing_always_inlined", true, "Always inline #method_missing call targets.");

public static final Option<Boolean> TRUFFLE_METRICS_TIME = bool(TRUFFLE, "truffle.metrics.time", false, "Print the time at various stages of VM operation.");

public static final Option<Boolean> NATIVE_ENABLED = bool(NATIVE, "native.enabled", true, "Enable/disable native code, including POSIX features and C exts.");
public static final Option<Boolean> NATIVE_VERBOSE = bool(NATIVE, "native.verbose", false, "Enable verbose logging of native extension loading.");
public static final Option<Boolean> FFI_COMPILE_DUMP = bool(NATIVE, "ffi.compile.dump", false, "Dump bytecode-generated FFI stubs to console.");
36 changes: 36 additions & 0 deletions test/truffle/memory/minimum-heap.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env ruby
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# Calculates the approximate minimum heap sized needed to run hello world.
# Not run it fast - just run it at all.

# For example:
# $ ruby test/truffle/memory/minimum-heap.rb bin/jruby "-X+T -e 'puts 14'"

tolerance = 1

lower = 0
upper = 4 * 1024

while upper - lower > tolerance
mid = lower + (upper - lower) / 2

print "trying #{mid}m... "
can_run = !(`#{ARGV[0]} -J-Xmx#{mid}m #{ARGV[1]} 2>&1`.include? 'GC overhead limit exceeded')

if can_run
puts "yes"
upper = mid
else
puts "no"
lower = mid
end
end

puts "minimum heap: #{upper}m"
25 changes: 25 additions & 0 deletions test/truffle/startup/count-classes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env ruby
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# Counts how many classes are loaded to run a program.

# For example:
# $ bin/jruby -X+T -J-XX:+TraceClassLoading -e 'puts 14' 2>&1 | ruby test/truffle/startup/count-classes.rb

classes = 0

ARGF.each do |line|
if line.start_with? '[Loaded '
classes += 1
else
puts line
end
end

puts "classes-loaded #{classes}"
14 changes: 14 additions & 0 deletions test/truffle/startup/jruby-timed
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

gnu_date() {
if hash gdate 2> /dev/null
then
gdate "$@"
else
date "$@"
fi
}

gnu_date +"before-launcher %s.%N"
bin/jruby "$@"
gnu_date +"after-launcher %s.%N"
49 changes: 49 additions & 0 deletions test/truffle/startup/process-times.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env ruby
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# Calculates where the time goes for important regions while running a program.

# For example:
# $ test/truffle/startup/jruby-timed -X+T -Xtruffle.metrics.time=true -e 'puts 14' 2>&1 | ruby test/truffle/startup/process-times.rb

before_times = {}
after_times = {}
nesting = 0
accounted = 0

ARGF.each do |line|
if line =~ /([\w-]+) (\d+\.\d+)/
id = $1.split('-')
relative = id.first
region = id.drop(1).join('-')
time = $2.to_f

case relative
when 'before'
before_times[region] = time
nesting += 1
when 'after'
after_times[region] = time
elapsed = time - before_times[region]

# 3 means ignore launcher, ignore main, then count regions within that
if nesting == 3 && !(['launcher', 'main'].include? region)
accounted += elapsed
end

puts "#{region} #{elapsed}"
nesting -= 1
end
end
end

total = after_times['launcher'] - before_times['launcher']

puts "accounted #{accounted}"
puts "unaccounted #{total - accounted}"
21 changes: 21 additions & 0 deletions test/truffle/subjects/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env ruby
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# Repeatedly makes the same request, ignoring failures. Useful for server.rb
# where you may want to know how soon it can handle its first request.

require 'open-uri'

loop do
begin
open('http://localhost:8000/hello').read
rescue
next
end
end
24 changes: 24 additions & 0 deletions test/truffle/subjects/server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env ruby
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# Serves a single request then shuts down. Useful with client.rb to make that
# request.

require 'webrick'

server = WEBrick::HTTPServer.new(Port: 8000)

server.mount_proc '/hello' do |req, res|
res.status = 200
res['Content-Type'] = 'text/plain'
res.body = 'Hello, World!'
server.shutdown
end

server.start
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
import org.jcodings.EncodingDB;
import org.jcodings.specific.UTF8Encoding;
import org.jcodings.transcode.EConvFlags;
import org.jruby.Main;
import org.jruby.RubyString;
import org.jruby.ext.ffi.Platform;
import org.jruby.ext.ffi.Platform.OS_TYPE;
@@ -53,7 +54,6 @@
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.layouts.ThreadBacktraceLocationLayoutImpl;
import org.jruby.truffle.runtime.layouts.ext.DigestLayoutImpl;
import org.jruby.truffle.runtime.loader.SourceLoader;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.rubinius.RubiniusTypes;
import org.jruby.truffle.runtime.signal.SignalOperations;
@@ -664,12 +664,16 @@ public void initializeAfterMethodsAdded() {
// Load Ruby core

try {
Main.printTruffleTimeMetric("before-load-truffle-core");

state = State.LOADING_RUBY_CORE;
try {
context.load(context.getSourceCache().getSource(CoreLibrary.CORE_LOAD_PATH + "/core.rb"), node, NodeWrapper.IDENTITY);
} catch (IOException e) {
throw new RuntimeException(e);
}

Main.printTruffleTimeMetric("after-load-truffle-core");
} catch (RaiseException e) {
final Object rubyException = e.getRubyException();
BacktraceFormatter.createDefaultFormatter(getContext()).printBacktrace((DynamicObject) rubyException, Layouts.EXCEPTION.getBacktrace((DynamicObject) rubyException));

0 comments on commit 492d310

Please sign in to comment.