株式会社はてなに入社しました
Intellij IDEA で効率的にコーディングするためにやっていること
まとめ
Shift
を2回押してどこでも検索を使おう。
まえがき
一般的に効率的にコーディングするためにはキーボードショートカット (以下、ショートカット) を使い、キーボードから極力手を離さないという方法があります。
しかし Intellij の場合、たくさんあるショートカットを覚えるのは大変ですし、操作によってはショートカットの割当設定が必要になるかもしれません。
また、Key Promoter X などのショートカットを教えてくれるプラグインがありますが、通知がたくさん出るのが私には合いませんでした。
どこでも検索
そこで私が使っているのがどこでも検索という機能です。
機能の詳細は Intellij のドキュメントに任せますが、これによりショートカットを1つ1つ覚えたり設定する必要はなくなります。加えてショートカットを教えてくれるので、私はよく使う操作のショートカットを覚えることができました。
使い方
Shift + Shift
(Shift
キーを2回) で呼び出すことができます。
以下に2つ使用例を載せました。
例1: Git のブランチ切り替え
よく行う操作に Git のブランチ切り替えがあります。これをどこでも検索でやります。
まず、どこでも検索の検索ウィンドウを開き、「git branch」で検索したのが次の画像です。
Branches...
の横に書かれている Ctrl+Shift+`
は割り当てられているショートカットです。何度も実行しているうちに目に入って覚えられると思います。
実行するとブランチを管理するウィンドウが開きます。
例2: タブを全て閉じる
次は現在開いているタブをすべて閉じます。
どこでも検索で「close」と入力すると候補に Close All Tabs が出てきました。これを実行するとタブを全て閉じることができます。
この操作にはショートカットがデフォルトで割り当てられていません。もちろん自分で割当設定をしてもいいのですが、設定が面倒であればこのように実行できます。
おわり
いちいち検索するのが面倒という意見がありそうですが、個人的には Emacs で関数を実行する感覚で使っていて気になりません。
GitHubのREST APIを使って名前に '/' の入ったEnvironmentを作る
要点: %2F
で /
をエスケープしてあげればいい
Create or update an environment
GitHub は Environment を作成する REST API を提供しています。
使い方はリファレンスに詳しく書いてありますが、curl なら次のような感じ。適切な権限を付与したアクセストークン (GITHUB_PAT
) を用いて、リポジトリ (OWNER
/REPO
) に ENVIRONMENT_NAME
という名前で Environment を作るコマンドです。
export GITHUB_PAT=<YOUR_TOKEN> export OWNER=<YOUR_OWNER> export REPO=<YOUR_REPO> export ENVIRONMENT_NAME=<YOUR_ENVIRONMENT_NAME> curl -L \ -X PUT \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer "${GITHUB_PAT}"" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/"${OWNER}"/"${REPO}"/environments/"${ENVIRONMENT_NAME}"
トークンの作り方:
Environment 名に '/' を使いたいとき
Environment 名に /
を使って、例えば、production/backend というように構造化したいかもしれません。
その場合は、/
を %2F
にパーセントエンコーディングする必要があります。
コマンド例 (ENVIRONMENT_NAME
に注目):
export GITHUB_PAT=<YOUR_TOKEN> export OWNER=<YOUR_OWNER> export REPO=<YOUR_REPO> # / を %2F に変換 export ENVIRONMENT_NAME=production%2Fbackend curl -L \ -X PUT \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer "${GITHUB_PAT}"" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/"${OWNER}"/"${REPO}"/environments/"${ENVIRONMENT_NAME}"
エンコードしないとエラーレスポンスが返ってきます。
プライベートリポジトリだと具体的なエラーメッセージは無く、Not Found とだけ返ってくるので注意です。
{ "message": "Not Found", "documentation_url": "https://docs.github.com/rest" }
補足1. ラベルの場合
Environment と同じように、Issue や Pull Request に付けるラベルも REST API を通じて作れます。
しかし、ラベルの場合は /
が名前に入っていてもエスケープ処理が不要でした。
補足2. プラン
GitHub Free プランでは、プライベートリポジトリで Environment を使えません。実際に試すときはリポジトリの可視性やプランを確認してください。
2023年の振り返り
とりあえず書いた。
仕事
学生生活が終わり社会人になった。
AWS でインフラ構築するのが主な仕事で、Terraform で IaC したり、TypeScript でツール書いたりしている。
よかった技術書
システム設計の面接試験
本のタイトルには「面接試験」とあるけれど普段の業務でも役立つ。内容がわかりやすいのはもちろん、参考文献がたくさん載っているのがよかった。
入門モダン Linux
短くまとまっているのと、図がわかりやすいのがよかった。
ロードバイクを買った
リモートワークで家に籠りがちなので運動のためロードバイクを買った。週末に80kmくらい乗ってる。
運動ならロードバイクである必要はないけれど、ずっとやりたいと思っていたので買った。やりたいと思っていたことが叶ったのは喜ばしいことなのだけど、このままやらなかったら一生やらずに死ぬんだろうと後ろ向きな感覚が芽生えてしまった。悲しい。
今は25km/hで数kmのペースなので、来年は30km/hで100km走れるようになりたい。.
来年
来年はもっとブログ書いたりコード書いたりアウトプットしたい。
来年もよろしくおねがいします。
Linuxカーネルの赤黒木のおもしろい最適化
この記事ははてなエンジニア Advent Calendar 2023 の27日目の記事です。はてなのアドベントカレンダーはまだまだ続きます!
26日目の記事は id:masayosu さんの EKS Pod Identity を活用するメリットでした。
赤黒木とは
赤黒木は平衡二分探索木の1種で、各ノードが赤か黒の色に塗り分けられていることが特徴の1つです。
(Wikipedia の赤黒木のページの画像)
この記事では赤黒木に詳しい必要はないので、説明は wikipedia の赤黒木のページに任せます。
Linux カーネルでは、CFS スケジューラで用いられたりしています。
Linux の赤黒木のノード
Linux カーネルの赤黒木の実装を見ていきます。この記事では特に赤黒木のノードに注目します。
include/linux/rbtree_types.h (v6.6) にある rb_node
が赤黒木のノードを表す構造体です。
struct rb_node { unsigned long __rb_parent_color; struct rb_node *rb_right; struct rb_node *rb_left; } __attribute__((aligned(sizeof(long)))); /* The alignment might seem pointless, but allegedly CRIS needs it */
まず、rb_node
構造体は3つのフィールドを持っています。
__rb_parent_color
- 木の親と自身の色 (赤か黒) の情報
- 下記で詳しく見ていきます。
*rb_right
- 右側の子ノードへのポインタ
*rb_left
- 右側の子ノードへのポインタ
次に、 __attribute__((aligned(sizeof(long))))
という部分はコンパイラにアライメント境界を伝えるキーワードです。
下記で詳しく見ていきます。
コミットログを追う
コミットログを読んで rb_node
構造体の理解を深めます。
v6.6 では rb_node
構造体は include/linux/rbtree_types.h に定義されていますが、v5.15 まで include/linux/rbtree.h ファイルに定義されていました1。
なので、include/linux/rbtree.h の Git のコミットログを追います。
v2.6.12-rc2
Linux カーネルのソースコードが Git で管理されるのは v2.6.12-rc2 からです。
そこで v2.6.12-rc2 から見ていきます。
include/linux/rbtree.h (v2.6.12-rc2)
struct rb_node { struct rb_node *rb_parent; int rb_color; #define RB_RED 0 #define RB_BLACK 1 struct rb_node *rb_right; struct rb_node *rb_left; };
v6.6 と大きく異なるのは、v2.6.12-rc2 の時点では __rb_parent_color
フィールドは存在せず、 *rb_parent
と rb_color
にフィールドが別れている点です。
v2.6.18
v2.6.18 で v6.6 とほとんど同じコードになります。
include/linux/rbtree.h (v2.6.18)
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)))); /* The alignment might seem pointless, but allegedly CRIS needs it */
赤黒木に関するコミットはいくつかありますが、その中でも2つのコミットを見てみます。
[RBTREE] Merge colour and parent fields of struct rb_node.
We only used a single bit for colour information, so having a whole machine word of space allocated for it was a bit wasteful. Instead, store it in the lowest bit of the 'parent' pointer, since that was always going to be aligned anyway.
このコミットで *rb_parent
と rb_color
が rb_parent_colour
というフィールドにまとまります。
struct rb_node { - struct rb_node *rb_parent; - int rb_color; + unsigned long rb_parent_colour; #define RB_RED 0 #define RB_BLACK 1 struct rb_node *rb_right; struct rb_node *rb_left; };
親へのポインタ ( *rb_parent
) の最下位1ビット (LSB) に色情報 ( rb_color
) を格納することでメモリの無駄遣いを防ぐことができるということがコミットメッセージに書いてあります。
なぜ、ポインタの LSB に色情報を格納できるのでしょうか。
それは、親へのポインタは偶数アドレスに配置されるので、LSB は必ず0になるからです。ポインタが偶数アドレスになる理由は、rb_node
構造体がアライメントされてメモリに配置されるからです。
このようなポインタの使い方を Tagged pointer と呼ぶらしいです。
ちなみに、colour というのは typo ではなくイギリス英語のスペルです。v2.6.18 のリリースまでにアメリカ英語の color に変更されました2。
[RBTREE] Add explicit alignment to sizeof(long) for struct rb_node.
Seems like a strange requirement, but allegedly it was necessary for struct address_space on CRIS, because it otherwise ended up being only byte-aligned. It's harmless enough, and easier to just do it than to prove it isn't necessary... although I really ought to dig out my etrax board and test it some time.
__attribute__
というコンパイラにアライメント境界を伝えるキーワードが追加されます。
+} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */
通常、コンパイラはこのコードが無くてもアライメントするはずですが、 CRIS ではそれがうまくいかないらしいということがコミットメッセージでわかります。
__attribute__
は GCC の構文3で、構造体と共用体に属性を付与できます。aligned
は属性の1つで、アラインメントの境界を指定できます。64ビットアーキテクチャでは long 型は8バイトなので、8バイトアライメントされるはずです。
CRIS というのは Axis Communications 社の開発しているアーキテクチャのことだと思います4。
まとめ
Linux カーネルの赤黒木の実装に見る Tagged Pointer を用いた最適化の話でした。
この記事ははてなエンジニア Advent Calendar 2023 の27日目の記事でした。
明日の記事は id:SlashNephy さんです。
参考
Jetbrains AI Assistant を使ってみた
2023年12月6日、ついに Jetbrains AI の提供が始まりました。
この AI 機能は、2023年7月ごろにテクニカルプレビューとして登場しました。私もそれを試用して、その機能に魅力を感じていました。そのため今回リリースされてすぐにライセンスを購入し、さっそく利用してみました。
この記事では、個人的に特に魅力を感じた Explain Code 機能を紹介します。
Explain Code 機能がすごい
AI チャットの機能の1つに Explain Code という機能があります。これはその名の通り、コードの意味を説明してくれるものです。
例えば、 Linux カーネルの CPU スケジューラの初期化関数を解説してもらうとこんな感じです。
コード: https://elixir.bootlin.com/linux/latest/source/kernel/sched/core.c#L9912
まず、1行目で、「これは Linux カーネルのコードでタスクスケジューラの初期化部分です」と説明されます。
This is a part of the Linux kernel code which is responsible for initializing the task scheduler.
こちらからこの関数が Linux カーネルのコードの一部であることは伝えていないので、AI がコードを見て推測しているということでしょう。
次に、 __init
が Linux カーネル独自のものであることを教えてくれます。
This function is named sched_init and is tagged with __init which in Linux kernel programming means that this function is executed only once at startup and its memory can be freed up after this.
もう少し説明がほしいと思ったので、AI Assistant に聞いてみました。
先程より詳しい解説が返ってきました。
要約すると、「これは Linux カーネルのマクロで、カーネルがメモリにロードされるときに1度呼び出され、メモリを効率的に扱えるようにするものです」と答えてくれています。
感想
まだすべての機能を試していませんが、AI チャットだけを見ても Jetbrains AI に期待できるのではないでしょうか。
関連
Intellij IDEAでemoji入力 (プラグイン不要)
Intellij IDEA など、Jetbrains 社の IDE で emoji (絵文字) を入力する方法を知ったのでメモ。
TL;DR
Ctrl+Alt+;
概要
IntelliJ IDEA 2020.3 でリリースされた機能の1つです。
Linux emoji picker という見出しで紹介されています。
for Linux と書かれているので、このアップデートは Linux ユーザ向けということだと思います。Windows や mac ではどうなっているのかわかりません。
使ってみる
デフォルトでは、 Ctrl+Alt+;
で emoji picker を開けます。
もし emoji picker が開かない場合、Ctrl+Alt+;
が Emoji & Symbols
に割り当てられているか確認してください。