- ymawky は ARM64 アセンブリのみで書かれた静的ファイルWebサーバーで、libc なしで syscall だけを使用し、接続ごとに fork する構造で動作する
- 開発対象は MacOS で、実行は Apple silicon arm64 でのみ可能。ビルドには Xcode Command Line Tools と
make が必要
- デフォルトでは
127.0.0.1:8080 で起動し、ポート指定は可能だが、現在はカスタムアドレスをサポートしておらず 127.0.0.1 でのみ動作する
- ドキュメントルートはデフォルトで
www/。GET / は www/index.html を探し、エラーページは err/(code).html から提供されるよう構成されている
- サポートする HTTP メソッドは GET, PUT, DELETE, OPTIONS, HEAD で、サーバー側コードの実行や
/search?query=term のような高度な URL パースはサポートしない
PUT は最大 1GiB のアップロードを標準でサポートし、一時ファイル www/.ymawky_tmp_<pid> に書き込んでから rename する方式で、部分アップロードが既存ファイルを上書きしないようにしている
GET は Range: bytes= リクエストをサポートし、bytes=X-N、bytes=-N、bytes=X- 形式を処理でき、動画シークにも適しているとされる
- ファイル拡張子に基づいて MIME タイプ を判定し、
Content-Type レスポンスヘッダーを返す。Webファイル・画像・フォント・文書・動画・音声・圧縮ファイルの拡張子を多数認識する
- パスの安全対策として、
PATH_MAX 以上のパス拒否、.. ベースのパストラバーサル防止、すべてのリクエストパスへの www/ プレフィックス付与、O_NOFOLLOW_ANY による symlink を含むパスの拒否を適用している
- slowloris 系 DoS 緩和のため、読み取り間隔が 10秒 を超えるか、ヘッダー全体の受信に 10 秒を超えた場合は接続を閉じて
408 Request Timeout を返す
- HTTP/1.1 リクエストでは
Host: ヘッダーが必要で、Host の値自体は実際には使用しないが、RFC 9112 Section 3.2 に従ってヘッダーの存在を要求する
config.S ではドキュメントルート、エラーページディレクトリ、デフォルトファイル、受信タイムアウト、PUT の速度・サイズ制限、最大同時プロセス数などを調整できる
- Linux や他の Unix に移植するには、syscall 呼び出しレジスタと
svc、エラー返却方式、fork()、SO_NOSIGPIPE、O_NOFOLLOW_ANY、renameatx_np()、構造体レイアウト、Mach-O 再配置構文、signal handling などを修正する必要がある
1件のコメント
Hacker Newsのコメント
実際にアセンブリ、特にマクロアセンブラで大きなプログラムを書いてみると、より冗長なだけで、高水準プログラミングと本質的にはそれほど変わらないとすぐにわかる
結局のところ、プロシージャやマクロで抽象化を作ることに慣れれば十分で、アセンブリを効果的に読むことのほうが、書くことよりはるかに難しい場合が多い
strlenはCでもRustでもAssemblyでも、ほかの言語でも、結局は文字列を走査してNULLバイトを探す。CPUが正確に何をどの順序で行うのかをそのまま展開して書くので、むしろほかの言語より直感的に感じることさえある本当に美しく、よくできたプロジェクトだ。ほかのコメントの流れで言えば、こういうプロジェクトは自分にとってMinecraftのマップに近い
巨大で驚くようなマップもあれば、小さなサバイバルマップもあるし、友人たちと自分のためだけにローカルで開くマップもある。商業的に大規模を狙うサーバーもある。AIのおかげで、サーバーに家を建てたり新しい道を設計したりすることはとても簡単になったが、その世界で生まれる価値は、そのサーバー本来の目的と、家や道をさらに増やすことに実際に意味があるかどうかにかかっている
商業サーバーがより速く成長し、より多くの家や道路を持てるのは素晴らしいが、アートプロジェクトが生み出す愛着とは比べものにならない
いまでも誰かがこういうことを手で直接やろうとしていると知って、なんだか心が温かくなった。自分だけじゃなかった
似たようなプロジェクトがあれば見てみたいし、自分だけじゃないとわかってうれしい。ほとんどのプログラマは、数週間か数か月でもアセンブリを学んでみれば、CPUとコンパイル言語がどう動くのかに対する神秘感がかなり薄れると思う
面白いプロジェクトだ。x86 Linux向けにもっとミニマルなバージョンを作ってあって、どんなものか見たければここにある: https://github.com/jcalvinowens/asmhttpd
自分のREADMEにあなたのリポジトリへのリンクを追加しても大丈夫か気になっている
あの偽のO'Reilly本の表紙は本当に最高だ
あまり意味のある比較ではないかもしれないけれど、フル機能のWebサーバーと比べて性能がどのくらいなのか気になる。毎秒最大リクエスト数のような指標を見てみたい
ymawkyは接続ごとに
forkする構造なので、nginxやApacheのような本番運用向けサーバーが使う方式より本質的に遅い。nginxはイベント駆動I/Oのkqueue/epollを使って、リクエストごとにプロセスをforkするオーバーヘッドなしに何千もの同時接続を処理できる。Apacheはスレッドプールを使って、リクエストごとに新しく生成せず複数の接続を処理するほかのWebサーバーと真正面から比較すると、たいていは接続ごとにforkすることとイベントループ/スレッドプールの違いを測るだけで、アセンブリとはほとんど関係がない
同じように接続ごとにforkするサーバーをCで書いたものと比べるなら、スループットはほぼ同じだと思う。このモデルのボトルネックは実際のコードではなく
fork()そのものだからだ。毎秒リクエスト数より、バイナリサイズや起動時間のほうに影響が出る可能性が高い。それでも実際にベンチマークしてみたら面白そうだよくできている。自分もRISC-Vで似たような、でももっと小さいプロジェクトを進めているが、これは素晴らしい
このバイブコーディングの世界が向かう方向にあえて逆らいたくて、もう一度挑戦している感覚を得たくて、WebAssemblyソフトウェアレンダラーを書こうとしている
終わらせられるかはわからないし、無茶だし、有用だとも言えない。それでも本当に気分がいい
元の作者の成果を祝福したい
完成後はそれでゲームを作っているが、いまは挑戦そのものの面白さがなくなってしまって、そちらはあまり進んでいない。でも問題ない、楽しかったから。バイブコーディングでやっていたら、ああいう楽しさや満足感は得られなかったはずだ
LLMが純粋な8088アセンブラでCGA向けレンダラーをどれだけうまく書けるのか見たくて、やらせてみたら、一発でかなりまともなデモを作ってきた。プロンプトにはEliteの宇宙船のベクターを入れておいた
https://imgur.com/a/Dy5rUku
自分の最初のアセンブリプロジェクトのひとつは、100% x86アセンブリで書いたCGIスクリプトだった
完全なWebサーバーのほうがたしかにもっと印象的ではある。それでも初心者なら、まずApacheのCGIと
mod_cgiを調べてみることを勧めたいCGIサポートは数週間前から考えてはいたけれど、まだちゃんと掘り下げてはいない。どこかホスティングされている場所があるなら見てみたいし、あとで取り組むときのよい参考資料になりそうだ
私たちはAIに移行しつつあって、コードを書いて頭を悩ませることをやめつつあるのに、ここではアセンブリでWebサーバーを書いている
身が引き締まる思いがする