neolytics 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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