t

メモ

test-kitchen + kitchen-docker on Mac OS X (2)

前回とそう変わらないが、Docker 側の変更に追従する必要がある気がした。

といっても Docker の設定は公式ドキュメントの通りなので何も難しくない。test-kitchen や kitchen-docker のインストールも変わったところはない。

$ brew install boot2docker
$ boot2docker init
$ boot2docker start
$ $(boot2docker shellinit)
$ gem install test-kitchen
$ gem install kitchen-docker

それで DOCKER_HOST をどうするかだけど、実は .kitchen.yml の中身は erb にかけられるらしいので、これを利用して DOCKER_HOST を読み込ませるのが良さそう(2015-02-03 追記: どうやら 1.6.0 からデフォルトで DOCKER_HOST を見るようになったらしいので、下記の socket の設定は不要になったはず)。

---
driver_plugin: docker

driver_config:
  use_sudo: false
  socket: <%= ENV.fetch('DOCKER_HOST', 'unix:///var/run/docker.sock') %>

provisioner:
  name: chef_solo

platforms:
  - name: ubuntu-12.04

suites:
  - name: foobar
    run_list:
      - "recipe[foo]"
      - "recipe[bar]"

Interactive Operations with Homebrew

brew cleanup とか brew switch とか brew upgrade とかをインタラクティブに実行できると楽な気がしたので、みっともないワンライナーを書いてみた。

brew.cleanup() {
    brew info --json=v1 --installed | jq '.[] | select(.installed | has(1)) | select(if .revision == 0 then .versions.stable else "\(.versions.stable)_\(.revision)" end == if .keg_only == true then .installed[(.installed | length) - 1].version else .linked_keg end) | if .linked_keg == null then .name else "\(.name) (\(.linked_keg))" end' | tr -d '"' | peco | awk '{ print $1 }' | xargs -n 1 brew cleanup
}

brew.switch() {
    brew info --json=v1 --installed | jq '.[] | select(.installed | has(1)) | "\(.name) \(.installed | .[].version)"' | tr -d '"' | peco  --query "$*" | xargs -n 2 brew switch
}

brew.upgrade() {
    brew outdated -v | tail -n +2 | peco | awk '{ print $1 }' | xargs brew upgrade
}

brew.update.upgrade() {
    brew update && brew.upgrade
}

mark-word for Atom

Emacsmark-sexp のようなのものが Atom に欲しい、と思ったのですが AtomCoffeeScript もよく知らないし面倒なので mark-word のようなもので我慢することにしました。

具体的には次のようなスクリプト(2014-08-04: Atom 0.120.0 で動くように修正)を ~/.atom/init.coffee に書けば使えます。なお atomic-emacs が必要です。

AtomicEmacs = require './packages/atomic-emacs/lib/atomic-emacs'

class MyAtomicEmacs
  constructor: (@editor) ->
    nonWordCharacters = atom.config.get('editor.nonWordCharacters')
    cs = nonWordCharacters.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
    @wordPattern = new RegExp('[\\s' + cs + ']*[^\\s ' + cs + ']*')

  markWord: (event) ->
    eof = @editor.getEofBufferPosition()
    for selection in @editor.getSelections()
      cursor = selection.cursor
      mark = AtomicEmacs.Mark.for(cursor)
      if selection.isEmpty()
        mark.set().activate()
      cp = cursor.getBufferPosition()
      mp = mark.getBufferPosition()
      selection.modifySelection =>
        if cp.isLessThanOrEqual(mp)
          @editor.scanInBufferRange @wordPattern, [mp, eof], (hit) ->
            cursor.selection.setBufferRange([cp, hit.range.end], isReversed: true)
            mark.marker.setHeadBufferPosition(hit.range.end)
        else
          @editor.backwardsScanInBufferRange @wordPattern, [mp, [0, 0]], (hit) ->
            cursor.selection.setBufferRange([hit.range.start, cp])
            mark.marker.setHeadBufferPosition(hit.range.start)

atom.workspaceView.eachEditorView (editorView) ->
  myAtomicEmacs = new MyAtomicEmacs(editorView.getEditor())
  editorView.command "my-emacs:mark-word", (event) => myAtomicEmacs.markWord(event)

私は ~/.atom/keymap.cson に次のような設定を書いて使っています。

'.editor':
  'ctrl-[ ctrl-space': 'my-emacs:mark-word'

そしてこの設定は KeyRemap4MacBook の Space to Shift_L と相性が悪いので、次のような ~/Library/Application Support/KeyRemap4MacBook/private.xml を書いてごまかしました。

<?xml version="1.0"?>
<root>
  <item>
    <name>Space to Shift_L</name>
    <appendix>(+ When you type Ctrl_L-Space, send Ctrl_L-Space)</appendix>
    <appendix>Ctrl_L+Space to Ctrl_L+Space</appendix>
    <identifier>remap.space2shiftL_ctrlspace_ctrlspace</identifier>
    <autogen>__KeyToKey__ KeyCode::SPACE, ModifierFlag::CONTROL_L, KeyCode::SPACE, ModifierFlag::CONTROL_L</autogen>
    <autogen>__KeyOverlaidModifier__ KeyCode::SPACE, KeyCode::SHIFT_L, KeyCode::SPACE</autogen>
  </item>
</root>

doc2dash_python-2.7ja

TL;TR - Python 2.7 の日本語ドキュメントを Dash に追加すると便利です

$ curl -fsSL "https://gist.github.com/hirofumi/2eee3797ade87a73e1d1/raw/doc2dash_python-2.7ja" | bash

せっかくPythonドキュメント日本語翻訳プロジェクトが存在して、しかもその成果を Dash の docset として追加する方法を公開されている方もいるので、スクリプト化してみました。といっても事前に pipvirtualenv をインストールしておく必要があります。

なお上記のスクリプトは以下のサイトの情報を元にして書きました。

How to Examine Memory Usage of JVM

JVM の、主にメモリ消費の様子を知りたい。方法をいくつか調べたのでメモしておく。

今のところ次のような使い分けになりそう。

  • その場で様子を見るなら VisualVM
  • ログを取っておいて後から見るなら GCViewer
  • 何がどのくらいメモリを消費しているか調べるなら Eclipse Memory Analyzer

jmap

JDK 付属の jmap を jmap -heap <pid> のように実行すると JVM の各メモリ領域の使用量が分かる。

jcmd

JDK 付属の jcmd を jcmd <pid> GC.class_histogram のように実行すると、どのクラスのインスタンスがどのくらいメモリを使っているのかが分かる。ただし #bytes に各インスタンスが参照している先は含まれていない(あるクラス Klass が巨大な java.lang.String を参照していたとしても、それは Klass#bytes には反映されない)ようなので、解釈には注意が必要と思われる。

jstat

JDK 付属の jstat を jstat -gc <pid> のように実行してガベージコレクトされたヒープの統計データ を見たり jstat -gccause <pid> のように実行して直前や現在のガベージコレクションの原因 を見たりできる。

jvmtop

jvmtop を使うと top を使うような感じで JVM の様子を見ることができる。たとえば GC に費された時間の割合やヒープの使用量などが分かる。各数値の見方はドキュメントに書いてある。

VisualVM

VisualVM を使うと GUIJVM の様子を見ることができる。グラフで表示してくれるので、時系列を見たいときは jvmtop より便利そう。

GCViewer

GCViewer を使うと GC のログをグラフで表示することができる。

GC のログは java のオプションに -Xloggc:ログのパス -XX:+PrintGCDetails -XX:+PrintGCDateStamps あたりを指定して取れば良い。

Eclipse Memory Analyzer

Eclipse Memory Analyzer を使うと GUI でヒープダンプを解析できる。とくに dominator_tree を見ると何にメモリを取られているかが分かりやすい。

ヒープダンプは JDK 付属の jcmd で jcmd <pid> GC.heap_dump /path/to/dump.hprof のようにして取れる。あるいは java の起動オプションで -XX:+HeapDumpBeforeFullGC-XX:+HeapDumpAfterFullGC をつけるとフル GC の直前や直後にヒープダンプを取れる。ファイルはカレントディレクトリに java_pidNNNNN.hprof という名前(NNNNN は pid)で作られるらしい。複数作られるときは java_pidNNNNN.hprof, java_pidNNNNN.hprof.1, java_pidNNNNN.hprof.2 のように連番になる。

ところで Eclipse Memory Analyzer 自体の起動オプションには -Xmx1024m が指定されており(OS X の場合 MemoryAnalyzer.app/Contents/MacOS/MemoryAnalyzer.ini にある)少ないので、巨大なヒープダンプを解析したい場合は適当に増やした方が良い。

Modest smartparens

最近 smartparens を使い始めたのだけど、開き括弧を書いたときに問答無用で閉じ括弧を挿入されるのはあまり嬉しくなかった。思案した結果、主に行末にいるときだけ挿入を許すことにしてみた。

(defun sp-autoinsert-inhibitedp (current-opening-pair inside-string-or-comment)
  (and (not (sp--get-active-overlay))
       (or inside-string-or-comment
           (/= (point) (save-excursion (end-of-line) (point))))))

(custom-set-variables
  '(sp-autoinsert-inhibit-functions '(sp-autoinsert-inhibitedp)))

とりあえず思ったように動いているものの sp-autoinsert-inhibit-functions は deprecated であるらしい。どうしてくれようかしらん。