時計を壊せ

駆け出してからそこそこ経ったWebプログラマーの雑記

errnoから何のエラーか簡単に調べるためのワンライナーの解説

qiita.com

こんなワンライナーがあります:

% perl -E 'say$!=24'
Too many open files

これの正体に迫っていきたいと思います。

どのように解釈されるのか

まずはこれがいったいどのようにParseされるのかを知るために、 -MO=Deparse を付けて実行してみましょう。

% perl -MO=Deparse -E 'say$!=24'
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
say $! = 24;
-e syntax OK

say $! = 24 キモはこれです。 $! という変数に 24 を代入して、その式の結果を say が受け取っています。

Perlの代入式は左辺値の値が取られるため、これは以下のコードと等価です。( 参考: perlop - Perl の演算子と優先順位 - perldoc.jp

$! = 24;
say $!;

24 を代入したのに文字列が出てきた!?バグか!?と驚くかもしれません。 しかし、これは実はちゃんとPerlのドキュメントに明記されている挙動です。

特殊変数

Perlにおいては $! のようにシジル($ など)のあとの変数名が記号で始まるものは特殊変数と呼ばれ、処理系によって特殊な扱われ方をする変数になっています。

特定の特殊変数がどのようなものかは perldoc -v '$!' などとしたりすることで調べられます。 $! とはなんなのかを調べてみましょう。perldoc.jp でも簡単に調べられます。

Perlの組み込み変数 $! の翻訳 - perldoc.jp

$! はerrnoを扱うための特殊変数だということがわかります。

こんな記述があります:

参照されると、$! は C の errno 正数変数の現在の値を取得します。 $! に数値が代入されると、その値は errno に補完されます。 文字列として参照されると、$! は errno に対応するシステムエラー 文字列を返します。

つまり、そういう挙動をする特殊変数なので、そうなる。という感じです。

インターフェースに対する考察

でも、「文字列として参照されると」とは、どういうことなのか? なんで、こんな不自然に見えるインターフェースになっているのか?

これにはPerl特有のコンテキストという考え方が関わってきます。

コンテキスト

Perlは文脈的多態言語 (Contextually Polymorphic Language)として作られています。 これは要するに、データ表現を単一のスカラにまとめ、そしてそのスカラを評価した文脈によってデータ表現を変えることによって、同一の概念を1つの変数で簡便に扱うための概念です。

参考資料:

http://perldoc.jp/docs/perl/5.26.1/perldata.pod#Scalar32values https://www.slideshare.net/karupanerura/ss-98704540 https://www.slideshare.net/KondoYoshiyuki/yapc2012-20120929

このコンテキストを実現するための仕組みとして、Perlのスカラ変数は同一の値に対する複数の型のデータ表現を持つSV構造体として表現されます。 具体的にはPV/IV/NVという3つの値をSVに同時に持つことができます。

参考資料:

http://xsubtut.github.io/ https://metacpan.org/pod/B#OVERVIEW-OF-CLASSES

通常はこれらのIV/PVなどには同一のデータを単に型変換したデータが保持されます。

use Devel::Peek;

# IVだけを持つSVを作る
my $age = 17;
Dump $age;

# 文字列コンテキストで評価したことによってPV値が求められる
print "私は永遠の $age 歳です\n"; 

# $ageはIVとPVを持つSVに変わる
Dump $age;

実行してみるとこのとおりです:

SV = IV(0x7ffe9080dd88) at 0x7ffe9080dd98
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 17
私は永遠の 17 歳です
SV = PVIV(0x7ffe9080b820) at 0x7ffe9080dd98
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 17
  PV = 0x7ffe8f402de0 "17"\0
  CUR = 2
  LEN = 10

PV値に "17" という値が増えて、FLAGSPOK が増えています。(PVはPointer Valueなのでその名の通り、実際にはその文字列へのポインタです)

内部的にはこのようにして同一の値に対する異なる表現のデータを持ち、コンテキストでその評価を変えるのがPerlのContextually Polymorphic Languageたる世界観なのです。

ソフトウェア工学的に正しいかどうかはさておき、データを直感的に扱うためのアプローチとしてはユニークで面白い概念なのではないかと個人的には思います。

dualvar

さて、これを見た賢い人は「つまり単一のスカラに違うデータを入れることも可能なのでは?」と考えると思います。 まさにそのとおりで、標準モジュールのScalar::Utilにdualvarという機能があります。

https://metacpan.org/pod/Scalar::Util#dualvar

これを使うとこういったことができます:

use Devel::Peek;
use Scalar::Util qw/dualvar/;

# PVとIVを持つSVをdualvar関数で作る
my $age = dualvar 17, 'seventeen';
Dump $age;

# 文字列コンテキストで評価したことによってPV値が参照される
print "I'm $age years old.\n";

# 数値コンテキストで評価したことによってIV値が参照される
print "Next age: ", $age + 1, "\n";

結果としてはこうです:

SV = PVNV(0x7fa429802150) at 0x7fa42981da58
  REFCNT = 1
  FLAGS = (IOK,POK,IsCOW,pIOK,pPOK)
  IV = 17
  NV = 0
  PV = 0x7fa42b200570 "seventeen"\0
  CUR = 9
  LEN = 11
  COW_REFCNT = 1
I'm seventeen years old.
Next age: 18

IV/PVに別々の値が入っており、それがそれぞれのコンテキストに応じて使われている事がわかります。

即ち、Perlではerrnoとそのエラーメッセージは表裏一体の同一概念として扱えるべきだと考えて $! をdualvarのようなスタイルで実装していると考えられます。

ちなみに、一応書いておくと、dualvarを通常のソフトウェア開発で使うべき場面は基本的には存在しないと思います。

$!の正体に迫る

ここまでの知識を前提知識として知っていると $! はdualvarのようにして実装されているのでは?と想像できると思います。

実際に実行してみましょう:

use Devel::Peek;

$! = 24;
say $!;

Dump $!;

やはりIVにはerrnoが、PVにはそのエラーメッセージが格納されています。

Too many open files
SV = PVMG(0x7fb7ce827140) at 0x7fb7ce806ff8
  REFCNT = 1
  FLAGS = (GMG,SMG,NOK,POK,pNOK,pPOK)
  IV = 24
  NV = 24
  PV = 0x7fb7cdc07b00 "Too many open files"\0
  CUR = 19
  LEN = 21
  MAGIC = 0x7fb7cdc08ec0
    MG_VIRTUAL = &PL_vtbl_sv
    MG_TYPE = PERL_MAGIC_sv(\0)
    MG_OBJ = 0x7fb7ce807058
    MG_LEN = 1
    MG_PTR = 0x7fb7cdc028d0 "!"

では $!sayの文字列コンテキストで評価する前に参照してみるとどうでしょうか?

use Devel::Peek;

$! = 24;
Dump $!;

なんとPVは0です:

SV = PVMG(0x7fc936815b40) at 0x7fc93581d9f8
  REFCNT = 1
  FLAGS = (GMG,SMG,IOK,pIOK)
  IV = 24
  NV = 0
  PV = 0
  MAGIC = 0x7fc93570a450
    MG_VIRTUAL = &PL_vtbl_sv
    MG_TYPE = PERL_MAGIC_sv(\0)
    MG_OBJ = 0x7fc93581da58
    MG_LEN = 1
    MG_PTR = 0x7fc93570a480 "!"

$! を評価したときに何かが起きて、IVに応じたPVがセットされた。ということがわかります。 これを実行しているのがMAGICと呼ばれる仕組みです。

MAGIC

MAGICは変数の操作に対してフックするための仕組みです。 以下のようなことができます:

   関数ポインタ        その振る舞い
   ----------------    ------------
   svt_get             SV の値が取得された前に何かを行う。
   svt_set             SV に値を代入した後で何かを行う。
   svt_len             SV の長さを報告する。
   svt_clear           SV が表わしているものををクリアする。
   svt_free            SV に結び付けられてい領域を解放する。
   svt_copy            tie された変数のマジックを tie された要素にコピーする
   svt_dup             スレッドのクローン化中にマジック構造体を複製する
   svt_local           'local' 中にマジックをローカル変数にコピーする

出展: https://perldoc.jp/docs/perl/5.20.1/perlguts.pod#Magic32Variables

$!のMAGIC

Devel::Peekによると MG_TYPE = PERL_MAGIC_sv とあるので先のドキュメントと照らし合わせるとやはり特殊スカラ変数向けのMAGICが内部的に定義されていることが分かります。

 mg_type
 (old-style char and macro)   MGVTBL         Type of magic
 --------------------------   ------         -------------
 \0 PERL_MAGIC_sv             vtbl_sv        特殊スカラ変数

該当箇所のソースを追うと、 mg_vtable.hでこれが定義されており Perl_magic_setPerl_magic_get によって実際の処理が行われていることが分かります。

https://github.com/Perl/perl5/blob/v5.30.0/mg_vtable.h#L191

$! = 24 のように代入されるタイミングで Perl_magic_set が実行され、 MG_PTR = 0x7fc93570a480 "!" なので以下の分岐に入ってきます。

https://github.com/Perl/perl5/blob/v5.30.0/mg.c#L3074-L3089

代入元のスカラを数値コンテキストで評価したときと同じ値を、 SETERRNOマクロで一般的な errno.h の提供するグローバル変数のerrnoにもセットしています。VMSの場合は挙動が少し違うようです。

https://github.com/Perl/perl5/blob/v5.30.0/perl.h#L1330

そして $! が評価されるタイミングで Perl_magic_get が実行され、errnoをSVのIVスロットにセットし直して最終的にはstrerror関数によってerrnoのエラーメッセージを取得してPVスロットにセットしています。

https://github.com/Perl/perl5/blob/v5.30.0/mg.c#L1003-L1032 https://github.com/Perl/perl5/blob/v5.30.0/embed.h#L843 https://github.com/Perl/perl5/blob/v5.30.0/mg.c#L883-L897

こうして $! の挙動がどのように実現されていることが分かりました。

まとめ

$! はPerlの特殊変数でerrnoを扱います。その挙動はMAGICによって実装されており、dualvarのように振る舞います。 $! を使うときはコンテキストによって表現を変えるのでコンテキストを適切にコントロールしましょう。

バックアップ用NAS検討

ことのあらまし

すると有益な情報を友人知人に教えてもらえた。(超感謝) おすすめされたメーカーで分類すると、Synology, ASUSTOR, Drobo, QNAPの4つ。

補足すると、Linux NASがと明言したのはLinuxだったら公式のサポートがなくてもコード書けばどうにでもできるやろ…という希望的観測が持てたからで、要件としてはツイートしたとおり「非同期で差分をDropboxにあげてくれる(Dropboxじゃなくても良い)」「省電力でスタンドアロンで動いてくれる」ということでDropbox同期などの機能があるNASなら問題なかった。というより正直なところ連携をあまり期待していなかったのでこんなにあるのかと驚いた。 (ただ、Linuxだったら色々 いたずら 楽しいことが出来そうという気持ちもあり、Linux basedのほうが気持ちがわくわくしそう。)

また、NAS自作も選択肢にあったが、楽をしたいので出来合いのやつがあればいいなという感じ。

そして、おすすめしてもらったやつはいずれも要件を満たしていた。つまり、迷う。レッツ比較。

Synology

クラウドストレージ連携

Hyper BackupがDropboxとかへのバックアップ機能らしい。

www.synology.com

だいたいの機種が対応しているようだ。

www.synology.com

Dropboxに対しては同期も可能なようだ。

省電力性

省電力性はValueシリーズがSpec上は優秀そうに見える。

www.synology.com

16.79 W (アクセス)
5.16 W (HDD ハイバネーション)

Plusシリーズもよさそう。

www.synology.com

17.23 W (アクセス)
5.4 W (HDD ハイバネーション)

価格

3万円弱くらい。

このモデルは CPU: Realtek RTD1296 クアッドコア 1.4 GHz メモリ: 1 GB DDR4 のようだ。

こっちは3万円台後半で CPU: Intel Celeron J3355 デュアルコア 2.0 burst up to 2.5 GHz メモリ: 2 GB DDR3L のようだ。

ASUSTOR

クラウドストレージ連携

Dropbox同期機能があるようだ。

www.asustor.com

非同期なバックアップはなさそう。(同期でも良いんだけどバックアップとしてはone wayなほうが安心感がある…)

省電力性

省電力性はv2シリーズが優秀そうに見える。

www.asustor.com

14.1 W(操作)
6.9 W (ディスクのハイバネーション)

www.asustor.com

消費電力: 14.6W (操作)
8.1W (ディスクのハイバネーション)
0.89W (スリープモード)

価格

ASUATOR NASケース AS10 v2シリーズ 2ベイモデル AS1002T v2

ASUATOR NASケース AS10 v2シリーズ 2ベイモデル AS1002T v2

このモデルは2万円弱で CPU: Marvell ARMADA-385 1.6GHz (Dual-Core) Processor メモリ: 512MB DDR3 のようだ。

ASUSTOR NASケース 31シリーズ 2ベイモデル AS3102T v2

ASUSTOR NASケース 31シリーズ 2ベイモデル AS3102T v2

このモデルは2万円台後半で CPU: Intel Celeron 1.6GHz Dual-Core (burst up to 2.48GHz) Processor メモリ: 2GB DDR3L のようだ。

安い。

Drobo

HDD入れ替えていけば容量増やせる ってどういうことだろうと思ったらBayond RAIDという機能があるようだ。

www.drobo.com

https://ascii.jp/elem/000/001/422/1422949/ascii.jp

クラウドストレージ連携

期待したようなものはなさそう。

matt.ucc.asn.au

SSHできるようだしPerlも動かせそうなのでなんとかしようと思ったら出来そう。

省電力性

Datasheetに載ってたり載ってなかったりする…謎。 製品のウリ的に2 bayみたいな小さいモデルはないようだ。

www.drobo.com

このモデルにはあった。

https://drobo-wpengine.netdna-ssl.com/downloads/products/04-05-01-b810n-DS.pdf

8 bayで 13W~82W っぽい。

価格

Drobo 5N2 5 Bay NAS

Drobo 5N2 5 Bay NAS

5 bayで5万円台といったところか。

QNAP

www.songmu.jp

UPSと連動してくれるのはたしかに良さそう。

クラウドストレージ連携

Cloud Drive Syncという機能がそれに当たるっぽい。

www.qnap.com

省電力性

省電力性はTS-251bが同社の2 bay製品のなかではSpec上は優秀そうに見える。

www.qnap.com

電力消費量:HDDスリープモード 8.08 W
電力消費量:動作モード、通常時 15.25 W

価格

3万円台後半。

このモデルは CPU: Intel® Celeron® J3355デュアルコア2.0 GHzプロセッサ(最大バースト2.5 GHz) メモリ: 2 GB SO-DIMM DDR3L(1 x 2 GB) のようだ。

検討

自分は本ちゃんのバックアップはクラウドに置いて運用したい。うっかりDriveの寿命を迎えたりするリスクがないし、可用性の観点で安心だし、アクセスもしやすいから。 そのための、前段に置くバックアップとアップロードを代わりにやってくれるマイクロホームサーバーとしてNASがほしい。

そういう用途なのでNAS自体の可用性や拡張性は自分にとってはあまり重要ではない。

一方でLinuxで動いていると嬉しいことがいくつかあり、たとえばmackerel-agentでS.M.A.R.Tを監視したりできるので、故障前にアラートで通知してもらったり障害を検知したりできるはずだ。 その点はどれもLinuxベースのようなので良さそう。

性能面も踏まえると、総合的には個人的にQNAP TS-251bかSynology DS218+、AUSUSTOR AS3102T v2が良さそうかなぁ。

追記

Github/Dropboxだけだとダメなの?ってなるけど、コードとかはもちろんGithubにあげてるけど楽曲制作やってるとレコーディングした各楽器の各テイクを96kbps/24bitとかで持っているのでそれなりの容量になってしまう。ときどき録画データとかもあるので、それを保管するのも手間。 Dropboxは普段使いは良いけどselected syncの設定を逐一いじるのが手間だし、アップロード完了まで待たないといけないので、普段使いのノートPCには不向き。Smart Syncも楽曲制作のために確実に容量を空けておきたいとなるとあまり期待できない気がする。 とはいえ、なにかしらのクラウドストレージサービスにアップロードしておきたい。というわけで、NASにコピーさえすればあとはよしなにやってくれるという世界観になるとうれしいとなった。

Dropbox以外はダメなのかというとそんなことはなくて、Dropboxは今自分が年間契約している唯一のクラウドストレージサービスなのでまずはそこにあげようとしているだけで、GCSとかGlacierやGoogle Driveも検討外というわけではなくそのうち別途検討しようと思っている。

Japan Perl Associaton代表理事に就任します

SEE ALSO:

blog.perlassociation.org

なぜ平成も終わるこのご時世に?と思う方もいらっしゃると思います。 思いの丈を書いてみます。

昨今のWeb開発のトレンドとしては、動的型付け言語から静的型付け言語へシフトが進んでいます。 また、PaaS/SaaS/FaaSの普及により言語選択よりも技術選択とそのアーキテクチャがより重要になってきており、 *1いちプログラミング言語の重要性というものは、(特に動的型付け言語においては)昔ほど重要ではなくなっているのが実情かと思います。

その中でもPerlは、人気度でいえば比較的低い言語といえるでしょう。 LLと呼ばれる言語の中で最低の人気と言っても間違いではないかもしれません。 ひどいときには、1987年に作られたPerlと1959年に作られたCOBOLが並べて語られることすらあります。*2

それでも、ぼくはPerlが好きです。

Perlを支えてきたPerlコミュニティが好きです。

Perlコミュニティが作り上げてきたCPAN Moduleが好きです。

Perlはたぶん知らない人が思ってるよりは、実際はもっと使いやすく、また面白い言語です。 一方で他のプログラミング言語とは考え方が、一見似ているようでまるで違う部分もあります。 たとえば、文脈的多態言語 (contextually polymorphic language) としての特徴は他のプログラミング言語によく慣れた人には奇妙な設計に見えるでしょう。 しかし、この特徴があるお蔭で、一定以上Perlに慣れれば直感的にPerlのコードを書き下すことができます。(詳しくはここでは割愛します)

もちろん、ただ書き下しただけの読みにくいコードがどういう問題を引き起こすかという話はありますが、それは実際には書き下しただけのコードをリファクタリングせずに運用してしまう開発体制の問題であり、Perlに限った話ではなくどの言語でも起こり得るものです。 一方で、そういった問題に苦しめられた結果、Perlを嫌いになってしまったという話も悲しいことによく見ます。

ただ、そういった噂が尾びれをつけて、Perlでコードを書くと汚くなる、Perlでは綺麗なコードは書けない、などとあらぬ誤解が多く広まってしまっている悲しい実情もあります。 綺麗なコードが書けるかどうかは、単にその言語の熟練度とその書き方の問題です。「罠」と言われるものの大半は、言語仕様やその考え方に対しての無知から来ている誤解です。 Perlは正しく理解すれば、とても強力なスクリプト言語になります。

そして、多くのCPANモジュールはPerlでより大規模なサービスを作れるようにしてくれました。 結果として、いまも多くのWebサービスがPerlで支えられています。

しかし、現状は残念ながらその実力が過小評価されてしまっている場面がやはり多いと思います。 ぼくはそんな現状が悲しいのです。

ところで、実用上はどうでしょうか。

実際のところ、まだまだPerlのまま運用されている、そしてまだしばらくはPerlのまま運用しようとしている、そしてそれが収益の柱(の一部)になっているというサービスは無数にあります。 また、IaaS/オンプレミスでの運用もまだまだ少なくはなく、ログをしゅっと集計するスクリプトをさっと書きたいような場面もたくさんあります。

冒頭で述べたようなトレンドの変化に加え、各クラウドベンダーは残念ながらPerlをサポート外にしていることも多く、新規開発でPerlという事例はもうほとんどなくなっていくでしょう。 一方でPerlの利用場面が全くなくなるかというとそんなことはなく、その強力な正規表現エンジンはML学習用データのクリーニングに使えば複雑なケースでもシンプルに問題を解決できるでしょうし、 OSにプリインストールされて互換性の高いスクリプト言語として、ワンライナーや書捨てスクリプトの類ではまだまだ力を発揮することでしょう。もちろんCPANモジュールを使えばもっと高度なこともできます。 当然、延命させてきたPerlのサービスに突然ビジネスチャンスがやってきてすばやく改修を加えたい。となる場面もあるかもしれません。

かくして、まだまだPerlのエンジニアは必要とされており、その一方でPerlのエンジニアの採用に困っているという声もよく聞きます。 決してメジャーラインではありませんが「死んだ」と形容されることが似合うほど落ちてもいないのではないでしょうか。

そういうわけで、こういう僕のエゴで僕が id:nekokak に代わり代表理事を引き継ぐことにしました。

まだまだ自分は若輩者で、牧さんやねこかくさんほどの働きができるとは思えませんが、そういった気持ちを胸に少しでも現状をよくできたら、Perlコミュニティがもっと楽しい場になると良いなと思っています。 不束者ではございますが、みなさん改めてよろしくおねがいします。

*1:あくまでもWeb開発というコンテキストにおいては

*2:Perlはもちろん、COBOLも現代で未だに活躍しているプログラミング言語のひとつです

YAPC::Tokyo 2019で話したことの落穂拾い、あるいはISUCON8予選問題出題の感想

話してきた。スライドはこちら。

speakerdeck.com

20分で話せるボリュームにまとめるにはちょっとスコープが広すぎて抽象的かつ割と普通な結論になってしまったなと題材選びに反省がある。 もう少し具体例について堀り下げられる時間がほしかったが、コンテキストなくそこだけ話してもやはり本質的には意味の薄いものになってしまっただろう。 問題を考えるときに、チームとして実際に考えてたことの本質的な部分についてなんとか言語化できたかなーという気がする。 逆に言えばそういう言葉を使って議論してたわけじゃなくて、自然とそういう目的や価値観を議論の中で共有できたからこそ、問題を良い方向にどんどんブラッシュアップできた。といえると思う。(ぼくが勝手にそう思っていただけでなければ…)

基本的にはまとめに書いたとおり、目的ドリブンで価値観を決めて、その価値観をもとに良し悪しを図り、やっていく。を実践した結果としてこういうのが出来たという話をした。 言ってることは当たり前のことになっちゃったけど、なんだかんだ一番重要かつ本質的に一番大事だったのはここで、これをそのまま伝えることにした。

プロポーザルに書いておいて語れなかったことにちょっと触れる。

どのようにしてブラックボックスとなっているアプリケーションが仕様を満たしているかをテストするとよいのか

これは id:sonots さんが主にやっていたことなので本当はインタビューしないといけないんだけど、 基本的には操作による状態の変化をエミュレートして、サービスが返すデータがそれと矛盾していないことをテストしていた。 簡単な具体例をだすと、S席が100席あるときに並列で5人同時に買ったら、残り95席になっているはず、それぞれ別の席が得られているはず、ということを確かめる。

実際はもっと複雑で、タイムアウトがありえる。すると何が難しいかというと、クライアント側からは操作が成功しているか失敗しているかが分からない。 つまり、並列で5人同時に買った操作のうち2件がタイムアウトした場合、残りの座席は95席とは限らないし97席とも限らない。 僕たちはどうしたかというと、許容誤差の範囲を動的に計算して、95席〜97席の範囲に収まっていれば正とするようなチェックをしていた。

また、座席のランダムチェックに関しては、全体でn件以上予約した結果として全体の座席の割り振られた順番が等差数列的になっていないことを確認していた。 こうすることで、単純な ORDER BY RAND()ORDER BY id などに書き換えればFAILさせることができるし、一方でランダムにn個生成した数が等差数列になる確率は許容範囲になるだろうという目論見があった。 n件予約できない場合はもちろんこのチェックは走らないが、このようなことを試すモチベーションは仕様無視して予約処理の高速化を図るチート行為なので、件数が増えたときだけチェックすればよく何ら問題がなかった。

極限までチューニングする上でどのようにプロファイリングするとよいのか

普通にプロファイリングする。のだけど、以下のようなツールを組み合わせてボトルネックを解析してチューニングするのをひたすら繰り返していた。

ボトルネックとその原因を明確につかめるまでは多角的に情報を集めて矛盾の無い判断をするように気をつけていたと思う。 あと、PerlのNYTProfはかなり詳細に出せるので、読み方さえ理解すればすごく強力な武器になった。

あとは理屈上このほうが速いんじゃね?というのを適当にいろいろ試したりするのは予想外の結果になったりして面白く純粋に楽しかった。

そのほか

当たり前だけど、完璧な問題が作れたわけじゃない。課題はたくさん残ったまま予選当日を迎えてしまったし、いくつか初期実装の不備も出してしまった。 それらの点に関しては講評でも触れたとおりだけど反省しかないし申し訳ないと思っている。

その一方で、出題した問題そのものの本質的な問いかけに関しては、自分で言うのもなんだが高い評価をもらえたんじゃないかなと思っている。 おこがましいけど過去イチで面白くやりがいのある問題を作り上げてやろうと(勝手に)思っていて、そう思っていた反面ぜんぜん自信がなかったからずっと不安だったけど、良いフィードバックがたくさんもらえたのは本当に嬉しかったし、ひとに会うたびに無限に褒められが発生したので自信につながった。

あとは、ISUCONの作問は業務時間を使ってやっていたんだけど、仕事としてやる以上は成果を残さなきゃいけないというプレッシャーもあった。 ISUCONに関わる上での成果とはなにかって考えると、やはり良い問題を作るというのが本質的なコミュニティへの貢献だし、それこそが会社や自分自身のプレゼンスの向上への最大の近道だと思ってやっていた。逆にいえば、中途半端な成果にはしないという覚悟をしたからこそ「やります」という声を挙げられた。覚悟だいじ。

今年もいろいろ覚悟を決めて良い変化をちょっとずつ起こしていきたい。

追記

落ち穂拾い != 落ち葉拾い。覚えた。

落穂拾い - Wikipedia

ところでこれ送り仮名つけるのとつけないのどっちが正しいの?

YAPC::Tokyo 2019で「ISUCON8予選問題の裏側」について話します

こんな感じのトークをします:

ISUCONとはIikanjini Speed Up CONtestの略で、アプリケーションからOSレイヤまでなんでもありのWebアプリケーションの総合的な高速化スキルを競うコンテストです。2018年で第8回目の開催となり、参加者数は1000人を超えます。本年度の出題はDeNAとカヤックでした。僕はDeNAのエンジニアの一人としてISUCON8予選の問題作成に携わりました。

ISUCONの問題の提供のためには、参照実装(具体的な問題)の作成、ベンチマーカーの作成、競技を成立させるための最低限の制約であるそしてそれが十分に高速化できることを示すための模範解答の作成が必要です。ISUCON8の予選問題はPerlで最初に参照実装が作成されました。そして、模範解答も実はPerlで作成されています。そして、その参照実装が各言語へ移植されて競技で各言語ごとに様々なチューニングが行われました。

その過程で様々な学びを得ました。たとえば、ISUCONのような競技で気を遣うべきポイントはなにか、どのようにして問題を考えていくと良いのか、どのようにしてブラックボックスとなっているアプリケーションが仕様を満たしているかをテストするとよいのか。極限までチューニングする上でどのようにプロファイリングするとよいのか。他言語移植においてどのようなポイントで問題が起きるのか。などといったものです。

このセッションではISUCON8予選問題の作問の過程から、どのような学びを得たかについて語ります。

あんまりPerlっぽいことは出てこないのでPerl詳しくなくても聞きやすいと思います。 ぜひ聞きに来てください!

個人的注目トークです:

blog.yapcjapan.org

公式見どころ情報です:

blog.yapcjapan.org

明日までにチケットを買えば自由なサイズのTシャツが購入できます。 気になってきた方はこれを見てどうぞ:

blog.yapcjapan.org

CSS初め

このブログのデザインに対して冷静になった結果、どうも背景の主張が強すぎてタイトルとかが読みにくいという思いに至った。 はてなブログはたしかカスタムCSSが書けたはずなので、CSSでなんとかすることにした。

書いたのはこんな感じ:

body:before {
  content: '';
  position: fixed;
  top: -5px;
  left: -5px;
  width: 120vw;
  height: 120vh;
  z-index: -1;
  background: inherit;
  filter: blur(5px) brightness(40%);
}

div#wrapper {
  margin-right: -221px;
}

div#wrapper>* {
  margin-right: 220px;
}

aside#box2 {
  width: 180px;
}

要素名は詳細度を調整して優先されるようにこうした。!important 使え案件な気もする。

背景を暗めにしてぼかす

はてなブログ全部なのかこのデザインのみなのか分からないけれど、背景画像はbodyに設定される。 暗めにするだけならその直下で全部くるんでるdivとかで background-color: rgba(0, 0, 0, .6) とやってやればよいのだが position: absolute な要素があるのでうまく行かなかった。

CSS3 filterを使うことにしたが素直に適用すると背景以外の全体に掛かってしまう。困ってぐぐってみたところこんな記事がヒットした。

kuroeveryday.blogspot.com

最背面に置いた疑似要素に対してやれば良い感じなのねーということで、position: fixed な疑似要素を width: 100vw; height: 100vh; で画面サイズに合わせて最背面に配置するという感じでうまくいった。ついでなのでblurもかけてボカした。ボカしたところ端っこが残ってしまったので top: -5px; left: -5px としつつ width: 120vw; heigth: 120vw としてお茶を濁した。 position: fixed はiPhoneで描画がアレだったきがするけど、どうせデザインはモバイル向けに適用されないので良いでしょう。

サイドバーを広げる

Twitterのフォローボタンがきゅうくつな感じだったので、広げたくなった。

単純にサイドバー #box2 を広げたがうまくいかず、下にコンテンツが回ってしまった。デバッガを眺めていたところ float: left で実装されていてそれで吹っ飛んだことがわかった。 もう少し調べるたところ、どうも#wrapper#wrapper > * への指定がキモらしい。

#box2 には 160px の幅と 20px のmarginが全体に設定されており、横幅は合計で 200px となる。 一方、 #wrapper には margin-right: -201px; という怪しげなネガティブマージン、 #wrapper > * には margin-right: 200px; が設定されていた。 つまり #wrapper のネガティブマージンでサイドバーぶんの余白+1pxを確保して、 #wrapper > * でmarginをもとに戻すことで余白を確保したのだろう。 コーディングの苦労が伺える。いまであればFlexboxでやるのが良さそうだが、当時はこういうハックしかなかったのだろう。実装方法に関心した。

というわけでちょっとこのブログが見やすくなった気がします。

2018年のKPT

昨年度:

techblog.karupas.org

Keep

良かったこと、続けたいこと

YAPC::Okinawaで話した

id:charsbar さんの代打でPerlの最新情報について話せる機会を頂けたので(想定外にスタッフ業が忙しくなってしまったので辛かったけど)charsbarさんの力を借りながらなんとか自分なりに調べてまとめて話した。

大変だけどPerlの最新機能をあれやこれや調べたり試したりできてよかった。これをきっかけにperl-portersを購読しはじめた(あんまり追えてないけど…)

Shibuya.pmをやった

YAPC::OkinawaのKeynoteでid:yappoさんがShibuya.pmに触れて、Shibuya.pmも次の人につないでいくべきだよねという話をしていた。 懇親会でやらないかとなったので、Gotanda.pmと両方やるのは難しいのでこっちを誰かに渡せたらやりますとしたところid:kfly8が快諾してくれたのでそっちは彼に引き継いでShibuya.pmを正式に引き継ぐことになった。そのまま7/5になんとか開催して伝統(?)の引き継ぎの儀もやった。

LTもやった:

speakerdeck.com

いろいろな人の協力もあって、楽しんでもらえてよかった。

ライブやった

ひょんなことで知り合った八王子の居酒屋さんの新年会で年明け早々の1月2日に弾き語りでライブやって、2月,4月とモンズリーズで出演。 11月にはソロで5年ぶりくらいに弾き語りでエンジニアライブに出演。客層わかってたからそこに絞って構成と演出練ったらウケたっぽいので良かった。新曲も作ったのでレコーディングしたい。年明けそうそうに喉の調子がよかったらやる。

ベース教室に通い始めた

自分で練習しているとどうしても自分の手癖っぽい感じに偏りがちだったりするので教室に通い始めた。 指弾きが特に独学過ぎてわからんかったので、フォームの修正から入っていった。リズムに関しても厳しく見て優しく教えてくれてリズム感も鍛えられた。 特にコードの解釈とベースのフレージングの幅が広げられた気がする。TAB符でない普通の楽譜は苦手意識があったんだけど読譜も上達して苦手意識も減ってきた。 何より、定期的にあるとやる気が補充できるという嬉しい効果があったのがよかった。

社の軽音部に加入した

社にいつのまにか軽音部が発足していたので入った。ときどきセッションをしたりするゆるい感じ。 最近はコピーを何曲かガチめにやるぞという取り組みをしていて、普段やらないジャンルの選曲なので難しくて楽しい。

builderscon.tokyo で話した

素人ながらレコーディング/ミキシングのさわりを話した。

speakerdeck.com

割と好評だったようで、フィードバックも良いものがもらえてよかった。 60分でも触りから説明しようとしたら時間的に難しかったので色々端折ったので何かの機会にもうちょっと踏み込んだこと喋りたい。

ISUCON8出題した

がんばった!たのしかった!これ読んで:

isucon.net

各種コミュニティ/社内勉強会で話せた

引き続き各種コミュニティ、社内勉強会で話して交流できたのでよかった。 特にひとでさんの結婚を皮切りに京都方面とのコミュニケーションが厚くなったきがする。楽しいのでもっと入っていきたい。

これは今年公開したるなかで一番好きなスライド:

JPA引き続き活動できた

YAPCの主催以外の諸々など引き続き活動できて、実際いくつか動きがありました。 ここで書くのも適切じゃないので、ほかの機会にまたお知らせできればと思います。

Problem

技術ブログあんま書けなかった

今年の唯一の記事がこれ。

techblog.karupas.org

エイプリルフールだし、ボタンぽちっとだけだし、書いたうちに入らなさそう。

本当はShibuya.pmのやつとかYAPCとかISUCONとかも書きたかったんだけど色々大変なまま時間とれず過ぎ去ってしまった。 このままだと1年を振り返るブログになりつつあるが来年こそは何かしら記録していきたい。

スケジュール調整が厳しい

ベース教室や軽音部を始めたり、社やJPAの仕事の幅が広がったりしたデメリットとして、ただでさえ苦手なスケジュール調整が増えて大変になってしまった。 スケジュール調整を効率的に無心でやるすべを身に着けたい。

karupas.org がぶっ壊れたまま放置してしまった

NuxtとFirebaseで作り直すかとなってるんだけど色々忙しくてほとんど進められてない。

Try

TBD