次期ゆかりすたーの開発に着手

nebulaゆかり検索支援ツール「ゆかりすたー METEOR」の次期世代、「ゆかりすたー NEBULA」の開発に着手しました。

AutoResetEvent と CountdownEvent の速度差比較

スレッド間で繰り返し同期を取る必要がある場合、今までは AutoResetEvent を使っていたが、こちらの記事に「CountdownEvent の方が、オーバーヘッドが小さい」と書かれていた。

そうだったのか!

昔どこかのサンプルコードを見て AutoResetEvent を使っていたけど、他の手段との比較検討はしたことなかったなぁと思い、実際に CountdownEvent と処理速度を比べてみた。

処理速度の結論

処理速度について結論から言うと、AutoResetEvent より CountdownEvent のほうが速い。

そもそも

同期に使えるクラスはたくさんあり、MS 公式にまとめられている。そのうち、
  • AutoResetEvent……スレッドをシグナル状態になるまで待機させる。単一の待ちスレッドが解放された後、自動的にリセットされる。
  • CountdownEvent……スレッドをカウントダウンが 0 になるまで待機させる。複数のスレッドからのシグナルで 1 つ以上のスレッドのブロックを解除できる。
とあるので、待機させる側と待機する側のスレッド数は、AutoResetEvent は 1 対 1、CountdownEvent は複数対複数、ということになる。

また、AutoResetEvent はスレッド解放後に自動的にリセットされる(何もしなくても再び待機させられる)ので、セットし忘れてスレッドがスルーしてしまうバグや、セットのタイミングでブロックできないケースが発生するバグの軽減につながり、安心感は高い。

速度比較

機能的な違いは横に置いておいて、処理速度のみに注目して比較。コードは GitHub に上げておいた

メインスレッドとサブスレッドでそれぞれブロックし合うこと 500 万回(メインとサブがそれぞれブロックするので同期回数は 1,000 万回)、その所要時間を計測した。

result こちらの PC 環境で、.NET 5 の自己完結型リリースビルドで実行したところ、所要時間は
  • AutoResetEvent:22,031 ミリ秒
  • CountdownEvent:578 ミリ秒
となり、CountdownEvent のほうが 40 倍近く速いという結果になった。

まとめ

同期回数 1,000 万回で 20 秒程度の差が出たので、100 万回でも秒単位の差が出ることになる。短時間で 100 万回レベルの同期を行う場合は、CountdownEvent を選択する方が良いと思う。

自分のプロジェクトだとそこまで頻繁に同期するわけではなく(数分間で 1 万回程度、つまり 20 ミリ秒程度の差異)、速度差は誤差程度なので、安心感のある AutoResetEvent を使い続けるかもしれない。

ニコカラメーカーシリーズがコンテンツツリーランキング 2020 で 39 位入賞

39ニコカラメーカー 2 および初代ニコカラメーカーが、ニコニコ動画のコンテンツツリーランキング(親作品ランキング)2020 で 39 位に入賞することができました。

ありがとうございます!



ゆかり Blazor WebAssembly デモについて

ybdカラオケ動画をブラウザ上でリクエストをするためツール「ゆかり」をゆーふうりんさんが開発してくれているが、これを Blazor WebAssembly 化したらどうなるか、ということでゆかり Blazor WebAssembly デモを作ってみている。

このデモの目的は 2 つある。
  1. Blazor WebAssembly の体験(開発者側 & ユーザー側)
  2. ゆかりシンプルモードのイメージアイディア出し

開発側の体験

1 つめの目的については、「開発側の体験」と「ユーザー側の体験」の両方を含む。

開発者にとって Blazor WebAssembly は、ウェブサイトないしは SPA(ウェブのアプリ化)を C# で構築できるフレームワーク。正式リリースは 2020 年 5 月なのでまだ 1 年も経っていない。画期的だけど歴史は浅いフレームワークがどれほど実用的に使えるか、を確認したかった。

2 ヶ月ほど開発しての印象は「かなり良い」。

いくら開発言語が C# とはいえ、デスクトップアプリの開発とは構造が全く違うため、最初は戸惑いもあったというか、今も新しいことをやる度に勉強の日々だ。しかしやはり、慣れ親しんだ C# で開発できるというメリットは大きい。async/await も使えるし。

特に、統合開発環境である Visual Studio でいきなりデバッグできるというのは非常に大きいメリットだと思う。PHP も XDebug をインストールしたりいろいろ設定すれば VS Code でデバッグできるようになるらしい。が、F5 キーを押すだけで、ブレークポイント張りから構造化された変数ウォッチ表示まで何でもできる Blazor WebAssembly のお手軽さにはかなわない。

デスクトップアプリの開発と比べてしまうと「あれも足りないこれも足りない」状態ではあるが(WPF 使えないし)、PHP だと心折れる私でも「Blazor ならいいか」と思える程度には恵まれた環境となっている。

ユーザー側の体験

ユーザーにとっては Blazor WebAssembly かどうか自体はどうでも良いことだが、「キビキビ動く」というのは大きなメリットだと思う。

通常の Web ページは当然ながらサーバーにアクセスしてからの表示だが、Blazor WebAssembly では多くの部分をサーバーと通信せずにブラウザ側だけで完結する(しかもブラウザ内の動作はバイナリコードなので速い)。

search例えばこのデモでは、検索ページにアクセスしてもサーバーとは一切通信せず、ブラウザ側だけでページを描画する。このため、他のページから検索ページへの遷移は一瞬である。

検索ボタンをクリックして検索結果を取得する段階になって初めて、サーバーと通信して結果を得る。

検索結果の表示においても、結果のデータのみをサーバーから取得するだけで、表示自体はブラウザ側で行うので、通信量は最小化されて通信時間が短縮されるし、表示に要する時間も短い。

欠点としては、初回アクセス時にプログラムをダウンロードする形になるため、初回アクセスに時間がかかる点が挙げられる。しかし、何度もページ遷移するような使い方であれば、初回に時間がかかったとしても、その後キビキビ動くほうが、トータルの満足度は向上するのではと思う。

シンプルモードのイメージアイディア

ゆかりは高機能なので、初心者には使いこなすのが難しいのではないかという懸念が以前に出て、初心者向けのシンプルモードも使えるようにすると良いのではないかという発案があった。

とはいえ、具体的にどうすればいいのかという詰めは行われていないので、このデモでイメージアイディアとして作ってみた。

例えば、
  • 動画サムネイル表示:同じ曲でも複数の動画がある場合などに選択の目安になる
  • 検索ページのシンプル化:基本的にはキーワード入力欄が 1 つあるだけ
  • 検索結果ページのタブ切替:検索対象や結果の並び順をワンクリックで切り替えられる
  • ユーザー登録:予約時の名前入力が不要になる、自分の履歴を閲覧できる
  • 選曲・予約に関係の無い機能のそぎ落とし
などを行っている。

よさげなイメージがあったら、本家ゆかりで実現してもらえると嬉しい。

技術的キーワード

このデモで使用している主要技術は以下のような感じ。
  • Blazor WebAssembly (client-side Blazor / WASM) + ASP.NET Core hosted
  • Entity Framework Core + SQLite
  • JSON Web Token (JWT / トークン認証) + AuthorizeView
  • Server-Sent Events (SSE) + EventSource
  • C# 9.0 + nullable
  • REST API
  • ローカルストレージ (localStorage / Web Storage)
  • JavaScript (JS) 相互運用

GitHub

GitHub の README.md と Wiki の違い&使い分け

GitHub のリポジトリにドキュメントを入れる場合、大きく分けて
  • README.md(および必要に応じてその他のドキュメント)をリポジトリに直接配置
  • Wiki を使う
の 2 つのやり方があるが、基本的な機能(Markdown で書けて、GitHub サイト上での表示・編集が可能で、変更履歴も管理される)が同じだけに、どう使い分ければ良いのかというハテナが出て来たので、調べてみた。

機能的な違い

README.md と Wiki は基本的な機能は同じであるものの、確認できた範囲では以下のような違いがあった。

README.mdWiki
記述方法の簡単変更×
ページ一覧の自動作成×
サイドバー×
フッター×
ページの階層化×
変更履歴管理リポジトリで管理
(全体+ファイル別)
ファイル別のみ

根本的には「README.md はリポジトリそのものの 1 ファイルにすぎない」という位置づけになっていて、ドキュメントに特化した Wiki との違いが生じているということだと思う。

「記述方法の簡単変更」というのは、「最初は Markdown で書いていたけど、途中で Textile に切り替えたくなった」という場合に、簡単に変更できるかという観点。

EditmodeWiki の場合、Web 上での編集時に Edit mode を選べるため簡単に変更できる。

README.md の場合は、いったん README.md を削除してから新たに README.textile を作成すれば変更は可能(Code ページできちんとフォーマットして表示される)だが、Wiki と比べると一手間余計にかかる。

「ページ一覧の自動作成」は、Wiki の場合、特に何もしなくても、Wiki の右側に「Pages」という欄が表示されるようになる。逆に、これを消すことはできず、強制表示となる。

「サイドバー」「フッター」については、Wiki の場合、「_Sidebar」「_Footer」というページを作ることにより、常に Wiki の右側・下側にそのコンテンツを表示できる。

README.md の場合は、試しに _Sidebar.md _Footer.md というファイルをリポジトリに配置してみたが、README.md 表示の際にこれらのファイルは表示されなかった。

以上のように、Wiki にはドキュメントに特化したお手軽機能が備わっている。

一方で残念なのは、Wiki はページの階層化ができない点。ページ作成時に「A/B」のような命名をしてみても階層化されなかった。

README.md の場合はリポジトリそのものなので、リポジトリにフォルダーを作って新たな *.md(なり他のフォーマットのドキュメントなり)を配置すれば、ドキュメントも階層化できる。

「変更履歴管理」については、README.md はリポジトリそのものなので、リポジトリの変更履歴を見れば内容は一目瞭然。ドキュメントファイルを新規作成したり削除した場合も、リポジトリの変更履歴で確認できる。

Wiki の場合は変更履歴管理がページごとになっているので、それぞれのページの変更履歴は確認できるが、そもそもファイルが増えたり減ったりしたことを分かりやすく確認する手段は無い模様。

使い分け

機能的な違いを踏まえた上で、README.md(+リポジトリ内ドキュメント)と Wiki をどのように使い分けるか?

正直なところ、決定的な方法は思いつかない。

1 ページで済む簡単なドキュメントならば、README.md だけで事足りるのは間違いない。

ではファイルが増えてきたら Wiki かというと、個人的にはそうでもないかなと思う。理由は、Wiki だとデザインが変更できないから。ファイルが増えるような本格的なドキュメントということであれば、Markdown お仕着せのデザインではなく、自分なりのデザインにしたい。

となると、HTML でちゃんとドキュメントを作ってリポジトリで管理、ということになる。README.md はごく簡単にして、詳しくは HTML ドキュメントをご覧ください、という誘導。

つまり、README.md(+リポジトリ内ドキュメント)陣営オンリーになり、Wiki の出番は無い。

ただ、HTML ドキュメントの欠点は、GitHub サイト上で表示されないこと。http://htmlpreview.github.io/ で表示するか(現時点で CSS は反映されない)、あるいはリポジトリをいったんダウンロードしてもらうという手間が発生する。

その点 Wiki(でもリポジトリ上の *.md でもいいけど)はお手軽で良い。しかし、デザインを変更できないという他にも、ソフトウェア配布時にローカルで読めないという欠点もある。ネットに繋がっていないとドキュメントが読めないというのは困るシチュエーションがあるし、GitHub の都合で URL が変更されたりしたらリンク切れになってしまう。また、Wiki には「リンク先を別タブで開く」といった基本的な機能が備わっていなかったりする。

というわけで、暫定方針としては
  • 簡単なドキュメント……README.md
  • 本格的なドキュメント……HTML ドキュメントをリポジトリで管理
  • Wiki は使わない
としようと思うが、課題はある、といった感じ。

他の人はどうしているか

使い分けを明確に示しているサイトが意外と無いのだが、
というような事例はあった。

カンパのお願い
Amazon でお買い物の際は、下記で検索して頂けたら幸いです。
記事検索
最新コメント
月別アーカイブ
  • ライブドアブログ