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:



536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
# File 'ext/ruby_prof/rp_method.c', line 536

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:



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
602
603
604
605
606
607
608
609
610
611
612
613
# File 'ext/ruby_prof/rp_method.c', line 564

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)


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

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)


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

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)


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

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)


528
529
530
531
532
533
# File 'ext/ruby_prof/rp_method.c', line 528

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)


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

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)


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

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)


454
455
456
457
458
459
# File 'ext/ruby_prof/rp_method.c', line 454

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:



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

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)


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

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)


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

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)


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

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)


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

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