Class: RubyProf::MethodInfo

Inherits:
Data
  • Object
show all
Includes:
Comparable
Defined in:
lib/ruby-prof/method_info.rb,
ext/ruby_prof/rp_method.c,
ext/ruby_prof/rp_method.c

Overview

The RubyProf::MethodInfo class stores profiling data for a method. One instance of the RubyProf::MethodInfo class is created per method called per thread. Thus, if a method is called in two different thread then there will be two RubyProf::MethodInfo objects created. RubyProf::MethodInfo objects can be accessed via the RubyProf::Profile object.

Instance Method Summary collapse

Instance Method Details

#<=>(other) ⇒ Object

:enddoc:



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ruby-prof/method_info.rb', line 61

def <=>(other)
  if other == nil
    -1
  elsif self.full_name == other.full_name
    0
  elsif self.total_time < other.total_time
    -1
  elsif self.total_time > other.total_time
    1
  elsif self.min_depth < other.min_depth
    1
  elsif self.min_depth > other.min_depth
    -1
  else
    self.full_name <=> other.full_name
  end
end

#_dump_dataObject

:nodoc:



524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
# File 'ext/ruby_prof/rp_method.c', line 524

static VALUE
prof_method_dump(VALUE self)
{
    prof_method_t* method_data = DATA_PTR(self);
    VALUE result = rb_hash_new();

    rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_method_klass_name(self));
    rb_hash_aset(result, ID2SYM(rb_intern("klass_flags")), INT2FIX(method_data->klass_flags));
    rb_hash_aset(result, ID2SYM(rb_intern("method_name")), method_data->method_name);

    rb_hash_aset(result, ID2SYM(rb_intern("key")), INT2FIX(method_data->key));
    rb_hash_aset(result, ID2SYM(rb_intern("root")), prof_method_root(self));
    rb_hash_aset(result, ID2SYM(rb_intern("recursive")), prof_method_recursive(self));
    rb_hash_aset(result, ID2SYM(rb_intern("excluded")), prof_method_excluded(self));
    rb_hash_aset(result, ID2SYM(rb_intern("source_file")), method_data->source_file);
    rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(method_data->source_line));

    rb_hash_aset(result, ID2SYM(rb_intern("measurement")), prof_measurement_wrap(method_data->measurement));

    rb_hash_aset(result, ID2SYM(rb_intern("callers")), prof_method_callers(self));
    rb_hash_aset(result, ID2SYM(rb_intern("callees")), prof_method_callees(self));

    rb_hash_aset(result, ID2SYM(rb_intern("allocations")), prof_method_allocations(self));

    return result;
}

#_load_data(data) ⇒ Object

:nodoc:



552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'ext/ruby_prof/rp_method.c', line 552

static VALUE
prof_method_load(VALUE self, VALUE data)
{
    prof_method_t* method_data = RDATA(self)->data;
    method_data->object = self;

    method_data->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
    method_data->klass_flags = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("klass_flags"))));
    method_data->method_name = rb_hash_aref(data, ID2SYM(rb_intern("method_name")));
    method_data->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));

    method_data->root = rb_hash_aref(data, ID2SYM(rb_intern("root"))) == Qtrue ? true : false;
    method_data->recursive = rb_hash_aref(data, ID2SYM(rb_intern("recursive"))) == Qtrue ? true : false;
    method_data->excluded = rb_hash_aref(data, ID2SYM(rb_intern("excluded"))) == Qtrue ? true : false;

    method_data->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
    method_data->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));

    VALUE measurement = rb_hash_aref(data, ID2SYM(rb_intern("measurement")));
    method_data->measurement = prof_get_measurement(measurement);

    VALUE callers = rb_hash_aref(data, ID2SYM(rb_intern("callers")));
    for (int i = 0; i < rb_array_len(callers); i++)
    {
        VALUE call_info = rb_ary_entry(callers, i);
        prof_call_info_t *call_info_data = prof_get_call_info(call_info);
        st_data_t key = call_info_data->parent ? call_info_data->parent->key : method_key(Qnil, 0);
        call_info_table_insert(method_data->parent_call_infos, key, call_info_data);
    }

    VALUE callees = rb_hash_aref(data, ID2SYM(rb_intern("callees")));
    for (int i = 0; i < rb_array_len(callees); i++)
    {
        VALUE call_info = rb_ary_entry(callees, i);
        prof_call_info_t *call_info_data = prof_get_call_info(call_info);

        st_data_t key = call_info_data->method ? call_info_data->method->key : method_key(Qnil, 0);
        call_info_table_insert(method_data->child_call_infos, key, call_info_data);
    }

    VALUE allocations = rb_hash_aref(data, ID2SYM(rb_intern("allocations")));
    for (int i = 0; i < rb_array_len(allocations); i++)
    {
        VALUE allocation = rb_ary_entry(allocations, i);
        prof_allocation_t* allocation_data = prof_allocation_get(allocation);

        st_insert(method_data->allocations_table, allocation_data->key, (st_data_t)allocation_data);
    }
    return data;
}

#allocationsArray

Returns an array of allocation information.

Returns:

  • (Array)


407
408
409
410
411
412
413
414
# File 'ext/ruby_prof/rp_method.c', line 407

static VALUE
prof_method_allocations(VALUE self)
{
    prof_method_t* method = prof_get_method(self);
    VALUE result = rb_ary_new();
    st_foreach(method->allocations_table, prof_method_collect_allocations, result);
    return result;
}

#calledObject

The number of times this method was called



31
32
33
# File 'lib/ruby-prof/method_info.rb', line 31

def called
  self.measurement.called
end

#calleesArray

Returns an array of call info objects that this method called (ie, children).

Returns:

  • (Array)


394
395
396
397
398
399
400
401
# File 'ext/ruby_prof/rp_method.c', line 394

static VALUE
prof_method_callees(VALUE self)
{
    prof_method_t* method = prof_get_method(self);
    VALUE result = rb_ary_new();
    st_foreach(method->child_call_infos, prof_method_collect_call_infos, result);
    return result;
}

#callersArray

Returns an array of call info objects that called this method (ie, parents).

Returns:

  • (Array)


381
382
383
384
385
386
387
388
# File 'ext/ruby_prof/rp_method.c', line 381

static VALUE
prof_method_callers(VALUE self)
{
    prof_method_t* method = prof_get_method(self);
    VALUE result = rb_ary_new();
    st_foreach(method->parent_call_infos, prof_method_collect_call_infos, result);
    return result;
}

#children_timeObject

The time this method’s children took to execute



51
52
53
# File 'lib/ruby-prof/method_info.rb', line 51

def children_time
  self.total_time - self.self_time - self.wait_time
end

#eliminate!Object

Remove method from the call graph. should not be called directly.



84
85
86
87
88
# File 'lib/ruby-prof/method_info.rb', line 84

def eliminate!
  # $stderr.puts "eliminating #{self}"
  callers.each{ |call_info| call_info.eliminate! }
  callers.clear
end

#excluded?Boolean

Returns the true if this method was excluded

Returns:

  • (Boolean)


516
517
518
519
520
521
# File 'ext/ruby_prof/rp_method.c', line 516

static VALUE
prof_method_excluded(VALUE self)
{
    prof_method_t* method = prof_method_get(self);
    return method->excluded ? Qtrue : Qfalse;
}

#full_nameObject

Returns the full name of a class. The interpretation of method names is:

  • MyObject#test - An method defined in a class

  • <Class:MyObject>#test - A method defined in a singleton class.

  • <Module:MyObject>#test - A method defined in a singleton module.

  • <Object:MyObject>#test - A method defined in a singleton object.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/ruby-prof/method_info.rb', line 15

def full_name
  decorated_class_name = case self.klass_flags
                         when 0x2
                           "<Class::#{klass_name}>"
                         when 0x4
                           "<Module::#{klass_name}>"
                         when 0x8
                           "<Object::#{klass_name}>"
                         else
                           klass_name
                         end

  "#{decorated_class_name}##{method_name}"
end

#klass_flagsInteger

Returns the klass flags

Returns:

  • (Integer)


470
471
472
473
474
475
# File 'ext/ruby_prof/rp_method.c', line 470

static VALUE
prof_method_klass_flags(VALUE self)
{
    prof_method_t* method = prof_method_get(self);
    return INT2FIX(method->klass_flags);
}

#klass_nameString

Returns the name of this method’s class. Singleton classes will have the form <Object::Object>.

Returns:

  • (String)


455
456
457
458
459
460
461
462
463
# File 'ext/ruby_prof/rp_method.c', line 455

static VALUE
prof_method_klass_name(VALUE self)
{
    prof_method_t *method = prof_method_get(self);
    if (method->klass_name == Qnil)
        method->klass_name = resolve_klass_name(method->klass, &method->klass_flags);

    return method->klass_name;
}

#line_noInteger

returns the line number of the method

Returns:

  • (Integer)


442
443
444
445
446
447
# File 'ext/ruby_prof/rp_method.c', line 442

static VALUE
prof_method_line(VALUE self)
{
    prof_method_t* method = prof_method_get(self);
    return INT2FIX(method->source_line);
}

#calledMeasurement

Returns the measurement associated with this method.

Returns:



420
421
422
423
424
425
# File 'ext/ruby_prof/rp_method.c', line 420

static VALUE
prof_method_measurement(VALUE self)
{
    prof_method_t* method = prof_get_method(self);
    return prof_measurement_wrap(method->measurement);
}

#method_nameString

Returns the name of this method in the format Object#method. Singletons methods will be returned in the format <Object::Object>#method.

Returns:

  • (String)


483
484
485
486
487
488
# File 'ext/ruby_prof/rp_method.c', line 483

static VALUE
prof_method_name(VALUE self)
{
    prof_method_t *method = prof_method_get(self);
    return method->method_name;
}

#min_depthObject

The min call depth of this method



56
57
58
# File 'lib/ruby-prof/method_info.rb', line 56

def min_depth
  @min_depth ||= callers.map(&:depth).min
end

#recursive?Boolean

Returns the true if this method is recursively invoked

Returns:

  • (Boolean)


505
506
507
508
509
510
# File 'ext/ruby_prof/rp_method.c', line 505

static VALUE
prof_method_recursive(VALUE self)
{
    prof_method_t* method = prof_method_get(self);
    return method->recursive ? Qtrue : Qfalse;
}

#root?Boolean

Returns the true if this method is at the top of the call stack

Returns:

  • (Boolean)


494
495
496
497
498
499
# File 'ext/ruby_prof/rp_method.c', line 494

static VALUE
prof_method_root(VALUE self)
{
    prof_method_t *method = prof_method_get(self);
    return method->root ? Qtrue : Qfalse;
}

#self_timeObject

The time this method took to execute



41
42
43
# File 'lib/ruby-prof/method_info.rb', line 41

def self_time
  self.measurement.self_time
end

#source_fileString

return the source file of the method

Returns:

  • (String)


432
433
434
435
436
# File 'ext/ruby_prof/rp_method.c', line 432

static VALUE prof_method_source_file(VALUE self)
{
    prof_method_t* method = prof_method_get(self);
    return method->source_file;
}

#to_sObject



79
80
81
# File 'lib/ruby-prof/method_info.rb', line 79

def to_s
  "#{self.full_name} (c: #{self.called}, tt: #{self.total_time}, st: #{self.self_time}, wt: #{wait_time}, ct: #{self.children_time})"
end

#total_timeObject

The total time this method took - includes self time + wait time + child time



36
37
38
# File 'lib/ruby-prof/method_info.rb', line 36

def total_time
  self.measurement.total_time
end

#wait_timeObject

The time this method waited for other fibers/threads to execute



46
47
48
# File 'lib/ruby-prof/method_info.rb', line 46

def wait_time
  self.measurement.wait_time
end