diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2016-04-05 00:48:46 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2016-04-05 00:48:46 +0900 |
commit | 28602c83ac43224b555157739842bd9167fb67b8 (patch) | |
tree | 0f3eb4ce787a66cab3dfd8d860bafd2296f68641 | |
parent | 492cb5aec30cbb253932f54d549f07610a2ed037 (diff) | |
download | poe-28602c83ac43224b555157739842bd9167fb67b8.tar.gz |
実行時間の計測に対応
-rw-r--r-- | backend/src/run_result.rs | 9 | ||||
-rw-r--r-- | config.json | 28 | ||||
-rw-r--r-- | frontend/app/snippet-detail.component.ts | 2 | ||||
-rw-r--r-- | frontend/app/snippet.service.ts | 1 | ||||
-rw-r--r-- | sandbox/child.c | 3 | ||||
-rw-r--r-- | sandbox/main.c | 29 |
6 files changed, 61 insertions, 11 deletions
diff --git a/backend/src/run_result.rs b/backend/src/run_result.rs index 697b8fa..2deb2e0 100644 --- a/backend/src/run_result.rs +++ b/backend/src/run_result.rs @@ -13,6 +13,7 @@ use std::process::Output; struct RunResultMetadata { pub exit: i32, pub result: i32, + pub elapsed: u64, pub message: String, pub truncated: bool, } @@ -28,6 +29,7 @@ pub fn open_render(snip: &Snippet, comp: &Compiler) -> Json { let meta: RunResultMetadata = json::decode(&encoded).unwrap(); map.insert("exit".to_string(), meta.exit.to_json()); map.insert("result".to_string(), meta.result.to_json()); + map.insert("elapsed".to_string(), meta.elapsed.to_json()); map.insert("message".to_string(), meta.message.to_json()); map.insert("truncated".to_string(), meta.truncated.to_json()); map.insert("output".to_string(), read_output_str(&snip, &comp).to_json()); @@ -80,17 +82,18 @@ pub fn parse_and_save(snip: &Snippet, comp: &Compiler, output: Output) -> Result let output_limit = 65536; if output.status.success() { - if output.stderr.len() < 8 { + if output.stderr.len() < 16 { return Err(PoeError::from("failed sandbox (result)")); } - let (metavec, msgvec) = output.stderr.split_at(8); + let (metavec, msgvec) = output.stderr.split_at(16); let mut rdr = Cursor::new(metavec); let reason = rdr.read_i32::<LittleEndian>().unwrap(); let exit = rdr.read_i32::<LittleEndian>().unwrap(); + let elapsed = rdr.read_u64::<LittleEndian>().unwrap(); let msg_str = String::from_utf8_lossy(&msgvec); let trunc = output.stdout.len() > output_limit; - let meta = RunResultMetadata { exit: exit, result: reason, message: msg_str.into_owned(), truncated: trunc }; + let meta = RunResultMetadata { exit: exit, result: reason, message: msg_str.into_owned(), truncated: trunc, elapsed: elapsed }; let mut meta_file = fs::File::create(format!("{}/results/{}.json", &snip.basedir(), &comp.id))?; meta_file.write(json::encode(&meta).unwrap().as_bytes())?; diff --git a/config.json b/config.json index 7dc40b1..fb75a7e 100644 --- a/config.json +++ b/config.json @@ -24,6 +24,34 @@ "{}" ] }, + "ruby-2.2.3": { + "version": "ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]", + "commandline": [ + "/opt/bin/ruby", + "{}" + ] + }, + "ruby-2.2.2": { + "version": "ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]", + "commandline": [ + "/opt/bin/ruby", + "{}" + ] + }, + "ruby-2.2.1": { + "version": "ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]", + "commandline": [ + "/opt/bin/ruby", + "{}" + ] + }, + "ruby-2.2.0": { + "version": "ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-linux]", + "commandline": [ + "/opt/bin/ruby", + "{}" + ] + }, "ruby-2.1.10": { "version": "ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux]", "commandline": [ diff --git a/frontend/app/snippet-detail.component.ts b/frontend/app/snippet-detail.component.ts index f9ddae6..a80107a 100644 --- a/frontend/app/snippet-detail.component.ts +++ b/frontend/app/snippet-detail.component.ts @@ -9,7 +9,7 @@ import {EditingData, EditingDataService} from "./editing-data.service"; <div class="result-item panel" *ngFor="#r of snippet.results.slice().reverse(); #i = index" [ngClass]="{'panel-success': isSuccess(r), 'panel-failure': isFailure(r), 'panel-running': isRunning(r), 'result-item-collapsed': isHiddenIdx(i)}"> - <div class="panel-heading" (click)="toggleHiddenIdx(i)">{{r.compiler.id}} ({{r.compiler.version}})</div> + <div class="panel-heading" (click)="toggleHiddenIdx(i)">{{r.compiler.id}} ({{r.compiler.version}}) {{r.elapsed / 1000}}ms</div> <div class="panel-body container"> <pre><code [innerHTML]="formatted_output(r)"></code></pre> </div> diff --git a/frontend/app/snippet.service.ts b/frontend/app/snippet.service.ts index dd1278e..ad687f9 100644 --- a/frontend/app/snippet.service.ts +++ b/frontend/app/snippet.service.ts @@ -13,6 +13,7 @@ export class Result { public compiler: Compiler, public result: number, public exit: number, + public elapsed: number, public message: string, public output: any[], public _: any, diff --git a/sandbox/child.c b/sandbox/child.c index a521a4a..caa6fc5 100644 --- a/sandbox/child.c +++ b/sandbox/child.c @@ -49,8 +49,7 @@ noreturn void poe_child_do(struct playground *pg, if (poe_seccomp_init()) bug("seccomp init failed"); - if (close(child_fd[0]) || close(child_fd[1])) - bug("close child_fds failed"); + // child_fd は exec によって close される if (dup2(stdout_fd[1], STDOUT_FILENO) < 0 || close(stdout_fd[0]) || close(stdout_fd[1])) bug("dup2/close stdout failed"); if (dup2(stderr_fd[1], STDERR_FILENO) < 0 || close(stderr_fd[0]) || close(stderr_fd[1])) diff --git a/sandbox/main.c b/sandbox/main.c index d539a63..8043929 100644 --- a/sandbox/main.c +++ b/sandbox/main.c @@ -1,9 +1,21 @@ #include "sandbox.h" +static struct timespec start_timespec = { 0 }; + static noreturn void finish(enum poe_exit_reason reason, int status, const char *fmt, ...) { + if (!start_timespec.tv_sec && !start_timespec.tv_nsec) + bug("start_timespec not set?"); + struct timespec end_timespec; + if (clock_gettime(CLOCK_MONOTONIC, &end_timespec)) + bug("clock_gettime failed"); + uint64_t elapsed = + (uint64_t)(end_timespec.tv_sec - start_timespec.tv_sec) * 1000 * 1000 + + (end_timespec.tv_nsec - start_timespec.tv_nsec) / 1000; + int xx[] = { reason, status }; fwrite(xx, sizeof(int), 2, stderr); + fwrite(&elapsed, sizeof(uint64_t), 1, stderr); if (fmt) { va_list args; va_start(args, fmt); @@ -103,6 +115,9 @@ int main(int argc, char *argv[]) bug("unreachable"); } + if (close(stdout_fd[1]) || close(stderr_fd[1]) || close(child_fd[1])) + bug("close child write pipe failed"); + int epoll_fd = epoll_create1(0); if (epoll_fd < 0) bug("epoll_create1 failed"); @@ -124,7 +139,7 @@ int main(int argc, char *argv[]) if (timerfd_settime(timer_fd, 0, &(struct itimerspec) { .it_value.tv_sec = POE_TIME_LIMIT }, NULL)) bug("timerfd_settime failed"); -#define ADD(_fd__) do if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, _fd__, &(struct epoll_event) { .data.fd = _fd__, .events = EPOLLIN })) \ +#define ADD(_fd__) do if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, _fd__, &(struct epoll_event) { .data.fd = _fd__, .events = EPOLLRDHUP|EPOLLIN })) \ bug("EPOLL_CTL_ADD failed"); while (0) ADD(signal_fd); ADD(timer_fd); @@ -150,10 +165,6 @@ int main(int argc, char *argv[]) for (int i = 0; i < n; i++) { struct epoll_event *ev = &events[i]; - if (ev->events & EPOLLERR) { - // fd closed - close(ev->data.fd); - } if (ev->events & EPOLLIN) { if (ev->data.fd == stdout_fd[0]) { handle_stdout(ev->data.fd, STDOUT_FILENO); @@ -173,6 +184,14 @@ int main(int argc, char *argv[]) die("child err: %s", strndupa(buf, nx)); } } + if (ev->events & EPOLLERR || ev->events & EPOLLHUP || ev->events & EPOLLRDHUP) { + // fd closed + close(ev->data.fd); + if (ev->data.fd == child_fd[0]) + // exec succeeded + if (clock_gettime(CLOCK_MONOTONIC, &start_timespec)) + bug("clock_gettime failed"); + } } } |