neolytics 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ line,method,sum,count,average
2
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/railties-4.2.5/lib/rails/generators/named_base.rb:2,Kernel#require,55422,2,27711
3
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/rack-1.6.4/lib/rack/utils.rb:5,Kernel#require,27433,2,13716.5
4
+ /Users/brian/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/set.rb:292,Set#add,19018,2343,8.116944088775075
5
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/core_ext/module/delegation.rb:214,Module#module_eval,17404,160,108.775
6
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/commands.rb:5,Kernel#require,16623,104,159.83653846153845
7
+ /Users/brian/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/set.rb:283,Hash#each_key,15520,54,287.4074074074074
8
+ /Users/brian/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/forwardable.rb:192,Module#module_eval,11143,108,103.17592592592592
9
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/command.rb:34,#<Class:Pry::Command>#match,8824,810,10.893827160493828
10
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sprockets-rails-2.3.3/lib/sprockets/railtie.rb:6,Kernel#require,8672,2,4336
11
+ /Users/brian/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/set.rb:94,Array#each,8640,90,96
12
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/inflector/methods.rb:100,ActiveSupport::Inflector#underscore,7288,237,30.751054852320674
13
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activemodel-4.2.5/lib/active_model/validations.rb:404,Kernel#require,6561,26,252.34615384615384
14
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/script/value/color.rb:23,Range#each,6495,298,21.79530201342282
15
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/command.rb:183,#<Class:Pry::Command>#command_regex,6131,510,12.02156862745098
16
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/command.rb:47,#<Class:Pry::Command>#command_options,6111,641,9.533541341653667
17
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/command.rb:192,#<Class:Pry::Command>#convert_to_regex,5683,1020,5.57156862745098
18
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/neo4j-6.0.1/lib/neo4j.rb:47,Kernel#require,5516,2,2758
19
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/script.rb:1,Kernel#require,5350,2,2675
20
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/actionview-4.2.5/lib/action_view/helpers/form_helper.rb:1321,Module#class_eval,5178,34,152.2941176470588
21
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/bundler-1.11.2/lib/bundler/runtime.rb:77,#<Class:Kernel>#require,4845,30,161.5
22
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/nokogiri-1.6.7/lib/nokogiri/html/element_description_defaults.rb:650,Array#each,4676,2,2338
23
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/inflector/inflections.rb:209,ActiveSupport::Inflector#inflections,4633,238,19.46638655462185
24
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/neo4j-6.0.1/lib/neo4j.rb:38,Kernel#require,4486,2,2243
25
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/script.rb:34,Kernel#require,4464,2,2232
26
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/tree/node.rb:35,BasicObject#instance_eval,4387,54,81.24074074074075
27
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/core_ext/module/attribute_accessors.rb:57,Module#class_eval,4263,66,64.5909090909091
28
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/command_set.rb:318,Array#select,4040,24,168.33333333333334
29
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/dependencies/autoload.rb:46,ActiveSupport::Autoload#autoload,3681,233,15.798283261802576
30
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sprockets-3.5.2/lib/sprockets/utils.rb:41,Sprockets::Utils#hash_reassoc1,3467,115,30.14782608695652
31
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/core_ext/string/output_safety.rb:231,Module#class_eval,3212,38,84.52631578947368
32
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/neo4j-6.0.1/lib/neo4j.rb:51,Kernel#require,3087,2,1543.5
33
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/neo4j-6.0.1/lib/neo4j.rb:82,Kernel#require,2914,2,1457
34
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/temple-0.7.6/lib/temple/mixins/engine_dsl.rb:55,Module#const_get,2849,18,158.27777777777777
35
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/temple-0.7.6/lib/temple/map.rb:12,Array#any?,2833,290,9.76896551724138
36
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.5/lib/action_controller/metal/live.rb:1,Kernel#require,2765,2,1382.5
37
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/script/functions.rb:407,Array#map,2717,180,15.094444444444445
38
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/nokogiri-1.6.7/lib/nokogiri/xml/parse_options.rb:61,Module#class_eval,2715,44,61.70454545454545
39
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.5/lib/active_support/core_ext/module/attribute_accessors.rb:123,Module#class_eval,2640,60,44
40
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/scss.rb:5,Kernel#require,2618,2,1309
41
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass.rb:99,Kernel#require,2556,2,1278
42
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/concurrent-ruby-1.0.0/lib/concurrent.rb:26,Kernel#require,2500,2,1250
43
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/concurrent-ruby-1.0.0/lib/concurrent/configuration.rb:2,Kernel#require,2488,2,1244
44
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sprockets-3.5.2/lib/sprockets/environment.rb:3,Kernel#require,2458,2,1229
45
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/temple-0.7.6/lib/temple/map.rb:97,Array#any?,2369,222,10.67117117117117
46
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/actionpack-4.2.5/lib/action_controller.rb:4,Kernel#require,2344,2,1172
47
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/slim-3.0.6/lib/slim.rb:2,Kernel#require,2279,2,1139.5
48
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/pry-0.10.3/lib/pry/command.rb:144,#<Class:Pry::Command>#matches?,2245,498,4.508032128514056
49
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/scss.rb:4,Kernel#require,2245,2,1122.5
50
+ /Users/brian/github/neo4j-examples/ruby_code_analytics/config/application.rb:18,Kernel#require,2223,2,1111.5
51
+ /Users/brian/.rvm/gems/ruby-2.2.3/gems/sass-3.4.20/lib/sass/script.rb:35,Kernel#require,2220,2,1110
@@ -9,7 +9,7 @@ module Neo4Apis
9
9
  uuid :ASTNode, :uuid
10
10
  uuid :File, :path
11
11
 
12
- batch_size 10000
12
+ batch_size 6000
13
13
 
14
14
  IMPORTED_OBJECT_NODES = {}
15
15
 
@@ -50,16 +50,25 @@ module Neo4Apis
50
50
  object_node
51
51
  end
52
52
 
53
- importer :TracePoint do |tp, execution_time, execution_index, last_tracepoint_node, parent, associated_call|
54
- next nil if tp.method_id.blank? && tp.defined_class.blank?
53
+ importer :TracePoint do |tp, execution_time, total_execution_time, execution_index, last_tracepoint_node, parent, associated_call|
54
+ next nil if tp.method_id.to_s.strip.empty? && tp.defined_class.to_s.strip.empty?
55
55
 
56
+ # if tp.lineno == 19 && tp.event == :line
57
+ # require 'pry'
58
+ # binding.pry
59
+ # end
56
60
  trace_point_node = add_node :TracePoint, tp, %i(event lineno method_id) do |node|
57
61
  node.uuid = SecureRandom.uuid
58
62
  node.defined_class = tp.defined_class.to_s
59
63
  node.execution_time = execution_time if execution_time
64
+ node.total_execution_time = total_execution_time if total_execution_time
60
65
  node.execution_index = execution_index
61
66
 
62
- node.path = Pathname.new(tp.path).realpath.to_s
67
+ node.path = if tp.path == '(eval)'
68
+ tp.path
69
+ else
70
+ Pathname.new(tp.path).realpath.to_s
71
+ end
63
72
  end
64
73
 
65
74
 
@@ -82,11 +91,16 @@ module Neo4Apis
82
91
  object_node = import :Object, value
83
92
  add_relationship :HAS_VARIABLE_VALUE, trace_point_node, object_node, variable_name: var
84
93
  end
94
+
95
+ # TracePointHelpers.each_referenced_object(tp) do |object|
96
+ # object_node = import :Object, object
97
+ # add_relationship :REFERENCES_OBJECT, trace_point_node, object_node, variable_name: var
98
+ # end
85
99
  end
86
100
 
87
101
  if tp.event == :call
88
- TracePointHelpers.each_received_arguments(tp) do |argument, value|
89
- object_node = import :Object, value
102
+ TracePointHelpers.each_received_arguments(tp) do |argument, object|
103
+ object_node = import :Object, object
90
104
  add_relationship :RECEIVED_ARGUMENT, trace_point_node, object_node, argument_name: argument
91
105
  end
92
106
  end
@@ -14,14 +14,18 @@ module Neo4Apis
14
14
  tp.self.class.instance_method(tp.method_id)
15
15
  end
16
16
  parameter_names = method.parameters.map {|_, name| name }
17
- arguments = parameter_names.each_with_object({}) do |name, arguments|
17
+ arguments = parameter_names.compact.each_with_object({}) do |name, arguments|
18
18
  catch :not_found do
19
+ begin
19
20
  arguments[name] = get_trace_point_var(tp, name)
21
+ rescue Exception => e
22
+ require 'pry'
23
+ binding.pry
24
+ end
20
25
  end
21
26
  end
22
27
  arguments.each do |name, object|
23
- value = RubyObject.from_object(object)
24
- yield name, value
28
+ yield name, object
25
29
  end
26
30
  end
27
31
 
@@ -36,7 +40,18 @@ module Neo4Apis
36
40
  end
37
41
  rescue Parser::SyntaxError
38
42
  nil
39
- end
43
+ end
44
+
45
+ def each_referenced_object(tp)
46
+ line = get_file_line(tp.path, tp.lineno)
47
+ root = Parser::CurrentRuby.parse(line)
48
+ extract_object_references(root).each do |inspect_string|
49
+ value = tp.binding.eval(inspect_string)
50
+ yield value
51
+ end
52
+ rescue Parser::SyntaxError
53
+ nil
54
+ end
40
55
 
41
56
  private
42
57
 
@@ -56,7 +71,23 @@ module Neo4Apis
56
71
  end
57
72
  end
58
73
 
74
+ OBJECT_NODE_TYPES = [:str, :sym, :int, :float, :hash, :array, :true, :false, :nil]
75
+ def extract_object_references(ast_node)
76
+ if ast_node.is_a?(Parser::AST::Node)
77
+ if OBJECT_NODE_TYPES.include?(ast_node.type)
78
+ [ast_node.children[0].inspect]
79
+ else
80
+ ast_node.children.flat_map do |child|
81
+ extract_object_references(child)
82
+ end
83
+ end
84
+ else
85
+ []
86
+ end
87
+ end
88
+
59
89
  def get_file_line(path, lineno)
90
+ return '' if path == '(eval)'
60
91
  FILE_LINES[path] ||= File.read(path).lines
61
92
 
62
93
  FILE_LINES[path][lineno - 1]
@@ -64,7 +95,7 @@ module Neo4Apis
64
95
 
65
96
  def get_trace_point_var(tp, var_name)
66
97
  begin
67
- tp.binding.local_variable_get(variable)
98
+ tp.binding.local_variable_get(var_name)
68
99
  rescue NameError
69
100
  throw :not_found
70
101
  end
@@ -8,6 +8,21 @@ module Neolytics
8
8
  def initialize(neo4j_session)
9
9
  @neo4j_session = neo4j_session
10
10
  @neo4apis_session = Neo4Apis::Neolytics.new(neo4j_session)
11
+ create_indexes
12
+ end
13
+
14
+ def create_indexes
15
+ @neo4j_session.query('CREATE INDEX ON :ASTNode(file_path)')
16
+ @neo4j_session.query('CREATE INDEX ON :ASTNode(first_line)')
17
+ @neo4j_session.query('CREATE INDEX ON :ASTNode(type)')
18
+ @neo4j_session.query('CREATE INDEX ON :ASTNode(name)')
19
+
20
+ @neo4j_session.query('CREATE INDEX ON :TracePoint(path)')
21
+ @neo4j_session.query('CREATE INDEX ON :TracePoint(event)')
22
+ @neo4j_session.query('CREATE INDEX ON :TracePoint(lineno)')
23
+ @neo4j_session.query('CREATE INDEX ON :TracePoint(defined_class)')
24
+ @neo4j_session.query('CREATE INDEX ON :TracePoint(method_id)')
25
+ @neo4j_session.query('CREATE INDEX ON :TracePoint(execution_index)')
11
26
  end
12
27
 
13
28
  def record(&block)
@@ -20,16 +35,24 @@ module Neolytics
20
35
  end
21
36
  end
22
37
 
23
- file_paths = @neo4j_session.query("MATCH (tp) WHERE NOT(tp.path IS NULL) RETURN DISTINCT tp.path AS path").map(&:path)
38
+ @neo4apis_session.instance_variable_get('@buffer').flush
39
+ query = <<QUERY
40
+ MATCH (tp:TracePoint)
41
+ WHERE NOT(tp.path IS NULL) AND NOT(tp.path = '(eval)')
42
+ RETURN DISTINCT tp.path AS path
43
+ QUERY
44
+ file_paths = @neo4j_session.query(query).map(&:path)
24
45
  file_paths.each(&method(:record_ast))
25
46
 
26
47
  link_query = <<QUERY
27
- MATCH (tp:TracePoint), (node:ASTNode)
48
+ MATCH (tp:TracePoint)
49
+ WITH tp, tp.lineno AS lineno, tp.path AS path, tp.method_id AS method_id
50
+ MATCH (node:ASTNode {type: 'def'})
51
+ USING INDEX node:ASTNode(name)
28
52
  WHERE
29
- node.file_path = tp.path AND
30
- node.first_line = tp.lineno AND
31
- node.name = tp.method_id AND
32
- node.type = 'def'
53
+ node.name = method_id AND
54
+ node.file_path = path AND
55
+ node.first_line = lineno
33
56
  MERGE (tp)-[:HAS_AST_NODE]->(node)
34
57
  QUERY
35
58
  @neo4j_session.query(link_query)
@@ -43,7 +66,11 @@ QUERY
43
66
  code = File.read(full_path)
44
67
 
45
68
  require 'parser/current'
46
- root = Parser::CurrentRuby.parse(code)
69
+ begin
70
+ root = Parser::CurrentRuby.parse(code)
71
+ rescue EncodingError
72
+ return
73
+ end
47
74
 
48
75
  file_node = @neo4apis_session.import :File, full_path, code
49
76
  node_node = @neo4apis_session.import :ASTNode, root, file_node
@@ -58,6 +85,7 @@ QUERY
58
85
  last_start_time = nil
59
86
  ancestor_stack = []
60
87
  run_time_stack = []
88
+ total_run_time_stack = []
61
89
 
62
90
  last_tracepoint_end_time = nil
63
91
  last_run_time = nil
@@ -66,15 +94,23 @@ QUERY
66
94
  begin
67
95
  last_run_time = 1_000_000.0 * (Time.now - last_tracepoint_end_time) if last_tracepoint_end_time
68
96
 
97
+ start = Time.now
69
98
  output << tracepoint_string(tp, indent)
70
99
 
71
100
  last_method_time = nil
72
101
  if [:call, :c_call].include?(tp.event)
73
102
  run_time_stack.push(0)
103
+ total_run_time_stack.push(0)
74
104
  elsif [:return, :c_return].include?(tp.event)
75
105
  last_method_time = run_time_stack.pop
106
+ last_method_total_time = total_run_time_stack.pop
76
107
  else
77
- run_time_stack[-1] += last_run_time if run_time_stack[-1] && last_run_time
108
+ #puts "total_run_time_stack: #{total_run_time_stack.inspect}"
109
+ #puts "increment by #{last_run_time}"
110
+ if run_time_stack[-1] && last_run_time
111
+ run_time_stack[-1] += last_run_time
112
+ total_run_time_stack.map! { |i| i + last_run_time }
113
+ end
78
114
  end
79
115
 
80
116
  associated_call = nil
@@ -87,6 +123,7 @@ QUERY
87
123
 
88
124
  last_tracepoint_node = @neo4apis_session.import :TracePoint, tp,
89
125
  last_method_time,
126
+ last_method_total_time,
90
127
  (execution_index += 1),
91
128
  last_tracepoint_node,
92
129
  ancestor_stack.last,
@@ -96,6 +133,12 @@ QUERY
96
133
  ancestor_stack.push(last_tracepoint_node)
97
134
  end
98
135
 
136
+ stop = Time.now
137
+ diff = stop - start
138
+ if diff > 0.5
139
+ puts "time: #{diff}"
140
+ puts "tp: #{tp.inspect}"
141
+ end
99
142
  last_tracepoint_end_time = Time.now
100
143
  rescue Exception => e
101
144
  puts 'EXCEPTION!!'
@@ -1,3 +1,3 @@
1
1
  module Neolytics
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/neolytics.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency 'neo4apis', '~> 0.8.2'
22
+ spec.add_dependency 'neo4apis', '~> 0.9.0'
23
23
  spec.add_dependency 'neo4j-rake_tasks', '~> 0.3.0'
24
24
  spec.add_dependency 'parser', '~> 2.2.3.0'
25
25
  spec.add_development_dependency "bundler", "~> 1.10"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neolytics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Underwood
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-28 00:00:00.000000000 Z
11
+ date: 2016-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: neo4apis
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.2
19
+ version: 0.9.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.2
26
+ version: 0.9.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: neo4j-rake_tasks
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -111,6 +111,23 @@ files:
111
111
  - Rakefile
112
112
  - bin/console
113
113
  - bin/setup
114
+ - examples/model/ast.png
115
+ - examples/model/object_relationships.png
116
+ - examples/model/trace_point_ast_nodes.png
117
+ - examples/model/trace_point_flow.png
118
+ - examples/model/trace_point_objects.png
119
+ - examples/output/abc.csv
120
+ - examples/output/all_args_vars_statics.csv
121
+ - examples/output/arguments_and_return_values.csv
122
+ - examples/output/assignments.csv
123
+ - examples/output/ast.csv
124
+ - examples/output/common_ancestor.csv
125
+ - examples/output/common_ancestor.json
126
+ - examples/output/cyclomatic_complexity.csv
127
+ - examples/output/cyclomatic_complexity_and_runtime.csv
128
+ - examples/output/numeric_class_hierarchy.png
129
+ - examples/output/numeric_return_values.csv
130
+ - examples/output/time_spent_by_method.csv
114
131
  - lib/neo4apis/neolytics.rb
115
132
  - lib/neo4apis/neolytics/trace_point_helpers.rb
116
133
  - lib/neolytics.rb