VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

2012年12月

Linuxカーネルのlist, rbtree, sortを使ってみた!

※ このエントリーは、VOYAGE GROUPエンジニアblog Advent Calendarの12/21分です。

こんにちは、VGエンジニアのポール(@pank7)です。

多分知ってる人はいらっしゃいますが、半年前にvgtechブログを書いた際にはまだ日本語がまだダメなので、英語で書きました。今回はできるだけ頑張って日本語で書きます。ご指導よろしくお願いいたします。

何を書きますか

私が書ける言語はそんな多くないですけど、普段自分が好きな言語だといえば、C言語はその中の1つです。Cのメリットとしてはやはり多いと思います。シンプルや移植性が良いや効率的やUNIX系OSと仲良いなどというのがあります。でも今の仕事で使っている言語のPHP、Perl、Python、Shellとかと比べて、正直なところ面倒なデメリットも少なくないと思われています。標準のライブラリーが少ないや標準のデータ構造が弱いやメモリー管理地獄や指針が危険などもいろいろあります。好きな言語なのに、残念ながら、社会人になって職場では一回使ったこともありません。

先ほど言った通りに、C言語のデメリットの1つは標準のデータ構造は確かに弱すぎると自分も強く感じています。PHPやPythonならば、配列(list)や連想配列(map)や集合(set)やソート関数などの基本的に必要なものは必ず提供されていますが、C++でもSTLにいろいろ入っています(そんなに使いやすくもないですけど)。何で私が好きなC言語では何も無いんですか(;´Д`)?!使う際には真っ白から作らなければいけないんですか?という気持ちがどんどん強くなってきて、では、良いコードを探して参考して、自分のライブラリーを暇な時に作らないのと思い始めました。

今回は中途半端に作ったものをみんなに見せて、指摘をいただきくために、ブログを書いてみることにしました。ぜひ興味のある方はご指導よろしくお願いいたします。

先ず考えなければいけないことは、良いコードはなんですか?誰の何のコードを参考すればいいですか?違う人の標準は多分異なっていますが、自分のスタンダードからすると、一つ目は多くのところでよく使われているこどです。使われているC言語だと考えたら、Linuxのカーネルはやはり良い選択肢ですね。そういうふうに思いながら、Linuxカーネルのコード少し探しました。結果として、予想どおりいつくかが出てきました。

linux/include/linux/list.h

これはLinuxカーネルでどこでも使ってリンクリスト(linked list)です。それをぐぐるすれば、概論的な文章はいっぱい出てきます。またコードを読むと、使い方もシンプルで、struct list_headというデータ構造を自分のデータ構造に埋め込んで、いくつかのマクロと関数で、どのタイプのデータもリンクリストとして使えるようになれます。

初めて知った際に、面白いと思っていたコードは下3つのマクロです

#ifndef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif /* offsetof */

#define container_of(ptr, type, member) ({              \
     const typeof( ((type *)0)->member ) *__mptr = (ptr);   \
     (type *)( (char *)__mptr - offsetof(type,member) );})

#define list_entry(ptr, type, member)                 \
     container_of(ptr, type, member) 

0を自分のタイプのアドレスにキャストして、構造体のアドレスからlist_headメンバーまでの距離が分かれます。それで、list_headメンバーのアドレスから構造体のアドレスを推測できています。

linux/include/linux/rbtree.h

これはLinuxカーネルの汎用の赤黒木(red-black tree)のデータ構造とアルゴリズムです。これもネット上では紹介文が多いと思います。デザインのせいで、list.hと比べて少し使いにくいですけど、メリットとしては、メモリの使用は非常に効率です。下のはrbtree.hの基本的なデータ構造で、使い方もlist_headと一緒で、自分のデータ構造に埋め込んで(こちらでもcontainer_ofマクロが使われてる)から、関数を呼ぶことだけです。

struct rb_node
{
  unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
  struct rb_node *rb_right;
  struct rb_node *rb_left
 } __attribute__((aligned(sizeof(long))));

赤黒木の節点では色が付いていますが、この構造を見ると、rb_parent_colorメンバーのこの名前がおかしくないですか?原因は”__attribute__((aligned(sizeof(long))));”のせいで、この構造体のアドレスは必ず8(64ビットX86のCPUなら)の倍数になるので、アドレスの一番右からの3つのビットは絶対0になります。それで、一番右にビットを節点の色として使うことなるので、rb_parent_colorという名前になりました。

linux/include/linux/sort.h

これはLinuxカーネルの汎用のソート関数です。アルゴリズム的には普通のヒープソートですから、時間計算量はO(n log n)です。インターフェース関数を見ればわかります。

void
sort (void *base, unsigned int *index, size_t num, size_t size,
      int (*cmp) (const void *, const void *), 
       void (*swap) (void *, void *, int size));

用意する必要なのもはデータの比較関数とデータの取り替え関数だけです。

自分が何を少しやったかというと(https://github.com/pank7/pank7-lib

1、上の3つの部分のコードを切り出して、Linuxカーネルコードの外でもC++でも使える形にしました


2、そして、intタイプのスタック(int_stack_type)と双方向キュー(int_queue_type)と集合(int_set_type)、この3つの基本的なデータ構造のサンプルコードを書いたことです。


テスト用の使い方を表すサンプルコードもいくつかがあります。中途半端なのも、多分完璧ではありませんが、ぜひC言語を書いてる方や興味のある方は使ってみれば嬉しいです、ご指摘よろしくお願いいたします。

終わりに

  • linux/include/linuxの下に他の良いデータ構造とアルゴリズムでもいっぱいあります…
  • 他の強い言語でよく使われてる基本的なデータ構造はそれだけではないんですけど、伝えたいこととしては、C言語でも使いやすいデータ構造は多くあるので、C言語のデメリットを改善して、メリットがちゃんと発揮できるということです。では、今回はここまでです。

次回予告

次回のAdvent Calendar担当は@_zooです。

なれる!VG ― 1エントリーでわかる?SE入門 #vgadvent2012

このエントリーは、VOYAGE GROUPエンジニアblog Advent Calendarの12/16分です。

本日は私、VOYAGE GROUP 新規事業開発室 兼 adingo データプラットフォーム本部所属エンジニア@bash0C7がお送りします。
俺Rubyテスト環境としてはrspecrrguard-sporkを愛用しています。フレームワークはPadrinothorが最近のお気に入りです。

■意思決定に足る情報に当たる

さて、現在大学3回生のみなさんは就職活動まっただ中かと思います。プログラマー職やシステムエンジニア職に興味をもち、IT技術の世界に飛び込もうと思っている方も少なからずいらっしゃるかと思います。

しかしインターネットを巡ると、SEだのプログラマだのという仕事について、きつい、帰れない、しんどい、休みとれないなどネガティブな言葉で語られているのを目にした方も多いと思います。また、知り合いや先輩がそういう事を言っているのを耳にした方も少なからずいると思います。

実際にはどうなのでしょうか。

確かに上記のような話は私も見聞きしたことがあります。しかしそれらは得てして端的に話をする中で、極めて一部の側面を切り取ってセンセーショナルの切り口にフォーカスした断片的な情報であり、それだけで何らかの意思決定を行うのはあまりに早計過ぎます。
きちんとコンテキストや雰囲気まで含む総合的な情報として、きちんとまとまった資料に当たることが王道です。

そこで、前置きが長くなりましたが、これからの自らのキャリアを考え未来を選択していく上で読むべき情報として私個人として強く薦めたいのが「なれる!SE」です。
■「なれる!SE」とは

公式サイトの説明を引用すると、「なれる!SE」とはこういう作品です。
平凡な社会人一年生、桜坂工兵は厳しい就職活動を経て、とあるシステム開発会社に就職した。
そんな彼の教育係についた室見立華は、どう見ても十代にしか見えない少女だった。
しかしそんな見た目に反し室見は確かな実力を持つワーカホリック娘で、多忙かつまったく優しくない彼女のもと、工兵は時に厳しく指導され、時に放置プレイされながら奮闘することになる。
入社早々、実際の顧客相手の案件担当を振られるのを皮切りに、社内の運用部署との調整や大規模案件の提案、はてはベンダー数社を束ねるプロジェクトマネージャーまで、およそ新卒一年目にはハードルの高すぎる業務を無茶振りされるが!?
システムエンジニアの過酷な実態をコミカルに描く物語、それが『なれる!SE』です!
小説、漫画、ドラマCD、グッズと、人気作品の王道展開がなされており、小説は12/10に最新刊の8巻が刊行されました。漫画版はWebサイトで読むことができる他、コミック2巻まで刊行されています。

内容としては、先に引用した説明文の通り、
システムエンジニアの過酷な実態
とあるように、確かにそういう部分についてのシーンがイキイキと描かれています。Amazonのカスタマーレビューをみてもそういう部分についての言及が多く、眠りを覚ます恐怖の記憶(トラウマ)が蘇った方が少なからずいらっしゃるようです。

また、主人公の上司の室見さんという人物がこれまた大変イキイキと描かれていまして、これがとてもとても魅力的であり、私としては「室見さんは俺のOJTメンター」という言葉を胸にいだいて生きています。これについても多くの読者が同意していただけるものと信じています。
余談ですが、職業人としての室見さんの立ち居振る舞いは色々な意味で参考になります。こちらについてはまた改めて主張しようと思います。

確かに、それらの部分に悶え倒すのは素晴らしいエンターティメントです。一読者として大いに楽しませていただきました。しかし、自らのキャリアを考える材料として読み取る上では、そういった部分だけをピックアップしてしまうのは、あえて強い口調でいうと誤読であると言わざるを得ません。

■環境に依存する事柄を見出す

例えば、SEだからプログラマーだから過酷だろうと読み取ってしまうかもしれません。残念ながらこれはあまりに短絡過ぎます。なぜならその過酷さは職業に由来する部分よりも環境に依存する部分が多いからです。

作中のエピソードを一つ引用すると、小説の1巻で室見さんがこういう事を発言しています。

「どんな状況だろうとベストを尽くす。それが私達技術屋の役割よ。クライアントがどんな人間でも扱うプロトコルやパケットは変わらない。いつもと同じことをするだけ」

この発言自体は室見さんとしてのエンジニアとしての矜持の発露でしょう。エンジニアとしての矜持としては私は別の考えをもっていますし、人の数だけ違ったものを抱いていると思います。しかし今回の論点はそういう個々人レベルの話ではありません。この発言からは室見さんの周りにある、対立関係の力が働く環境の影響が透けて見えます。

今の私のまわりを見渡すに、こういう発言が飛び出る状況はありません。想像もし難いです。経営理念のCREEDにある「仲間と事をなす」という項目が自分たちにとっていつものことと捉えられているのも、その現れなのでしょう。
もちろん激しい議論をぶつけ合うというのはあります。ときに過度にヒートアップしてしまうこともありますが、それもまたCREEDにある別の項目「本質を追い求める」の一つであり、信頼があるからこそできる事でもあります。

■職業に由来する楽しさを見出す 

それで、自らのこれからを考えていく上でこの作品から本当に読み取るべきは、この作品の登場人物たちが生業とし、そして私が生業としているこの職業は最高に楽しいものだという事です。

例えば、小説の2巻で下記のようなシーンがあります。
トラブルが突発し緊急で対応せねばならない事態となり、普段とはまるで違う雰囲気に切り替わった同僚。そのときの室見さんと、同僚のその変わり様に戸惑う主人公とのやり取りです。
「この子にはね、運用ドキュメントなんか必要ないの。コンフィグや設定ファイル、ソースコードからでもシステムの全体像を解析し障害ポイントを特定できる。……定型オペレーション?フロー?はっ、よく言うわ。いざとなったらそんなもの見もしないくせに。この子はね、オペレータなんかじゃない。生粋のエンジニア、トラブルシューターよ」
トラブル…シューター。
呆然とする工兵に室見は「なによ、おかしな顔して」とせせら笑ってみせた。白い歯を剥き出し、ひどく露悪的な顔つきとなる。
こうです!これぞです!これこそなんです!室見さんはエクセレントだッッ!!哭ける!!!今夜は哭けるッわたしは今夜大声で哭くぞッッ 私たちの仕事とは、私たちの生業とは、各々が日々磨いた技術(ワザ)と積み上げてきた経験で、不都合な現状を解決し、最高な方向に覆すことなんです。
その中で、上記のシーンのような障害対応はもちろん重要ではありますが、解決すべきことの一つでしかありません。
もっと広く、様々な物事について、自分たちの手で望ましいものを成り立たせ維持することができる、パッションあふるるのがこの生業なのです。

ありがたいことに、私たちの周りにはたくさんの実現したいことがたくさんあります。新サービスを立ち上げ、既存サービスを盛り上げ、より素晴らしい技術を取り入れ、予期しがたい事態を解決し、迅速に事を進行する。一生かけても行い尽くせません。そんな楽しい位置に私たちはいるのです。

それなので、すでに読んだよという方も、これから読むよという方も、是非こういう部分に着目して、室見さんたちの心の躍動を味わってみてください。
また、それを味わったならば、ぜひ自らの生業としてこの職業に就くことを志してみませんか?

我々VOYAGE GROUPは現在2014年入社となる新卒採用活動を実施しております。我々と一緒に、「ミチを切り拓く」強い意志と覚悟を持ち、 仲間として共に挑戦していきたい!という方を募集しております。
もし我々に興味がでてきたならば、是非新卒採用選考会2014にエントリー下さい。

■次回予告

明日は、  monmon がエエ話を書いてくれます。お楽しみに!

私男だけどタイポするECナビの中の人達って・・・

二度目まして。中村(おみ) @tomomihoge と申します。
VOYAGE GROUP 社内ではECナビ事業本部にてエンジニアをしたり、
他人の日報にアスキーアートを貼り付けたりしています。

Advent Calendar 的なモノをやるぜ? と言う話にうっかり手を挙げてしまったので、
日曜日にふさわしい脱力系のどうでもいい話をしようと思います。
こんなタイポで盛り上がった、と言う話題。

次回はもう少しテクニカルなものを書くと言ったな。アレはウソだ。

■EcanviController.class.php

去年の5月頃の事です。
Fuga 機能を実装するために、既存コードを参考にしようとHogeController のコードを読んでいた私。
EcnaviController から継承してるようなので、まずはそちらを読みに行きます。

$ls -l
EcanviController.class.php
こいつか。
$ vi EcnaviController.class.php
~
~
~
"EcnaviController.class.php" [新ファイル]

新ファイル・・・ だと? そう言えば bash の入力補完が効かなかった。

実際の所は EcnaviController.class.php ではなく EcanviController.class.php だったのですが、
気がつくのに相当時間がかかりました。

この罠は今も新入りのエンジニア達に情け容赦なく襲い掛かります。

「おみさん、この EcnaviController.class.php ってファイルあるじゃないすか。」
「あるね(ないけどな)。」
「何故か開けないんすよ。」
「そうだね(名前違うしな)。」
「どうしてっすかね。なんか権限足りないとか。」
「落ち着いて良くファイル名を確認するんだ。」
「え?いーしーな・・」
「いーしー、その次はエヌか?」
「いーし・・・・えー。いーしーきゃんびー!?」
「そこに気がつくとは・・・ 大したやつだ」

・・・的な会話が繰り広げられてるわけです。
配属直後からエンジニア間のコミュニケーションを促進する、まさに神タイポと言えましょう。

■Heler


今年の8月頃の事です。
とある機能をアレする為に、ハイパーメディアエンジニアの某氏が何かを作成しました。
事業部エンジニアで集まってのレビュー会での事。

「・・・と、言う感じ。」
「good job!」
「神!あるいはゴッド!」
「エクセレント!」
「ところで、ヘラーって何?」

当該機能の肝の一つ、なんちゃらヘルパーさんが、 NancharaHeler になってたのです。
(なんちゃらな処理を手助けしてくれる何かです。)

「ほんまや。ヘラーて。」
「ヘラーwww」
「これは良いタイポですね。」
「これは修正しておきm」
「このままでいいよ。」
「むしろ今のままのヘラーでいて!」
「もうヘラーしか愛せない。」

その日の日報は heler が席巻しました。
今日からアレをアレする作業に取り掛かりました。
山口さん(仮)の例のなんちゃらができあがったようです。
Helerフレームワーク、いい名前がついて、
今から伝説臭がします。
なんていうか、もう許してやれよ。

※ その後、修正されてしまった。泣ける。

■まとめ

タイプミスもまとめて楽しんでしまうのがECナビ流です。
すべてに楽しさを、みたいな?
でもまぁ、コード読む時に困るから結局直すんですけどね。

明日は @saya_223n さんが諸事情により不明な話を皆さんにお届けする模様!

※ 記事の最後で紹介したいから内容聞かせてって言ったのにスルーされました。(実話)

Advent Calendar 2012

時流に乗って当ブログでもAdvent Calendarやりますよ。

テーマ決定プロセス
テーマを決めるに当たり下記のような会話がGoogle spreadsheet上で行われVOYAGE GROUPに少しでも絡んでいたら何でもOKってことになりました。
「テーマどうする?」→「自分は技術の話はあんまりしないかなーと思うんだけど、他の人は全然コードの話とかしてもいいとおもうんですよね」→「あたりをスマートに表現したい、ということか」→「そうそう」→「どうしましょうねー」→「どっちもでいい」→「指針が欲しい」→「自ら考え自ら動け」→「さすがタイガさんCREED力あるなー」→「僕じゃないっすよ」→「会話すんなよ」→「この行面白いな」→「このカオスを貼り付けて終わりでいいと思うぜ」

VOYAGE GROUP エンジニアブログ Advent Calendar 2012
日付担当者エントリ
12/1@makoga挑戦し続けるために意識していること其の一
12/2@katzchangちょっと湯豆腐を作ってみますね…
12/3@suzu_v[#vgadvent2012] 湯豆腐の季節ですね
12/4@chiseiエンジニアのための年末大掃除ハック #vgadvent2012
12/5@tomitaWhat is worth fighting for
12/6@chocopie116僕らのサービスのお客さんは誰だろう? #vgadvent2012
12/7@kenichikatお正月をのんびり過ごすためのインフラ構成
12/8@ntakaaki素のRedmineに比べて様々な使い勝手が向上してるAlminiumのご紹介
12/9@tomomihoge私男だけどタイポするECナビの中の人達って・・・
12/10@saya_223nGirl's Web★Fantastic World!! [#vgadvent2012]
12/11@akiyahECナビ おしえて!どっち? の投票結果をグラフにする #vgadvent2012
12/12しま年末に向けたお金の稼ぎ方 #vgadvent2012
12/13@mugesoVOYAGE GROUPで新卒エンジニアを生暖かく見守ったお話 #vgadvent2012
12/14@kuromatu業務系プログラミングへのチャレンジのススメ #vgadvent2012
12/15@brtriver3分でできる俺PHPテスト環境
12/16@bash0C7なれる!VG ― 1エントリーでわかる?SE入門 #vgadvent2012
12/17@lesamoureuses Perlとバーコードリーダーで本棚整理をするよ! #vgadvent2012
12/18@tadasy僕とVOYAGEと開発マシーン #vgadvent2012
12/19@takkyuuplayer国会図書館のすすめ [#vgadvent2012]
12/20@hagino3000MacOS X Mountain Lionの通知センターを便利に使う
12/21@pank7Linuxカーネルのlist, rbtree, sortを使ってみた!
12/22@_zooSinatraからPadrinoへのお引越し
12/23@_hironomiu一年の振り返り
12/24@ajiyoshi やはりお前らはSICPを読むといい
記事検索
QRコード
QRコード

'); label.html('\ ライブドアブログでは広告のパーソナライズや効果測定のためクッキー(cookie)を使用しています。
\ このバナーを閉じるか閲覧を継続することでクッキーの使用を承認いただいたものとさせていただきます。
\ また、お客様は当社パートナー企業における所定の手続きにより、クッキーの使用を管理することもできます。
\ 詳細はライブドア利用規約をご確認ください。\ '); banner.append(label); var closeButton = $('