Aizu Online JudgeやAtcoderなどのオンラインジャッジシステムを作る時のメモ.
オンラインジャッジシステムを作る上で必要なことは
- プログラムに入力を与えて期待する出力かどうか判定する
- リソースを均等にする
細かく言えばたくさんありますが,こんな感じだと思います.
今までは一つ目しか満たしてなかった(とてもよくない
とりあえず安全に実行できる環境にするべきだろうということでdockerを導入した.
その上で,幾つかハマりどころが合ったので残しておく.
要件
- 入力と出力は数MBになりえる
- 実行時間制限を指定できる.
- メモリ使用量を制限できる.
- プロセス数を制限できる.
- 生成されるファイルサイズを制限できる(今回は無し
- cpu使用率を均等にする(今回は無し
- 使用したメモリ量を取得できる.
- 実行時間を取得できる.
- プロセスのステータスを取得できる.
### 仕様
- サーバーの性能的に,同時に実行できるプログラムは1つ
プログラム
プログラムは以下.
require 'docker'
image = 'gcc:latest'
tmp_path = File.expand_path('../tmp', __FILE__)
memory = 128
options = {
'Image': image,
'Tty': true,
'HostConfig': {
'Binds': [ tmp_path + ":/tmp" ],
'Memory': memory * 1024 * 1024,
'PidsLimit': 10
},
'WorkingDir': '/tmp'
}
container = Docker::Container.create(options)
container.start
p container.exec(["sh", "-c", "g++ source.cpp"])
p container.exec(["sh", "-c", "/usr/bin/time -f \"%M KB\" ./a.out > result.log"])
container.delete(force: true)
createに渡すオプションは基本的に ここの構造をrubyで実現すればいい.
'Tty' を trueにしないといい感じに動かなかった.
'Memory'はByte指定なので適当に掛け算してMBにした.
'Binds'はマウントの指定.
** あと,createしただけではstartされないので注意**
execの渡し方は基本的には配列だけど,まとめた長いコマンドとかはこんな感じにするといい.
終了後にdeleteするようにしておく.