Meiryo’s blog

やってみて詰まったことを備忘録として残すブログ

【C#】出力の高速化について調べて使ってみた

競技プログラミングのことを調べていたら
Console.WriteLineはそのまま使うと遅いらしいってこと、
そしてそれを高速化する方法があるとのことを下記記事で知りました。

qiita.com
「出力の高速化」のとこですね。
記事に記載されているコードが下記になります。

var sw = new StreamWriter(Console.OpenStandardOutput()){AutoFlush = false};
Console.SetOut(sw);
/*何らかの出力処理*/
Console.Out.Flush();

この3行のコードなのですが、 ・・・なにしてるかさっぱりわかりませんでした。
で調べたら割と時間かかったのでそれをまとめていきます。

①Console.OpenStandardOutputメソッド

引数に突っ込まれているこのメソッド、何をしているのだろうか
まずは公式ドキュメントを読んでみることに。

標準出力ストリームを取得します。

とのことなので標準出力ストリームを取ってきているようです。
それをコンストラクタに渡して出力先を作成してるんですね。

ちなみに標準出力ストリームの意味はまだあんまりわかっていません。
ここを見てとりあえずコンソールだと思ってます。

②AutoFlushの設定

なんか設定をfalseにしましたね。
また公式ドキュメントを見てみます。

StreamWriter が呼び出されるたびに、Write(Char) によって基になるストリームに
対するバッファーをフラッシュするかどうかを示す値を取得または設定します。

・・・あ?
フラッシュ・・・? なんだフラッシュって。
なんか前にもこれ詰まったことある気がするぞ。
多分溜め込んで一気に出力するとかそんな感じがするけど
調べてみよう。

「「フラッシュする」とは?」(1) Java Solution − @IT

サービス終了のお知らせ
上記の2つのサイトを読んでみるとやっぱそうですね。
AutoFlushをプロパティをfalseにしたことで即出力じゃなく、
溜め込んでからFlush(またはClose)メソッドが実行されたら
出力になった感じです。

③SetOutメソッド

①で作った出力先をここで設定しているようです。
Console.Writeメソッドでファイルに出力する - .NET Tips (VB.NET,C#...)

④何らかの出力処理

なんらかの出力処理ってなに・・・?
これはWriteメソッドで良いようです。(②で紹介した1つめのサイトで気づく)
f:id:meimaru:20190730193022p:plain デバッグしてみた結果ですがAutoFlushプロパティがfalseになってるので
Flushメソッドが実行されるまで出力されないのが確認できました。
f:id:meimaru:20190730195221p:plain Flushメソッドが実行されるとコンソール画面に文字がされあれ文字化けぇ!?

⑤【未解決】文字コードの設定

日本語文字化けしますね。
これが未解決なのですが相手の環境の文字コードを取得する方法がわからない・・・
相手の環境の文字コードがわかってるんだったらそいつを設定してやりゃ済む話なのですが
わからない場合ってどうすればいいんだろ。

なにに困ってるかを具体的に言うと競技プログラミングのサイト(AtCoder)で
これを使う予定なのですがサイトの環境で設定されている文字コードがわからないので
文字コードを設定できないんですよね。
なんか自動で取得できる方法あるんすかね?

テストしてみた

⑤が未解決ですがAtCoderでは出力する文字って英語か数字だけな気がしたので
とりあえずこのまま使ってみることにしました。
適当な問題を解いてみる。
A - DDCC型文字列

提出したコードはこれです
https://atcoder.jp/contests/ddcc2017-qual/submissions/6608986

無事通りました!
f:id:meimaru:20190730201542p:plain

本当に早くなるのかはわかりませんが、とりあえずこれを使って行こうと思います。