-
Notifications
You must be signed in to change notification settings - Fork 3
[アイディア求む] rime 作り直し #9
Comments
今のコードは黒歴史感があるのでなんとかしたいですね……
そのとおりだと思います。
そうですね。
環境合わせって、コンパイラのバージョンとかでしょうか。確かに何かできるといいですね。
わたしは最近ほとんど作問をしていないので、どういう需要があるのか教えてもらえると助かります。
開発のしやすさも重要ですが、使いやすさも大事なのですよね。 |
手書きだとコメント書けた方がいいですね。とはいえ、rimeの設定ファイルに(テンプレに元から書いてあるコメント以外の)コメント書いてる人あまり見たことないですが
C++だとg++のバージョン問題の他にg++/clang派や、macのニセg++問題とかO2つけるのかとかstd=c++14をつけるのかとかいろいろあります。
リアクティブとか部分点ジャッジとかへの完全な対応とかですかね。これから新しい形式が続々生まれるかもしれないですし、それらへの対応もやりたいですね。あと割とコドフェが変なことをやっているのでそれらの調査もしたいです。
再配布手段が整備されているという点ではやはりGoは強いですね。pythonというかpipは最近 #6 に遭遇したのでちょっと信用してないところがありますが。
ガチの競プロ系だと少ないですが、初めて問題準備やってみる人とか業務で問題を準備する場合とかたまに windows 環境がいます。 |
一方でコンパイラを揃えるのはあんまり簡単な話ではないのですよね。
基本は今のようにローカルでコンパイル実行する方針にしつつ、コンパイルと実行をカスタマイズできるようにすることで他の実行形態の余地も残すくらいにしたほうがよさそうです。
リアクティブはテストデータの代わりにジャッジプログラムそのものを標準入出力に繋げる感じですよね。
Python はちゃんと設定すればそんなに問題はないはず。大体の Linux システムにはデフォルトで Python が入っているので、それは強みです。
問題の準備はけっこう人数を割くので、ユーザの環境やスキルもまちまちなんですよね。 |
あと、N年前に受け取ったリクエストとして、ユニットテストを走らせたいというのもありました。 いろんな需要に応えようとすると、じつは結局ほとんど汎用のビルドシステムを作らないといけないのでは、という気もしてきます。 |
コンパイラを揃える話
これによってそこそこ円満に解決できると良かったんですけど、私はatcoder標準イメージ・ICPC標準イメージなどを用意してdockerで走らせるのが本命で、native環境での実行は、諸事情でdockerを使いたくないときなどのために、driverでnative、docker等を選択できる形にしてもいいかなくらいに考えています。それは、あるスタッフの解答が他のスタッフのPCでコンパイルできないという問題は、各人の手元の環境に合わせた設定でコマンドを出し分けるだけでは解決できず、最低限の機能要件を満たしていないと考えているからです。 特に、C++で問題が深刻です。Macだとgccが portsのgcc、brewのgccだけどライブラリがclang系、標準のgccの振りをするclangの上にバージョンが古いという3系統があり、さらにlinux環境の存在やバージョン違いがあります。それぞれコンパイルできるコードがそこそこ違いますが、「インストールの簡単」な範囲では基本的にどれか1個しか1つの環境に用意できません。一方で、スタッフの方はそんなことお構いなく、手元では動くがほかでは動くかよくわからないコードを追加してきます。そのためかなりの頻度で問題が起き、これをそのコードを書いた本人の手で防げるようにすることは円滑な準備においては必要なことではないかと考えています。 rootが必要なことに関しては、そもそも各種処理系を準備する時点ですでに必要なのでそれほど大きなハードルとは考えていないです。 他の案としては、以下のようなものも検討しました。
|
リアクティブとか部分点ジャッジ
大雑把な理解としてはそれで良くて、実際そういう形で作ったものがあります。 が、入出力のとり方、終了時の判定の仕方などで幾つかvariantがあってKUPC(atcoder, aojで標準的)、testlib(codeforces?)、NEERC(java使ってるぽい)、それら全部に対応すると色々考えることがありますね。
これは2種類あって、与えられた部分テストケース集合ごとに点数がついていてその合計で点数をつけるものと、(atcoderでは半分隠し機能になっている)カスタムジャッジで点数を計算出力するものがあります。 一応機能としてあり、実際のコンテストでの使用例もあります。 さらにこれらの合わせ技とかになってくるともうどうしようかな、かなり困った感じです。 |
私はこの認識は正しくないと考えています。ビルドシステムに相当する部分がrimeのコードの中で大きな割合を占めているのは事実だと思いますが、rimeの本質的な部分はその外側の薄皮部分にある問題準備用のカスタムターゲットとカスタムタスクの集合ではないでしょうか。より詳しく言うと、カスタムターゲットとは問題・解答・テストセット・解答コード・入力生成器・入力検証器・出力検証器・…といったものであり、カスタムタスクとはテストケースビルド・解答ビルド・解答テスト・データデプロイといったものです。現行のrimeもそんな感じのアーキテクチャになっていたと思います。 可能であれば、汎用のビルド部分には注力せず、CMake, gyp等をラップして使い、その上に必要な機能をターゲット・タスクとして載せることがrimeの目指すべき方向性なのではないかと思います。 ユニットテストについてはコンテストのための問題準備という対象ドメインから外れているような気もするので個人的にはあまり気乗りはしませんが、需要があれば都度作るべきと考えています。 |
配布・非Linuxインストールの簡単さという観点だと以下の2択になるかと思います。
ただ、JAG, KUPC, UTPC, KLab それぞれで派生品ができて秘伝のソースを受け継いでいるという状態になり、本家のアップデートが反映できないといった不都合が出たのであまり好ましいとは考えていません。また、依存ライブラリなどを同梱しないと意味がないので肥大化するといった点もあまり良くなさそうです。
最近のイケてる言語ではapt, brew等でインストールできない場合でもcurlとシェルスクリプトを用いたワンライナーが用意されている場合が多いのでパッケージマネージャ等を入れるのにそんなに苦労しないことが多いです。例えば Rust (と同梱されているパッケージマネージャの cargo) は以下のコマンドで入れられます。
なので、インストールの簡単さはあまり心配していません。私としては、それよりもマルチプラットフォームでアプリをインストールが正しく終了し、実行できるかの方に懸念を持っています。 Python/Ruby/PHPといった言語は、多くの環境で標準的に用意されていますが、バージョンの違いがあったりします。スクリプト系言語では、うっかりバージョン依存コードを埋め込む、というかそれ以前に、重大であからさまなエラーがあってもそのパスを通らない限り全くわからないという特性があるので、多くの環境で動くコードなのかをチェックするのが難しいです。これはそれだけで多くの環境で動かすことに対する重大なリスクであるという認識です。Perlはバージョン違いの懸念はないと思いますが、全体的に用意されているライブラリが古そうという別の懸念があります。 バージョン違いという点では、Haskellのstackでは処理系も標準ライブラリも含めてインストール時にバージョンを強制できる点があって普通、パッケージマネージャでは処理系・標準ライブラリのバージョンまでは変更できず、そこで問題が出たりするのでこれも気をつけるべき点ではないかと思っています。また、Haskellで以前使われていたcabalのように他のインストール済みアプリの使っていたライブラリとバージョンが干渉して失敗するということがあったのでそこも気をつけたいですね。割とそのあたり壊れているパッケージマネージャは多そうです。 Rustは割と型がしっかりしているのでスクリプトと比べるとあからさまなエラーは埋め込みにくいです。しかし、多くの環境で使えるという観点でいうとパッケージ群の作りが荒いのか、問題が結構出そうなイメージがあります。以前PijulというVCSをインストールしようとしたとき、依存パッケージに問題がありmacじゃビルドできないという問題に当たりました。信頼性の高いパッケージに詳しい人等がいないと少しリスキーかもしれません。 Goは一応静的チェックがあり、巷の評判で何も考えなくてもマルチプラットフォームで動くようにできるとのことです。本当のところはどうなのでしょうか? ところでRustは流行りのbetter C系言語の中で型システムがちゃんとしている例として挙げただけで、私の最近のイチオシ言語はScalaです。しかしビルドシステムのsbtと内部で使っているパッケージマネージャのIvyにはアプリをインストールする機能がなさげなのと、JVM系は色々起動がめんどくさくて各自が秘伝の必殺ランチャースクリプトを作っている状況なので除外しました。 |
コンパイラを揃える話コンパイラが揃っていない問題でだいぶ苦労されたんだなということが伝わってきます。お疲れ様です……。 しかし依然としてわたしは Rime から Docker 経由でプログラムを起動するは筋が悪いと思っています。
これはユーザが使っているマシンで root 権限を持っていないのではないかという懸念ではありません。Rime の実行を root 権限で行う必要が出てくるのではという懸念です。Rime を初めて触る作問者が、クイックスタートガイドを見て、「Rime を走らせるには sudo rime build を実行します」と書いてあったら眉をひそめますよね(何も知らない人はそのまま実行するのでしょうけど)。 Docker の起動時だけ sudo するという手もなくはないですが、わたしはユーザの明示的な許可なしに sudo するプログラムを心の底から憎んでいるので、そういう挙動を見つけたらすぐアンインストールします。そういう人はそこそこいる気がします。 総じて、root 権限が必要になる操作を Rime から実行することはセキュリティ的にもユーザートラスト的にも問題が起こりうるので、なるべく避けたいです。
コンテナの作成は軽い操作ではありません。たとえば debian:latest イメージの作成・破棄には手元で 0.6 秒前後かかります:
なので、たとえば Java プログラムの場合に、解答を1つのテストケースに対して実行する度にコンテナを作成・破棄するという単純なアプローチは選択肢になりえません。複数のプログラム実行を一回のコンテナ実行にまとめる必要があり、複雑度がぐっと増すだろうという懸念があります。 対案さてここで元の話に戻りますが、コンパイラのバージョンを揃えたいのであれば、Rime から Docker を実行するのではなくて Docker から Rime を実行すればよいのではないですか?
このアプローチだと上記二点の問題は解決されます。 |
ああ、ちょっと細かい点ですが訂正します。 わたしも話を聞いた当初は Rime から Docker を起動する案はありかなと思ったのですが、上記のような懸念を考えたあとだと、Docker から Rime を起動するアプローチの方が問題の解き方として正しいないう考えに至りました。 ちなみにこの方法の場合、Rime 自体のバージョン違いさえ解決できますね。 |
さらに追記ですが、Rime を Docker イメージとして提供することにすればバイナリ配布の問題も解決できますね。ユーザビリティの観点からのプログラミング言語の制約はこれで無くなったのでは? |
ビルドシステムの話おそらく誤解があると思うのですが、CMake や gyp は最終的に Makefile など他のビルドシステムの設定ファイルを書き出し、ビルド自体は make などに任せる、メタビルドシステムです。 なので、
この辺の山口さんの意見とは一致していると思います(違ったらすみません)。 わたしが「ほとんど汎用のビルドシステムを作らないといけないのでは」と言っていたのは、リアクティブ、部分点、ユニットテストのようないろいろなロジックを自由にユーザに定義できるようにさせられるようにすると、ほとんど Make/CMake/... 並の自由度がコンフィグファイルに必要になってくるのでは、という懸念でした。まあ、なので、たとえばリアクティブのようなユースケースをサポートするときも、そのコード自体は Rime のバイナリの中に組み込んでしまうことにするのでしょうね。 |
おっしゃっている意味がわかりました。すっかり忘れていましたが、普通にlinuxのディストリだと初期状態ではログインするユーザーにはdockerを実行する権限がなかったんでしたね。各人にレクしてsudoなしで済むように適切に設定させるのはとても骨が折れそうです。
0.6sは耐えられないほど遅いかというと、そもそもJVMの起動時間が0.2~0.3sはかかることと比較して桁が違うわけではないので議論の余地があると思います。とはいえモッサリが体感できるレベルなのでcontainer側にrime実行サーバを用意するといったことが必要になりシステムがめんどくさくなるというのはその通りだと思います。
下のコマンドですが、以前はmacでboot2docker+virtualboxのようにremoteでdockerを動かす環境だと動作が怪しかったので考慮に入れていませんでした。今は巷の噂によると今はちゃんとローカルのファイルをmountできるらしいですし、確認しておきたいです。
システムはできるだけ単純な方がいいですし、rimeから直接dockerを弄る必要はなさそうですね
概ねそのとおりだと思います。ただ、柔軟性を高めるために自由度を高くするという方向性は、作った人が片手で数えられるくらいしかいない今のプラグインシステムと似た過ちの雰囲気を感じました。 |
|
rime を作り直しましょう。理由としては以下のようなものがあります。
作り直しに使う言語の候補としては以下があります。
The text was updated successfully, but these errors were encountered: