kubo39's blog

ただの雑記です。

ぴにゃっ!

今日は引き続きCloudFrontのコード化を調べていた。

それにしても突然急激な眠気に襲われて、ああ俺はこんなところで死ぬのか…というかんじがあった。労は人間から活力を奪います。

アニメ

ガーリッシュナンバー!をみていました。労のわるさのはなしがありました。ちーさまはかわいいので勝利ですね。勝ったなガハハ!w

ドリフターズ!をみました。敵側が胸糞ですね。性のわるさも観測されました。話自体はおもしろいです。

悲しいや辛いはほうっておくとどんどん心を満たしていくの

祝日だった。祝日でない日はさしずめ呪いの日か。

サッカー

浦和レッズの年間優勝を見届けた。内容自体は凡庸。

アニメ

アイカツスターズ!をみました。お別れの手紙のシーンでわんわんおたく泣きをしてしまいました。これは泣いてまうやろ。。

フリップフラッパーズ!をみました。ホラーテイストなシーンがこわかった。なんだかこの2人にも幸せになってもらいたいなと思いました。

レガリアをみました。ひとりぼっちはさびしいもんな…

競女をみました。すごい(すごい)

コードを書き換えずに実行時のメモリ使用量を観測したい

元のプログラムを書き換えることなく実行中にメモリ使用量をみることを考える。

libcの関数、例えば free(3) にフックを仕込んでみたらどうだろうか。

こういうコードを書く。

import core.stdc.stdio : printf;
import core.sys.linux.dlfcn : dlsym, RTLD_NEXT;

extern (C)
{
    struct mallinfo_
    {
        int arena;  /* Non-mmapped space allocated (bytes) */
        int ordblks;  /* Number of free chunks */
        int smblks;  /* Number of free fastbin blocks */
        int hblks;  /* Number of mmapped regions */
        int hblkhd;  /* Space allocated in mmapped regions (bytes) */
        int usmblks;  /* Maximum total allocated space (bytes) */
        int fsmblks;  /* Space in freed fastbin blocks (bytes) */
        int uordblks;  /* Total allocated space (bytes) */
        int fordblks;  /* Total free space (bytes) */
        int keepcost;  /* Top-most, releasable space (bytes) */
    }

    mallinfo_ mallinfo();

    void free(void *ptr)
    {
        auto info = mallinfo();
        printf("mallinfo arena:  %d.\n", info.arena);
        auto original = cast(void function(void*)) dlsym(RTLD_NEXT, "free");
        return original(ptr);
    }
}

いい感じに観測できていそうだ。いろいろオプションがついているが、-sharedは共有リンクライブラリを作成するためにつけており、-defaultlibや-fPICはGCC hardenedのためこうしているだけでこれらは本質的な部分ではない。

(dmd-2.072.0)( ՞ਊ ՞) :~/dev/dlang $ dmd -shared -fPIC -defaultlib=libphobos2.so freewrap.d
(dmd-2.072.0)( ՞ਊ ՞) :~/dev/dlang $ LD_PRELOAD=./freewrap.so dmd -fPIC -defaultlib=libphobos2.so hello.d
malloc info arena:  135168.
malloc info arena:  135168.
malloc info arena:  135168.
...
malloc info arena:  2195456.
malloc info arena:  2195456.
malloc info arena:  2195456.

originalのfree(3)を実行する直前のメモリ使用量を観測できた。

LD_PRELOADを使った方法なので、共有リンクライブラリで定義されている関数でしか使えないが、それなりに役に立つ可能性はありそう。

幸せとか考えたら自殺するしかないよな

精神の失われがありました。コミュニケーション異常に難しいのですがなんとかならないですかね。

cloudfrontのコード化

terraform/ansible/cloudformation を調査していた。といってもリンク集めくらい。

THP

echo never > /sys/kernel/mm/transparent_hugepage/enabled をやった場合効果があるだろうか、とかを考えていた。

Linuxカーネルのドキュメントを持ってくるのに、aptはlinux-docパッケージなのにCentOSというかyumはkernel-docという名前なのにハマっていた。

peformance系ツール

弊社はCentOS7.1を使っているため古いカーネル(3.10)を使っており、eBPFベースの iovisor/bcc を使うことができない。

brendangregg/perf-tools

これが使えそうだと思ったのだが、debugfsに依存しているためXFSでは使えないようだ。

debugfs:  ls
ls: Filesystem not open

ねほりんぱほりん

人間社会のゴミ性を観測していました。はやく滅んでほしいですね。

アニメ

響け!ユーフォニアム!をみました。

自己肯定感の失われが激しい。交互に波がくるかんじなんだけれども、まあそのうち他人の評価とかどうでもよくなってくるのでそれまで待つしかないですね。

Rust

労のあいだの空き時間にリハビリとして触っていた。

Boxのコピーは単に clone() を呼び出せば良さそう。

fn main() {
    let a = Box::new(1);  // allocated on the heap.
    let _ = a;  // moved, a is no longer accessable.
    // println!("{}", a); << panic!

    let a = Box::new(2);  // allocated on the heap.
    let _ = a.clone();  // copied.
    println!("{}", a);  // we can access.
}

Boxのcloneは malloc + memset + memcpy が走っているのだと思うんだけど、objdump -drSで追うのはなかなかきついものがある。

fn main() {
    let mut a = Box::new(2);  // allocated on the heap.
    let b = a.clone();  // copied.
    *a = 3;
    println!("{}", a);  // a = 3.
    println!("{}", b);  // b = 2.
}

D言語

D言語でBoxを表現するとどうなるかな。

一旦所有権を無視して、内部的におこっていることをみるとこうなる。

import std.stdio;
import core.stdc.string : memcpy;

void main()
{
    auto a = new int(1);  // allocated on the heap.
    auto b = new int;
    memcpy(b, a, int.sizeof);
    *a = 2;
    writefln("a = %d.", *a);  // a = 2.
    writefln("b = %d.", *b);  // b = 1.
}

上のmoveはどう表現するのかな、std.typecons.Uniqueはなんだか使用感が違う感じがする。

アニメ

まといちゃんをみました。キャラデザがけっこういいです。

Crystalのprofiling的なsomething?

まずは環境。

( ՞ਊ ՞) :~/dev/crystal $ crystal --version
Crystal 0.19.4 [7f82f79] (2016-10-07)
( ՞ਊ ՞) :~/dev/crystal $ cat /etc/issue
Ubuntu 16.10 \n \l

( ՞ਊ ՞) :~/dev/crystal $ cat /proc/version
Linux version 4.8.0-26-generic (buildd@lgw01-58) (gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12) ) #28-Ubuntu SMP Tue Oct 18 14:39:52 UTC 2016

こういう雑なコードを書く。

arr = [] of Int32
(0..1e7).each do |i|
  arr << i
end

-d つきでビルドしてDWARF吐くように。

( ՞ਊ ՞) :~/dev/crystal $ crystal build -d arr_push.cr
( ՞ਊ ՞) :~/dev/crystal $ crystal build --release -d arr_push.cr  # リリースビルド

time (bash組み込み)

まあ一番雑に

( ՞ਊ ՞) :~/dev/crystal $ time ./arr_push

real    0m0.198s
user    0m0.212s
sys     0m0.020s

こちらは releaseビルドの結果。

( ՞ਊ ՞) :~/dev/crystal $ time ./arr_push

real    0m0.105s
user    0m0.096s
sys     0m0.040s

/usr/bin/time

もう少し細かく。見方は man time 見ればなんとなくわかるはず。

( ՞ਊ ՞) :~/dev/crystal $ /usr/bin/time -v ./arr_push
        Command being timed: "./arr_push"
        User time (seconds): 0.20
        System time (seconds): 0.02
        Percent of CPU this job got: 115%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.19
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 108504
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 17448
        Voluntary context switches: 192
        Involuntary context switches: 9
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0

perf

Linuxならなんだかんだこれが楽ですよね。

( ՞ਊ ՞) :~/dev/crystal $ perf record ./arr_push
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.053 MB perf.data (936 samples) ]
( ՞ਊ ՞) :~/dev/crystal $ perf report | head -20
[kernel.kallsyms] with build id 500e786445f3c205298601de61824e582ab15bef not found, continuing without symbols
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 17
#
# Samples: 936  of event 'cycles:ppp'
# Event count (approx.): 559710139
#
# Overhead  Command   Shared Object       Symbol
# ........  ........  ..................  ....................................................................
#
    16.59%  arr_push  arr_push            [.] GC_mark_from
    15.30%  arr_push  arr_push            [.] *Array(Int32)@Array(T)#push<Int32>:Array(Int32)
    12.96%  arr_push  arr_push            [.] *Array(Int32)@Array(T)#check_needs_resize:(Pointer(Int32) | Nil)
    12.06%  arr_push  arr_push            [.] __crystal_main
     7.65%  arr_push  arr_push            [.] *Pointer(Int32)@Pointer(T)#[]=<Int32, Int32>:Int32
     7.10%  arr_push  arr_push            [.] *Array(Int32)@Array(T)#<<<Int32>:Array(Int32)
     6.67%  arr_push  arr_push            [.] *Pointer(Int32)@Pointer(T)#+<Int32>:Pointer(Int32)
     4.70%  arr_push  [unknown]           [k] 0x00007ff8b3229f0a
     2.75%  arr_push  arr_push            [.] *Int32@Int#succ:Int32

GC_mark_from が一番時間かかっていることがわかる。

releaseビルドも同様。

( ՞ਊ ՞) :~/dev/crystal $ perf report | head -20
[kernel.kallsyms] with build id 500e786445f3c205298601de61824e582ab15bef not found, continuing without symbols
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 8
#
# Samples: 504  of event 'cycles:ppp'
# Event count (approx.): 279905518
#
# Overhead  Command   Shared Object      Symbol
# ........  ........  .................  ...................................................
#
    32.09%  arr_push  arr_push           [.] GC_mark_from
    23.87%  arr_push  arr_push           [.] *Array(Int32)@Array(T)#push<Int32>:Array(Int32)
     9.43%  arr_push  [unknown]          [k] 0x00007f8aa3ab5f0a
     7.99%  arr_push  arr_push           [.] main
     4.57%  arr_push  libc-2.24.so       [.] __memmove_avx_unaligned_erms
     3.10%  arr_push  [kernel.kallsyms]  [k] 0xffffffff9ea3c907
     1.44%  arr_push  [kernel.kallsyms]  [.] 0xffffffff9ee9fa57
     0.81%  arr_push  libc-2.24.so       [.] __memset_avx2_erms
     0.61%  arr_push  [kernel.kallsyms]  [k] 0xffffffff9e7e0114

check_needs_resize とかなくなってるけど、inline展開されたんだろうか。

( ՞ਊ ՞) :~/dev/crystal $ readelf -s ./arr_push| grep check_needs_resize
   419: 0000000000021400   197 FUNC    GLOBAL DEFAULT   15 *Array(Pointer(Void))@Array(T)#check_needs_resize:(Pointer(Pointer(Void)) | Nil)
   683: 000000000002c2f0   197 FUNC    GLOBAL DEFAULT   15 *Array(String)@Array(T)#check_needs_resize:(Pointer(String) | Nil)
   847: 0000000000032bf0   197 FUNC    GLOBAL DEFAULT   15 *Array(Proc(Int32, Nil))@Array(T)#check_needs_resize:(Pointer(Proc(Int32, Nil)) | Nil)
  1972: 0000000000034580   197 FUNC    GLOBAL DEFAULT   15 *Array(Int32)@Array(T)#check_needs_resize:(Pointer(Int32) | Nil)

いや、関数本体は残るのだっけ。objdump -drS でみてみよう。

0000000000021310 <*Array(Pointer(Void))@Array(T)#push<Pointer(Void)>:Array(Pointer(Void))>:
  #
  # a = ["a", "b"] of (Int32 | String)
  # a.push("c") # => ["a", "b", "c"]
  # a.push(1)   # => ["a", "b", "c", 1]
  # ```
  def push(value : T)
   21310:       41 57                   push   %r15
   21312:       41 56                   push   %r14
   21314:       41 54                   push   %r12
   21316:       53                      push   %rbx
   21317:       50                      push   %rax
   21318:       49 89 f6                mov    %rsi,%r14
   2131b:       48 89 fb                mov    %rdi,%rbx
    zip?(other) { |x, y| pairs << {x, y} }
    pairs
  end

  private def check_needs_resize
    double_capacity if @size == @capacity
   2131e:       8b 43 04                mov    0x4(%rbx),%eax
   21321:       3b 43 08                cmp    0x8(%rbx),%eax
   21324:       75 2d                   jne    21353 <*Array(Pointer(Void))@Array(T)#push<Pointer(Void)>:Array(Pointer(Void))+0x43>
  end

  private def double_capacity
    resize_to_capacity(@capacity == 0 ? 3 : (@capacity * 2))
   21326:       8d 0c 00                lea    (%rax,%rax,1),%ecx
   21329:       85 c0                   test   %eax,%eax
   2132b:       41 bf 03 00 00 00       mov    $0x3,%r15d
   21331:       44 0f 45 f9             cmovne %ecx,%r15d
  end

おお、なんかinline化されてる雰囲気だ。LLVMさまさままだな。

  • 追記

valgrind(callgrind) を失念していた。。

Rustのcargo profilerとかの裏側はこれ。

( ՞ਊ ՞) :~/dev/crystal $ valgrind --tool=callgrind ./arr_push 
==30942== Callgrind, a call-graph generating cache profiler
==30942== Copyright (C) 2002-2015, and GNU GPL'd, by Josef Weidendorfer et al.
==30942== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==30942== Command: ./arr_push
==30942== 
==30942== For interactive control, run 'callgrind_control -h'.
==30942== brk segment overflow in thread #1: can't grow to 0x4bea000
==30942== (see section Limitations in user manual)
==30942== 
==30942== Events    : Ir
==30942== Collected : 1026463326
==30942== 
==30942== I   refs:      1,026,463,326

出力された*.outみたいなファイルをkcachegrindに食わせるとGUIないい感じのインターフェースが出てくる。

$ kcachegrind callgrind.out.30942

もてなくて金がなくて技術力がない若者が奇行に走るのを止めるな

金曜に引き続きHTMLのATS対応を死んだ魚の目をしながらやっていました。いつのまにかフロントエンドエンジニアになっていたようです。

エラーを握りつぶしているコードがあったためつらいものがありました。

労で心が死んでいる上に前日から体調がよくなかったのではやめにフレックスで帰りました。

dstep

dstep を試してみる。題材はemacs-module。

先にdstepを用意

$ wget https://github.com/jacob-carlborg/dstep/releases/download/v0.2.1/dstep-0.2.1-linux-debian7-x86_64.tar.xz
$ tar Jxfv dstep-0.2.1-linux-debian7-x86_64.tar.xz

libclang.soがないと怒られた。

$ wget https://raw.githubusercontent.com/emacs-mirror/emacs/emacs-25.1/src/emacs-module.h
$ dstep emacs-module.h -o emacsmodule.d
dstep: error while loading shared libraries: libclang.so: cannot open shared object file: No such file or directory

思ったよりめんどうそうだ。

$ sudo apt install clang -y
...
$ LD_LIBRARY_PATH=/usr/lib/llvm-3.8/lib dstep emacs-module.h -o emacsmodule.d
File(8B2100, "")emacs-module.h:25:10: fatal error: 'stdbool.h' file not found