diary

I like Hatena Star with a text selection.

2024-04-04

github.com

Steep で不要な RBS::Location#to_s の呼び出しを消すPRを作った。 RBSのメモリ使用量を減らす前準備。


github.com

RBSのメモリ使用量を減らすために色々やっているのだけど、計測用にベンチマークスクリプトを毎回書いているのは面倒なので、rbsリポジトリに追加するPR。


Cを書いていて、謎のセグフォが出てそこそこ悩んだ。雰囲気は次のようなコード

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int id;
  int value;
} entry;

typedef struct {
  int len;
  int cap;
  entry entries[0];
} table;

table *table_new(int cap) {
  table *t = malloc(sizeof(table) + sizeof(entry) * cap);
  t->len = 0;
  t->cap = cap;
  return t;
}

int main(void) {
  table *t1 = table_new(1000);
  for (int i = 0; i < t1->cap; i++) {
    t1->entries[i].id = i;
    t1->entries[i].value = i * 10;
    t1->len++;
  }

  table t2 = *t1;
  printf("t1 last value: %d\n", t1->entries[t1->len-1].value);
  printf("t2 last value: %d\n", t2.entries[t2.len-1].value);

  return 0;
}

t1もt2も同じstructなので同じ値が出力されると思いきや、私の手元だとt2`を出力するところでセグフォが出てしまう。

t1 last value: 9990
zsh: segmentation fault  ./a.out

この問題に最初遭遇したときは、t2の方の書き方だけをしていたので、セグフォの原因がさっぱりだった。 その後t1の書き方をすると解決することに気がついたのだけど、「えっ->(*v).ってsyntax sugerの関係なんじゃないの??」としばらく理解ができていなかった。

これの答えが何だったかと言うと、構造体をコピーしていることが原因だった。

まず、entry entries[0] の部分が影響している。これは可変長構造体、みたいな用語(正確な用語は知らない)のテクで、メモリ使用量を抑えるのに便利。 https://satosystems.hatenablog.com/entry/20100916/1284637817 とかを参考にしていた。

これは構造体の直後のメモリ領域に配列のためのメモリ領域を確保して、構造体に配列へのポインタをもたせることなく可変長の配列を実現している。便利。

ところが、table t2 = *t1;t1 を別のローカル変数であるt2にコピーしている。ということは、このt2が保存されているアドレスはもともとmallocしてきたアドレスとは異なるということ。t2.entriest2の直後の領域を参照しようとして、セグフォになってしまっていた。

2024-03-28

github.com

rspec-request_describer に PR をしていた。

RSpeccontext を差し込むところを間違えたら、rspec-request_describer 内部でエラーが起きていてエラーの意図を掴むのにちょっと手間取ったので、エラーをハンドルしてどういうエラーなのか分かりやすいようにしてみた。巨大describeになってくるとインデントが迷子になりがち。

速攻マージ&リリースされたので、迷子になりがちな人はアップデートすると良さそう。


最近(といっても数ヶ月前からだけど)は、ピアノで海の見える街を練習している。ピアノのやる気に満ち溢れている期がやってきたので、割と進捗が良い。

曲のイメージをもうちょっと膨らませたくなって、魔女の宅急便の映画を見たりもした。配信がなくて、仕方なくDVDを買った。

2024-03-26

TOEIC IPテストを受けた。860点。

前回から20点下がったが、ツイートにもある通り大きな差ではないので、前回がまぐれでなかった安堵のほうが大きい。

とはいえもうちょっと勉強していきたいなの気持ちでabceedを再開した。

前回受けたのは半年ぐらい前だったかなーと思っていたので、1年も経っていたのはちょっとびっくりした。

ちなみに点数の推移は、680点(2022-04-12), 795点(2022-12-01), 880点(2023-03-01), 860点(2024-03-26)となっている。次は900超えたいなー


www.amazon.co.jp

「追放されたチート付与魔術師は気ままなセカンドライフ謳歌する。 ~俺は武器だけじゃなく、あらゆるものに『強化ポイント』を付与できるし、俺の意思でいつでも効果を解除できるけど、残った人たち大丈夫?~」を最近読んだ。

「あーはいはいよくある追放ものね」と思っていたら、完全に異常で良かった。なろう系だと思わず異常漫画だと思って読んでみるのをめっちゃおすすめ。

2024-03-20

github.com

github.com

activerecord-originator の型定義周りを軽く修正していた。

型の変更しか入っていないけれど、v0.2.1をリリースした。


github.com

graphql-coverage でも同様の型の修正をしていた。


github.com

graphql-coverage を久々にいじっていたら、新しいRubyのバージョンでCIが走っていなかったので有効にした。

2024-03-19

activerecord-originator、ここ数日毎日数件海外の人っぽいstarが増えているのだけど、どこからこれが見つけられているのかがさっぱりわからない。 もっと海外にリーチしていきたいのでヒントがほしい…

2024-03-16

github.com

github.com

activerecord-originatorベンチマークスクリプトを追加した。

これを追加したことによって、どの程度パフォーマンスが劣化しているかが分かった。単純に#to_sqlを呼び出す場合で3倍ぐらい、実際にselectクエリを発行する場合でも2倍ぐらいの速度差が出ていた。クエリを発行しているのはメモリ上のsqliteだし、レコードも100件しか作っていないからあまり現実的な比較ではない。


github.com

activerecord-originatorの速度改善をした。今まではすべてのNodeを拡張してinitialize時にcallerを保存していたのだけど、これをクエリに位置情報を差し込みたいNodeだけ拡張するようにした。

これによって、#to_sqlは71~78%程度、クエリの実行は84~86%程度の速度劣化に抑えられた。

これだけ速度劣化が小さく出ていれば、実アプリケーションに入れたときの速度差は気にならないぐらいになっていそう(たぶん)。単純なクエリ実行の例だと、1回あたり0.02ミリ秒しかオーバーヘッドが乗ってない計算になりそう。

この変更を入れたのでv0.2.0をリリースした


github.com

そういえばIS NULLとかを考えていなかったな、と思ってテストを書いてみたら、特に何もせず通って便利だった。 すでに実装は済んでいたけど、テストがあったほうが後々嬉しくなる可能性がありそうなのでテストだけ追加した。


where("title LIKE ?", "%#{title}%") みたいなやつの対応を考えていたのだけど、むずそう。

これはSqlLiteral nodeとして扱われるのだけど、このNodeが特殊で、どうやら作られるタイミングは#whereが呼ばれるタイミングではなく#to_sqlが呼ばれるタイミングっぽい。それだとこのnodeのinitializeにhookしてもほしい位置情報が取れなくて困る。

いい解決方法あるかなあ。あんまり思いつかない。whereメソッドを上書きして…とかやればできるだろうけどやりたくないよねえ

2024-03-13

activerecord-originator という gem を作った。

github.com

pocke.hatenablog.com

dev.to

めっちゃArelの内部構造に依存しているのだけど、デバッグのヒントを得るツールとしては便利なのではないかと思っている。

ただ常時出しておくと鬱陶しい気もしていて、使いたいときだけピンポイントでインストールするような使い方が良いのかなあと思ったりする。でもそれだと存在を忘れるんだよなあ。

1,2時間ぐらいで仕様や実装方法を検討して最低限コメントが出るプロトタイプまで作った。 その時のコードがこれ https://gist.github.com/pocke/9167bcdb8c13f7550da4ab322b99c229

そのあとちまちまコードを書いてgemとして公開した。思い立ってから2日でリリースまでこぎつけた。

default_scopeで追加された条件が分かりづらい、というところからスタートしていたので、最初は「default_scopeで追加された条件があればそれを分かりやすくする」という仕様を考えていた。しかしそれならより汎用的に対応したほうがいいよなあと思って今の形にした。一応deafult_scopeを条件にコメントとかを差し込めないかもコードを眺めてはいたけれど、それを見つける前に方針転換してしまった。

実際流行るかというと、どうだろうねえ。わりと"発明"なんじゃないかと思っているし、ハマるケースでは確実にめちゃくちゃ便利だとは確信している。とはいえ結構ログがデカくなるのうざいし、正直真に理解が難しいようなクエリがどの程度あるのかは微妙なところだなあと思っている。クソデカ検索条件クラスとかと戦うときには便利そうだけど、シンプルなRailsアプリのふつーなCRUDアクションとかだと無駄にクエリが読みづらくなるだけかもしれない。

これがデバッグに有用な情報であるという点には100%の自信があるのだけど、今の見せ方が最適かというと全然そうは思っていない。もっとnoisyじゃなく見やすくて役立てやすい見せ方が実現したほうが嬉しいと思うけれど、あんまりアイディアはない。

ちなみに実アプリでは(動作確認で一通り動くことは見ているけど)導入はまだしてないです。導入してみるかなあ

お野菜とかによくある「私が作りました」をイメージして作っていた。そんな感じの名前にしたかったけど、いい名前が思いつかず、GPTにいくつか候補を聞いた中からいい感じだなと思ったoriginateという単語を使ってみた。

Twitter(現X)とか英語版記事とかに書いたのだけど、こういう「SQLの各部分に対するデバッグ情報を出す」ツールって今まであったのかなあっていうのが気になっている。なんか知っている人がいたら教えてください。

思いついたコンセプトを、自分ではめっちゃいいと思いこんで興奮しながら、シュッと実装するという行為を久々にできて楽しかった。こういうの大好き


github.com

irb に issue を立てた。ダークサイドに落ちた人しかハマらなさそうな問題を踏んでいた。


久しぶりにこの日記を書いた。引っ越しで環境が変わったりしたのもあって、日記を書く習慣が途切れていた。本来日記のpublishはラズパイで自動化されているのだけど、そのラズパイをまだセットアップしていないから手動でのpublishになってしまっている。