バッチ処理の一部で 30 分以上かかっていた処理を 14 秒で終わるようにした話


Ubiregi Advent Calendar 2018 18

 POS 3014 Ruby 2.5  SEGV  - @watson1978   DTrace 使


 CSV CSV CSV DB Worker 

Rails DB

DTrace 


rbenv  Ruby  macOS  Ruby  DTrace 
$ CONFIGURE_OPTS="--enable-dtrace" rbenv install 2.5.3

DTrace 使便


 DTrace  Ruby 
#!/usr/sbin/dtrace -s

#pragma D option quiet

ruby$target:::method-entry
{
  @method_call_count[copyinstr(arg0), copyinstr(arg1)] = count();
  self->method_starttime = walltimestamp / 1000;
}

ruby$target:::cmethod-entry
{
  @method_call_count[copyinstr(arg0), copyinstr(arg1)] = count();
  self->cmethod_starttime = walltimestamp / 1000;
}

ruby$target:::method-return
{
  @invoked_time[copyinstr(arg0), copyinstr(arg1)] = sum((walltimestamp / 1000) - self->method_starttime);
}

ruby$target:::cmethod-return
{
  @invoked_time[copyinstr(arg0), copyinstr(arg1)] = sum((walltimestamp / 1000) - self->cmethod_starttime);
}

END
{
    printf("\n");
    printf("%-30s  %-15s  %s\n", "CLASS", "METHOD", "COUNT");
    printf("--------------------------------------------------------------------------------\n");
    printa("%-30s  %-15s  %@d\n", @method_call_count);

    printf("\n");
    printf("%-30s  %-15s  %s\n", "CLASS", "METHOD", "TOTAL TIME usec");
    printf("--------------------------------------------------------------------------------\n");
    printa("%-30s  %-15s  %@d\n", @invoked_time);
}

 DTrace  CTRL + C
$ sudo dtrace -q -s measure.d -p [Worker のプロセスID]

CLASS                           METHOD           COUNT
--------------------------------------------------------------------------------
#<Class:0x00007fe014884108>     lambda           424
#<Class:0x00007fe01db2a9d0>     category         424
#<Class:0x00007fe01db2a9d0>     name             424
#<Class:0x00007fe01db2a9d0>     new              424
Array                           compact          424
Array                           include?         424
Array                           select           424
Array                           zip              424
BigDecimal                      initialize       424
BigDecimal                      new              424
Class                           new              424
Enumerable                      all?             424
Kernel                          method           424
Method                          to_proc          424
Regexp                          ===              424
String                          gsub!            424
String                          rstrip!          424
String                          sub!             424
#<Class:0x00007fe01db2a9d0>     group            425
#<Class:0x00007fe01db2a9d0>     item_type        848
Integer                         ===              848
#<Class:0x00007fe01db2a9d0>     vat              1272
Array                           each             1272
Array                           map              1272
#<Class:0x00007fe01db2a9d0>     price            1696
#<Class:0x00007fe01db2a9d0>     sku              1696
Array                           first            1696
Kernel                          public_send      1696
Kernel                          respond_to?      1696
String                          strip            1696
Regexp                          match?           2120
Struct                          []=              4240
Symbol                          =~               4240

CLASS                           METHOD           TOTAL TIME usec
--------------------------------------------------------------------------------
Array                           compact          1617
String                          rstrip!          1727
Kernel                          method           2196
String                          gsub!            2790
Integer                         ===              2829
BigDecimal                      initialize       2844
Array                           zip              2861
String                          sub!             3295
Regexp                          ===              3980
Class                           new              4410
Array                           select           4515
Array                           first            5171
Kernel                          respond_to?      5820
BigDecimal                      new              6126
Enumerable                      all?             6158
String                          strip            6200
Array                           map              6604
Array                           each             8555
Regexp                          match?           11051
Kernel                          public_send      12027
Struct                          []=              13245
Symbol                          =~               16732
#<Class:0x00007fe01db2a9d0>     category         533850
#<Class:0x00007fe01db2a9d0>     new              537748
#<Class:0x00007fe01db2a9d0>     name             540244
#<Class:0x00007fe014884108>     lambda           547411
Method                          to_proc          549701
#<Class:0x00007fe01db2a9d0>     group            604678
#<Class:0x00007fe01db2a9d0>     item_type        1076239
#<Class:0x00007fe01db2a9d0>     vat              1599474
#<Class:0x00007fe01db2a9d0>     sku              2143290
#<Class:0x00007fe01db2a9d0>     price            2152747
Array                           include?         1544897529611642

 Array#include?  424 

Array#include? 


Array#include? C cmethod-entry  Array#include?  cmethod-entry Array#include? 
#!/usr/sbin/dtrace -s

#pragma D option quiet

// ruby:::cmethod-entry(classname, methodname, filename, lineno);
ruby$target:::cmethod-entry
/ copyinstr(arg0) == "Array" && copyinstr(arg1) == "include?" /
{
  printf("%s : %d\n", copyinstr(arg2), arg3);
}


$ sudo dtrace -q -s trace.d -p [Worker のプロセスID]
/Users/watson/src/ubiregi-server/lib/menu_import/menu_reader.rb : 60
/Users/watson/src/ubiregi-server/lib/menu_import/menu_reader.rb : 60
/Users/watson/src/ubiregi-server/lib/menu_import/menu_reader.rb : 60
/Users/watson/src/ubiregi-server/lib/menu_import/menu_reader.rb : 60
...(略)...

 Ruby DTrace 便(\( )/)



data = (1..200_000).to_a.map(&:to_s)

array = []
data.each do |item|
  if array.include?(item)
    raise "item is not uniq"
  end
  array << item
end

 Array#include? Array#include? 

Hash 使
data = (1..200_000).to_a.map(&:to_s)

hash = {}
data.each do |item|
  if hash[item]
    raise "item is not uniq"
  end

  hash[item] = true
end

 2091.88 sec  13.94 sec 


DTrace 使調便