SamasungのU.2 SSDで遊ぶ

年末から年始にかけて、一部界隈では『例のSSD』という名前でSamsungエンタープライズ向けU.2 SSDが話題になりました。 なんとこのSSD、新品にも関わらず大変安価(2TBで1万円と少し)にもかかわらず、PCIe3.0x4接続によりそこそこの性能が出るというわけでオタクが大挙して購入したわけです。 私も例に漏れず購入し、さすがに家のマシンにU.2コネクタは付いていないのでPCIeに指すための変換アダプタも買いました。噂ではこの変換アダプタもAmazonで在庫切れになったとか。

というわけで、遊びがてらbtrfsでの性能を見てみたいと思います。

検証環境

今回の検証環境はこんな感じ

  • CPU: AMD Ryzen 3 PRO 4350G
  • Mem: DDR-2666 64GB
  • M/B: MSI A520M PRO-C DASH
  • Disk1: 例のSSD with PCIe3.0 x4
  • Disk2: WD Black SN750
  • Linux: 5.4.0-59

今回の計測ではM/BののPEGスロットに対してPCIe->U.2変換ボードを設置して実験しました。PCIe3.0x16の帯域幅を持っているのでU.2デバイスの実験も大丈夫でしょう。

ベンチマークツールとしてはfio 3.16を使います。ベンチマーク用の設定は次のブログ記事を参照しました。

LinuxでもCrystalDiskMarkぽいディスクベンチマークしたい - 動かざることバグの如し

計測結果の単位はすべてMB/sです。

計測の下準備

今回はbtrfsを使うので、デバイスそのものをbtrfsでフォーマットしておきます。

$ fdisk /dev/nvme0n1
# パーティション1を作成
$ mkfs.btrfs /dev/nvme0n1p1

今回の測定ではマウントオプションを

  • -o defaults, ssd
  • -o defaults, ssd, compress=lzo
  • -o defaults, ssd, compress=zstd

の3つで試しました。

計測結果

実際に計測した結果です。それぞれ計測回数は1回だけなので参考程度の数値ということで。

-o defaults, ssd -o defaults, ssd, compress=lzo -o defaults, ssd, compress=zstd
Seq Read [MB/s] 999.595 956.729 903.166
Seq Write [MB/s] 1085.48 1084.36 1082.12
Rand Read(bs=512k) [MB/s] 846.991 809.711 737.395
Rand Write(bs=512k) [MB/s] 1031.05 1059.17 1044.4
Rand Read(bs=4k) [MB/s] 40.267 40.405 37.637
Rand Write(bs=4k) [MB/s] 126.746 126.961 98.034
Rand Read(bs=4k,qd=32) [MB/s] 684.896 680.01 255.812
Rand Write(bs=4k, qd=32) [MB/s] 227.21 219.367 213.515

まあまあだいたいいい感じという気がしますが、公称値ほどの読み込み速度が出ていないのが気になるところ。 それにzstdでのランダム読み込み性能がかなり落ちているのが気になるところです。特にランダム読み込みqd=32での悪化は気になるところですが、他は大差なさそうですね。 zstd:3を選択している影響もあるかもしれません。圧縮率を犠牲にしてzstd:1あたりを指定するともう少し改善しそうな予感がします。*1

参考としてWesternDigital Black SN750のベンチマーク結果を貼っておきます。マウントオプションはdefault, ssd, compress=lzoです。

[2020-01-10 23:55更新]

WD Black SN750
Seq Read [MB/s] 862.315
Seq Write [MB/s] 1521.88
Rand Read(bs=512k) [MB/s] 712.832
Rand Write(bs=512k) [MB/s] 1383.35
Rand Read(bs=4k) [MB/s] 39.253
Rand Write(bs=4k) [MB/s] 116.586
Rand Read(bs=4k,qd=32) [MB/s] 694.881
Rand Write(bs=4k, qd=32) [MB/s] 223.291

書き込み性能に関しても例のSSDとcomparableかちょっとこちらのほうが良いように見えますね。そしてこちらでもシーケンシャル読み込みが1000MB/sを超えていないので、このあたりに何かしらの壁があるように見えます。 手元の環境起因だとは思いますが、この状態だと見当がつかない感じですね。 こうして見ると例のSSDの素性の良さが見えてきます。さすがに書き込みでは公称性能が低いので太刀打ちできませんが読み込み性能はほぼほぼ同等と言えるんじゃないでしょうか。

とりあえずは今のメインディスクと入れ替えて使っていこうと思います。なにせ容量が4倍なので。

YAMAHA RTX1200を使ってJPNEに接続するプロバイダでIPv4 over IPv6を実現する検証[draft]

TL; DR

  • フレッツ契約情報を見つけ出す
  • ZOOT NATIVEの契約をする
  • DS-Liteの設定をする

はじめに

新型コロナウイルス感染症の流行で在宅勤務が一般的になったためかPPPoE接続の速度が終わってきて何のために回線契約しているのかわからなくなってきた今日このごろ、 家にちょっといいルーターがあればIPv4 over IPv6によってプロバイダの網終端装置をバイパスして多少速度を稼ぎたくなるところです。 ところで我が家で契約しているSo-net光は、ある日を境にIPv6のVNEをインターネットマルチフィード(mfeed)から日本ネットワークイネイブラー(JPNE)に変更してしまいました。 これによってIPv4 over IPv6を実現するために利用するトンネリング技術がDS-LiteからMAP-Eに変わったことを意味します。 一方、我が家に存在するYAMAHA RTX1200はMAP-Eに対応していません。 *1

ということで、設備投資をしなければMAP-EによるIPv4 over IPv6が使えないということになりますが、 mfeedを経由するIPv6 IPoEサービスを提供するプロバイダを別途契約することでDS-LiteによるIPv4 over IPv6を実現できないものでしょうか。 そこで今回はインターリンクが提供しているZOOT NATIVEとSo-net光を同時に契約できないか試してみます

予備調査

ZOOT NATIVEがコラボ光との併用をユースケースとして想定しているのか調べてみると、次のヘルプページがヒットします。 光コラボレーション(ドコモ光など)でZOOT NATIVEは利用できますか?

ということで大手を振ってプロバイダを切り替えられることがわかりました。正確に言えば切り替えるわけではなく複数プロバイダと契約する状態になっているわけですが。

事前準備

ZOOT NATIVE申込みのためにはフレッツのお客様IDとアクセスキーが必要です。 so-netの場合は[接続サービスご利用状況]->[ご契約情報の詳細]とたどったページで確認することができます。 この2つの値をメモしておきましょう。 f:id:akahana_1:20200606224745p:plain 次に、v6プラスオプションに加入していないか確認します。もし確認していた場合はその場で解約しておきます。 解約してから実際にVNEからの払い戻しが停止されるまでは1日程度必要なため、もしプロバイダでv6プラス契約をしていた場合はここで少し待つ必要があります。 私の場合は、解約申込みをしてから1日後になぜか再度v6プラスが有効になり、その後すぐにv6プラスが解約されるという謎の現象が発生しました。 v6プラスを有効化していた場合はある程度ゆとりを持ったスケジュールにするのが良いと思われます。

これでso-netとの契約情報から必要なものを抜き出し、事前準備が整いました。

ZOOT NATIVEへの申込みと開通

ZOOT NATIVEに申し込むフォームで先程メモしたフレッツのお客様IDとアクセスキーを利用します。 また、ZOOT NATIVEの申込ではフレッツ光の回線契約タイプの記入が求められます。

契約タイプの特定には回線の最大速度、貸与機器の種別などを見ながらフレッツ光の公式HPのプラント見比べるのが良いでしょう。 私はONUのみの貸与で、GE-PON-ONUが貸与されていたことと集合住宅に居住しているのでフレッツ光ネクストマンション・ギガラインタイプとしました。 あとはフォームに従って手続きを進めていけばZOOT NATIVEの申し込み作業は完了です。

次に、DS-Liteの設定をしますが、これについてはYAMAHAページの記載のとおりに行えば、良いでしょう。 http://www.rtpro.yamaha.co.jp/RT/docs/ipip/index.html#setting9

設定を終えたあとにhttp://ipv6-test.comにアクセスすれば、IPv4アドレスがMF-native6-eとなっているはずです。 これでDS-Lite開通が終了しました。おめでとうございます。

ハマりどころ

DS-Liteの設定をしたあとは一度WANにつながってるインターフェイスを再起動してあげましょう。 再起動しない状態だと、フレッツ網から外に抜けられないIPv6アドレスがルーターに割り当てられたままになっている可能性があります。 下の画像は、so-netのv6プラスオプションを解約して、その後にZOOT NATIVEの契約が通った状態ので私のRTX 1200に広告されていたrouter-prefixのリストです。

f:id:akahana_1:20200606234433p:plain

かなり分かりづらいですが2408:~から始まるアドレスと2409:~から始まるアドレスと240b:~から始まるアドレスの3種類のアドレスが広告されていることがわかります。 この内、2409:から始まるものがmfeedによって広告されているrouter-prefixです。残りのふたつのプレフィックスはなにか。 まず、2408:~から始まるrouter-prefixはフレッツ網内で有効なIPv6アドレスを示します。よって、このアドレスを使ってインターネットに出ていくことはできません。 もう一つの、240b:から始まるrouter-prefixはJPNEから広告されているrouter-prefixですのでJPNEの終端に対して接続することはできますが、mfeedの終端に対して接続することができません。 この状態でIPIPトンネルをmfeedが管理するAFTRに向けて張ろうとすると、張ることはできるものの通信が行えないといった状況が発生します。 おそらく、2409:~以外のアドレスを使ってAFTRと通信しようとしているからです。 これは、v6プラスの割当を受けた後、それを解約してv6契約がない状態からmfeedの割当を受けた時に、それまでにもらっていたrouter-prefixが削除できていないと起こる事象です。 こうなれば、ルーター再起動なりLANインターフェースの再起動を行うことが求められるでしょう。

*1:正確に言えばMAP-Eによるトンネル接続は可能ですが、あっという間にIPマスカレード(NAT)のポートを使い切ってしまうため使えたものではありません

LuaLaTeXで簡単日中混植

この記事はTUT Advent Calendar 2019 13日目の記事です。 Advent Calendarがスカスカだと適当な日付を指定して記事を投げ込めるというのはとてもいいことですね。 よくはないが。 ちなみに 2015年から投稿しているので5年連続です。控えろ控えろ

皆さんはLaTeXを使っていますか? もちろん、理工系の大学に通っているみなさんは、レポートに論文にとLaTeXが大活躍していることと思います。

そんなLaTeX処理系の一つであるLuaLaTeXでは、従来のLaTeX処理系と異なって、フォントファイルの実態を取り扱えるようになっています *1

この事によって、従来のLaTeX文書では考えられなかった、複数のフォントファイルを用いた文章を極めて簡単に作成することができるようになっているので、 今回はその紹介として日本語フォントと中国語(簡体字)フォントの混植を実現する方法を取り上げます。 とても簡単ですよ!

(2019.12.17 追記) 具体的には、日本語文書内で簡体字が必要となった時に、適切な簡体字を出すための方法についてです。 書いているときは、この意味で十分伝わると思いこんでいましたが、あらゆるフォントが簡体字字形になったり、 あるいは簡体字であることが文中で明記されていない場合にも簡体字になるかのような曖昧性を抱えていたので、注記しておきます。

ちなみにこの記事は私も参加しているサークル『おるみん党』の冬のコミックマーケット宣伝のために執筆されています。 ここで言及したテクニックも登場する、おるみん党の機関誌『測点』Vol.2は冬のコミックマーケット(C97)4日目に南リー31bで頒布されます。 読書好きの皆さんに向けた叢書管理ツールEnju Leafを使った書誌情報管理や、Web Assemblyの紹介、中国メーカーから販売されているRISC-Vプロセッサ採用ボードの調査記録などの記事を取り揃えてお待ちしています。 頒布価格は500円。お誕生日席に配置されたので、かなりわかりやすいと思います。皆さん、冬の有明南展示場で会いましょう。

用意するもの

まずTeX Liveなどを使って、LuaTeXをインストールしてください。 今回のテストではTeX Live 2019にバンドルされているLuaTeX v1.11.2を使っています。

LuaTeX上でCJKフォントを扱う手法として、luatexjaチームが開発しているパッケージ群が利用できます。

とりあえず次のようなファイルを用意して、LuaTeXで正しくコンパイルできることを確認しましょう

\documentclass{ltjsarticle}
\usepackage{luatex85, lautexja}
\usepackage{bxjalipsum}

\begin{document}
\jalipsum{kusamakura}
\end{document}

正しくコンパイルできれば草枕の冒頭が書かれたPDFが生成されるはずです。 LuaTeXのコンパイルを初めて行うときは、フォントデータベース生成のためにコンパイルに時間がかかる点に気をつけてください。

フォントを取り扱う

次にシステムにインストールされているフォントを明示的に取り扱ってみます。 TeX Liveをインストールすると日本語標準フォントとしてIPAexフォントがバンドルされているので、 これを指定してPDFファイルを生成してみます。

\documentclass{ltjsarticle}
\usepackage{luatex85, lautexja}
\usepackage[ipaex]{luatexja-preset} % この行を追加
\usepackage{bxjalipsum}

\begin{document}
\jalipsum{kusamakura}
\end{document}

luatexja-presetパッケージによって、一般的なフォントであれば簡単にPDFに埋め込むことができます。

再度文書をコンパイルすれば、IPAexフォントが埋め込まれたPDFが生成されることでしょう。

簡単日中混植

それでは本題の日本語+中国語(簡体字)混植を試してみましょう。 luatexjaパッケージはluatexja-fontspecというパッケージを提供しています。 これはfontspecパッケージ(())をCJK向けに拡張したパッケージで、CJK向けに便利な機能がいくつか追加されています。 中でも便利なのがAltFontと呼ばれるフォント機能で、これを利用することで簡単に複数のフォントを切り替えて使うことができます。 例えば、公式ドキュメントからサンプルを引っ張ってくると

\jfontspec[
    AltFont={
       {Range="4E00-"67EF, Font=KozGoPr6N-Medium} ,
       {Range="6800-"9EFF, FakeBold=4},
       {Range="3040-"306F, Font=KozGoPr6N-Regular}
    }
][KozMinPr6N-Regular]

などとすれば、簡単に混植が実現できます。 この例だと、基本的には小塚明朝 Pr6Nを使いますが、Unicodeの文字範囲U+3040~U+306fでは小塚ゴシック Pr6N Regularを U+4E00からU+67EFの文字範囲では小塚ゴシック Pr6N MediumをU+6800からU+9EFFの文字範囲では小塚明朝を擬似ボールド体にして利用しています。

というわけで、これを真似すれば簡単に日本語と簡体字の混植ができそうです。 詳細について話すまでもなかったですね。というわけにはいかないのが現実です。

CJK統合漢字の罠

では次のようなTeXソースを用意してコンパイルしてみましょう。 ここでは、Windows環境を想定して、簡体字フォントにSimSunを使う例です。 お手持ちの環境に合わせて簡体字フォント部分を入れ替えてください。

\documentclass{ltjsarticle}
\usepackage{luatex85, luatexja}
\usepackage[ipaex]{luatexja-preset}

\begin{document}
{
\jfontspec[
    AltFont={
       {Range="4E00-"9FEF, Font=SimSun}, % Unicode CJK 統合漢字面をすべて簡体字に置き換える
    }
]{IPAexMincho}
简体字とは、中国およびシンガポールにおいて现在正字として采用している。从来よりも简略化した汉字。简化字とも呼ばれる。\footnote{\url{https://dic.nicovideo.jp/a/簡体字}
}
\end{document}

ここでは「简」「现」「采」「从」「汉」の5字が、簡体字字形として表示されることが期待される文字です。 他の文字は、和文字形として表示されていて、この部分だけ簡体字になってくれていれば、目的を達したと言えます。

コンパイルに成功するとブラウザ表示で簡体字になっている部分が、豆腐にならずに正しく簡体字字体で表示されていることがわかるでしょう。 例えばこんな感じです。

f:id:akahana_1:20191215185553j:plain

ところで問題は、簡体字で書かれていない箇所においても、字形が簡体字相当になっている問題です。 これはCJK統合漢字面全体を簡体字字形を利用したフォントに置き換えているからです。 では、簡体字部分だけに置き換え範囲を限定してすればよいというのが直感的ですが、ここに一つ問題があります。 というのも、簡体字が割り当てられているコードポイントは、UnicodeのCJK統合漢字面の上に広くまたがっており、特定の範囲を指定することで解決する問題ではないからです。 このあたりは明らかにUnicodeの不具合では?という気持ちになるのですが、規格として制定されているのであれば仕方がないので、なんとかしてこれを解決しなければなりません。

文字種を限定した解決策

CJK統合漢字面全体にまたがって、簡体字字形のものと和文字形のものが存在しているということは、文字範囲の指定という統一的な枠組みで二つの字形を混植することは難しく、都度都度アノテーションを行っていくしかないという結論になります。 というわけで解決策として取りうる方法の一つは AltFontのRangeキーに対応する値として字形を変更したい対象を列挙する となります。

先ほどの文書であれば

\documentclass{ltjsarticle}
\usepackage{luatex85, luatexja}
\usepackage[ipaex]{luatexja-preset}

\begin{document}
{
\jfontspec[
    AltFont={
       {Range={`简, `现, `从, `汉}, Font=SimSun}, % 簡体字で表示したい字形を列挙する
    }
]{IPAexMincho}
简体字とは、中国およびシンガポールにおいて现在正字として采用している。从来よりも简略化した汉字。简化字とも呼ばれる。\footnote{\url{https://dic.nicovideo.jp/a/簡体字}
}
\end{document}

f:id:akahana_1:20191215185728j:plain

これで簡体字で表示したい漢字のみが簡体字字形で、その他の漢字は和文字形で表示されるようになりました。 このように、和文字形と簡体字あるいは繁体字字形をLuaTeX上で混植させるには、多少気にしなればならないことがあるという紹介でした。

おまけ

ところでSource Han Sans CJKみたいにCJK多言語対応しているフォントを使えばいいのでは?と思われた人はいないでしょうか。 おそらく一番正しい解決法はそれです。 確認するためにluatexja-presetsourcehanオプションを指定して、コンパイルしてみましょう。

\documentclass{ltjsarticle}
\usepackage{luatex85, luatexja}
\usepackage[sourcehan]{luatexja-preset}

\begin{document}
简体字とは、中国およびシンガポールにおいて现在正字として采用している。从来よりも简略化した汉字。简化字とも呼ばれる。\footnote{\url{https://dic.nicovideo.jp/a/簡体字}
\end{document}

思った通りの出力になりましたね。というわけで、和文簡体字で異なるフォントを使いたいという希望がなければ、これが最も簡単な解決法です。

f:id:akahana_1:20191215185808j:plain

というわけで、このように和文中において特定の文字において簡体字を指定せざるを得ない状況が発生したときは

  1. Source Han CJKのような基本字形として和文字形を採用し、その他に簡体字のみの文字コードに対して正しく字形が存在してるフォントを使う
  2. luatexja-fontspecが提供するAltFontオプションを利用して、簡体字文字コード部分を対応する適切なフォントに置き換える

の選択肢を取ることが出来ます。

*1:今までのLaTeXはフォントファイルをそのまま取り扱っていませんでした

卒研を倒すための装備の整え方

タイトルはoverclaimなので話半分に読みましょう。

TL;DR

TeXを使って論文を書いているときに gitを使って管理したり、自動校正を導入したりする方法についてなんとなく話します。 具体的には

  • latexmkを使った自動ビルド
  • 自動校正ツールの使い方
  • gitにとりあえずファイルを放り込む

みたいな話です。

だいたい、このリポジトリの説明。

github.com

まえがき

皆さん!楽しい研究ライフを送っていますか? まあ、楽しいことも楽しくないこともあると思います。 私は死んでます。

さて、研究をしていてもそれで終わりでなくて最終的には何かしらの記録を残す必要があります。 そう、論文です。 論文を書くのは大変ですね。 ところでWordで論文を書いていて体裁がひどいことになったりしていませんか? あるいは、突然論文がすっ飛んでしまったり?

どうせなら、論文を書く環境をあらかじめ整えておきたいですよね。 ここではTeXにターゲットを絞って論文を倒すために考えられることを列挙します。 君も論文をやっていけ。

論文を書き始める前に

論文を書き始める前の設定が論文がうまく書けるかを決めると言っても過言ではないので、先にその話をします。 論文を書くときに予めフォーマットが定まっているのならそのフォーマットを使いましょう。 私が卒論を書いたときはTeXフォーマットが用意されていなかった記憶があり、キレながら適当なフォーマットをでっち上げた記憶があります。 フォーマットをでっち上げる必要がある人はフォントサイズとフォント指定、余白に気をつけましょう。 フォントサイズについては私が過去に書いた記事を読むといろいろわかります

装備を整える

論文を倒すために装備を整えましょう。戦いに出るために武器を持たぬ人間はいない。 同じように我々もこれから論文と戦うのだから、装備をと整えずして他に何をするのかという話になります。

環境設定

倒すも何も、その前にまずは環境設定をする必要があります。 私はLinuxWindowsが動くマシンしか持っておらず、Macではどのように設定するのかよくわかりません。 もしもTeXの環境をインストールしていない人がいる場合はTeX Liveをインストールしておくといいと思います。具体的にはTeX Live - TeX Wikiを参照してください。

ついでに使うエディタも決めてしまいましょう。 いっとき前ならばTeXWorksなりTeXShopなりの統合環境を使うのがデフォルトという感じでしたが、今はElectronベースのエディタを使ってプラグインで環境を整えるのがイケてるんじゃないでしょうか。 この記事ではElectronベースイケイケエディタとしてVisual Studio Codeを前提にします。 他のElectronベースイケイケエディタを使っている人は適宜読み替えてください。 具体的な設定はVisual Studio Code - TeX Wikiを参考にしてください。 LaTeX Workshopはイケてる拡張機能だと思います。普段Visual Studio Codeをあんまり使わないのでイケてる具合があんまり説明できないので、そこは他の人の記事を見てください。

あと、この記事では環境の前提条件をupLaTeXとします。LuaLaTeXとかだといくつか楽になるのかもしれませんが、あんまり詳しくないのでここでは説明しません。

ビルドを自動化する

ちまちまとファイルを書いてからコマンドを叩いて結果を確認したいか? そんなわけはないですね。

Visual Studio Code + LaTeX Workshopを使っていればファイル保存時に自動でビルドが走って嬉しい!!ですね。 LaTeX Workshopだと標準でlatexmkというlatexビルドのための便利ツールキットが使えるので、これを実際に動作するようにすれば、保存時にいい感じにビルドしてくれるはずです。 武器は装備しないと意味がないぜ!

upLaTeX用の一番簡単な設定はこれです。

あとは論文用ディレクトリ直下にlatexmkrcとして突っ込んでおけば、LaTeX Workshopがlatexmkを使ってコンパイルするときに自動参照してくれます。

gitを使って版を管理する

論文を書いているときにどこを書いているかわからなくなったり、あるいはいきなりファイルが失われたりする可能性があるので、事前にバックアップを十分取っておきたいですよね。 セーブスロットを用意して保存できると良い。 とりあえずDropboxみたいなオンラインストレージを使っているなら、Dropboxが管理するディレクトリの中に論文を用意して管理しましょう。

それとミスったときに後戻りできると嬉しいのでgitを使って管理しましょう。 Visual Studio Codeだとgitを直接叩く拡張機能がすでに同梱されているので、あとはgitの実行ファイルが存在していれば楽に使えます。 Visual Studio CodeでGitを利用する (1/3):特集:Visual Studio Code早分かりガイド - @ITなどを読むと具体的にどうすればいいかがわかります。

とりあえず手が一旦止まったらgitメニューを開いて、こんな感じで表示されている[+]マークをクリックしてファイルを登録して適当にメッセージを入力し[✔]をクリックしてセーブするといいです。

あとは適当なオンラインリポジトリサービスにPrivateでリポジトリを用意しておくと、もしものときにネットの向こうにファイルがあって便利です。

gitを使う時はこんな感じのファイルを作って.gitignoreという名前で論文と同じディレクトリに置いておくと、余計なファイルが表示されなくて心が落ち着きます。

怪しげな場所を潰す

文章をガリガリ書いているとなんだか文章がぐんにゃりしてくることがあります。 例えば今のこの文章もだいぶぐんにゃりしています。 こういうことになるのは防ぎたいところですが、それなりに難しいのである程度機械になんとかしてもらいましょう。

世の中には自動校正ツールと呼ばれるものがいくつかあってこれらを使うといい感じに文章の確認ができます。 代表的な自動校正ツールは

  • textlint
  • RedPen

のふたつがあります。 textlintはnodejs製でVisual Studio Code向けにプラグインも用意されていて便利でいいですね。 RedPenはJava製のアプリで別途サーバーを用意して実行するケースで強い気がします。

普段はRedPenを使うようにしています。多人数で原稿を書いてgitリポジトリと連携するときなんかはCIを使ってRedPenを回すほうが楽ちんな気がします。 nodejsと向き合っていける人は、textlintを使うのもいいでしょう。

RedPenだとXMLで設定を書くことができて次のような形でいくつか簡単なルールを設定できます。

<redpen-conf lang="ja" variant="zenkaku2">
  <validators>
    <validator name="SentenceLength">
      <property name="max_len" value="100" />
    </validator>
    <validator name="HankakuKana" />
    <validator name="JapaneseStyle" />
    <validator name="DoubleNegative" />
    <validator name="SectionLevel">
      <property name="max_num" value="3" />
    </validator>
    <validator name="KatakanaEndHyphen" />
    <validator name="GappedSection" />
    <validator name="ListLevel" />
  </validators>
</redpen-conf>

この設定だと

  • 句読点を,.にする
  • 文長を100文字に制限する
  • 半角カナを使わない
  • 文末のスタイルを統一する
  • 二重否定を禁止する
  • 節の最大深さを3までにする(chapter->section->subsectionまで)
  • カタカナ終わりの長音を抑止する
  • 空のセクションを作らない
  • 入れ子の箇条書きの深さ制限をする

といったことが実現できます。

具体的に何が設定できるかはRedPen 1.10 ドキュメントなどを見ると良いでしょう。 実際のエラーメッセージはこんな感じで表示されます。

autobuild-latex.tex:11: ValidationError[JapaneseStyle], 不正な日本語のスタイルを発見しました "あった" at line: それに加えて,各執筆者による原稿をいざ結合してひとつの冊子として組版しようとした時に,誤字・脱字があったり内容にいくらかの誤りが含まれているということになると大変です.
autobuild-latex.tex:15: ValidationError[JapaneseStyle], 不正な日本語のスタイルを発見しました "である" at line: そこで今回は,継続的インテグレーション(CI)サービスであるwerckerを用いてRedPenによる自動校正とupによる自動タイプセットに挑戦しました.
autobuild-latex.tex:77: ValidationError[JapaneseStyle], 不正な日本語のスタイルを発見しました "である" at line: 今回のタイプセットではディストリビューションのひとつであるTeXLiveに同梱されている,upを用います.
autobuild-latex.tex:81: ValidationError[JapaneseStyle], 不正な日本語のスタイルを発見しました "である" at line: ところで,DockerイメージのリポジトリであるDocker Hubを見るとどうやらTexLive2017に対応したDockerイメージは無いようです.
autobuild-latex.tex:138: ValidationError[JapaneseStyle], 不正な日本語のスタイルを発見しました "である" at line: ただし,バージョンによってはSource Han SerifおよびSource Han Sansが使えない可能性があるため,下記のコマンドによってバージョンが1.0以降であることを確認しておきます.

こうやって見るといくつかのエラーは本当にそうなってるのかわからないところがありますが、 最低限ヤバそうな部分を潰すのにこういうのは使えます。 真面目に怪しげな箇所を潰すときは指導教官に相談してください。

終わりに

本当はこれをAdCalの記事にする予定だったんですが、なんとなく記録がてら別の日に投稿することにしました。 実際このワークフローでうまくいったんですか?と聞かれるとなんとも言えないところですが、備えあれば憂いなしということで一つお願いします。 ちなみにDockerHubには私の作ったredpen-cliのDockerイメージとTeXLive + SourceHanFontsのDockerイメージが転がっているので大抵のことをやるときには便利だと思います。

逐次的に読めるシリアライズファイルを作る/読む

TUT Advent Calendar 2018 7日目の記事です。

雉も鳴かずば打たれまいとはよく言ったもので、煽りをしたばっかりに書かざるを得なくなったので書いています。 もう少し真面目なネタを書くべきですが、あいにくと年末の一大イベントに向けてスケジュールがカッツカツになっているので簡単なネタでお茶を濁します。 使える人には使えるし、知ってる人走っているちょっとした豆知識です。

TL;DR

  • データのリストからひとつずつデータを取り出して、ひとつごとにシリアライズすると、読み込みが先頭から逐次的に行える
  • その代わり、ランダムアクセスを実現するのは難しい(そのためにはすべてをオンメモリにするか,データベースを持ち込む必要がある)
  • 必要とするメモリ量が少なくなるのでメインメモリが多くないラップトップでもデータを眺めるだけなら出来る

あらまし

皆さんは100万件や1000万件、あるいはそれ以上の数のファイルを日常的に扱うことがあると思います。*1 しかし、あなたの手元のラップトップにはメモリが8GBしかありません! これではデータをすべてメモリに載せるのは厳しそうです……。 という状況で使える軽いテクニックの話です。

たとえばTwitterJSONが1000万件程度収められているケースを考えると、これは明らかに8GBのような貧弱なメモリに載りそうにはありません。 いま、単純におのおののデータを1回だけ眺めて必要な値を抜き出すというタスクを考えると

  1. データリストの先頭からひとつデータを取り出す
  2. 必要な処理を行う
  3. データリスト末端でなければ1.に戻る

を繰り返すだけでよく、すべてのデータをオンメモリとする必要はなくなります。

そこで、すべてのデータを一回ずつ取り出せる構造を考えたくなってきました。 最も単純な方法としては、JSONをstringfyした行データを用意して1行ずつ読み込んでいく方法があります。 たしかにこれは便利ですが、そのかわり生データがそのまま保存されるため、今度はストレージが爆発する可能性があって嬉しくないです。 なんらかの圧縮法(たとえばgzipやbzip)を使って、うまくデータを圧縮しながらかつ行単位で読み込みが出来るようにならないでしょうか……。

実はこれは簡単に実現できます。具体的には次のコードを実行すれば十分です。

import gzip
data = [ ... ] # JSONオブジェクトのリスト
with gzip.open("data.dump", "wb") as f:
     f.write(str(data).encode("UTF-8"))
     f.write("\n".encode("UTF-8"))

これで実現できました。 ほんとに?となるので試してみましょう。

適当なデータを用意して、いい感じにダンプしてみます。 今回はテストデータを適当な件数生成してくれるdatabasetestdata.comを使ってJSONデータを10000件程度生成してみます。

Database test data generator - Fill your database with random test data!

サンプルコードはこんな感じです。

import json
import bz2
import gzip
import string

with open("sample.json") as f:
    d = json.load(f)


# gzipで試す
with gzip.open("sample.gz", "wb") as f:
    for _ in d:
        f.write(json.dumps(_).encode("UTF-8"))
        f.write("\n".encode("UTF-8"))

with gzip.open("sample.gz") as f:
    result = []
    for i, _ in enumerate(f):
        s = "".join(filter(lambda x: x in string.printable, _.decode("UTF-8")))
        a = json.loads(s)
        result.append(a == d[i])

print("gzip result :", all(result))

# bzip2で試す
with bz2.BZ2File("sample.bz2", "wb") as f:
    for _ in d:
        f.write(json.dumps(_).encode("UTF-8"))
        f.write("\n".encode("UTF-8"))

with bz2.BZ2File("sample.bz2") as f:
    result = []
    for i, _ in enumerate(f):
        s = "".join(filter(lambda x: x in string.printable, _.decode("UTF-8")))
        a = json.loads(s)
        result.append(a == d[i])

print("bzip2 result :", all(result))

実行結果はこうなりました

akahana@stokuno $ python3 sample.py
gzip result : True
bzip2 result : True

うまくいきましたね。

ついでにファイルサイズを確認してみましょう。

akahana@stokuno $ du -h sample.*
216K    sample.bz2
396K    sample.gz
1.7M    sample.json

どうやらいい感じに削減できているようです。

この方法のメリットは - プログラム実行時のメモリ使用量が全展開に比べて抑えられる - 逐次読み出しのみが必要なタスクでは十分に動作する という点です。

一方でデメリットとして - データを読み出す際のコストが重たい。特に時間は通常の読み込みよりも大幅に要する - すべてのデータを一度に圧縮するケースに比べて効率が低い

の2点です。 データを読み出す際に毎回gzipなどのアルゴリズムを用いてデータの展開を行う必要があるため、必然的に生データに比べてデータ読み出しに必要な時間が増えます。 また、データ圧縮時に利用する辞書が各データごとに用意されるため、全体を1度で圧縮するケースに比べれば効率が低いと言えるでしょう。

一方で限られたユースケースでは強力に動作します。 特に、メモリの制約を持つ中であるデータをシーケンシャルに読んで特定のタスクを実行したい(たとえばデータフィルタリング)ということを大規模なデータに行う際には有効な手法だと思います。

使える機会がどれくらいあるか、わかりませんが。知っておくと便利な手法でしょう。

まとめ

今回のAdCalでは大規模なデータの逐次処理に関してメモリやストレージにある程度制約が設けられている環境で動作させる方法を紹介しました。これらの方法は、データに対する単純な処理をメモリ使用量を少なくした状態で行いたいというケースにおいて役立ちます。 そういうケースがいかほど存在するかは別にして、頭の片隅に置いておくといいでしょう。

*1:要出典

Twitterが死んだあとに

Twitterがコミュニケーションツール足り得た要因になったUserStreamが廃止された。 開発者としてTwitterアプリを作ったりしたわけではないため、特にTwitter社の開発方針に文句をつけたいところがないというわけではないものの それほどTwitter社と提供するサービスに対して真摯に向き合った記憶もないが、なんとなく自分の中で一つの時代が終わりゆくので記録としていくつか文章を残しておきたい。

開発者たちが何を思っているのかはmikutterの薄い本製作委員会刊『mikutterの薄い本Vol.14 レズと青い鳥』を読むのがよい。

mikutter-book.booth.pm

Twitterとの出会い

Twitterと出会ったのは2009年のことだった。 当時NHK BS2で放映されていた『ザ☆ネットスター!』という番組に取り上げられたことがきっかけで、なんとなく登録してみた記憶がある。 この番組もやたらと不思議な番組で、なぜサブカル批評で有名な人が出ていたりといろいろとあった番組だった。 よくこの時期にあの番組に出会って、以来思想の側に傾倒しなかったものだなあという気持ちがある。 それはさておいて、インターネット上に知り合いがいたわけでもなく、ただなんとなくこれから先にやってくるイケてるアプリらしいみたいなあやふやな動機で登録したんじゃないだろうか。

当時のことといえば、広瀬香美Twitterに登録したカドなんかで有名になっており、ヒウィッヒヒーとかいう謎のあだ名が付けられ、勝間和代などがつぶやいていたりしたような気がする。 もちろんインターネット上で知り合いを作ろうというような明確な目的があるわけでもなく、インターネット有名人みたいなのの発言を見たいわけでもなかったので、登録したままでそのまま数年間放置されることになった。 一時期、『なるほど4時じゃねーの』というbotだけを動かしていた記憶がある。

Twitterにハマりだす

Twitterに本格的にハマりだしたのは、2011年になってからのことだった。 この年には東日本大震災が発生し、その中でTwitterがもたらすリアルタイム性の高い情報というものが注目を集めた年だったと思う。 今でも活動しているTwitter速報アカウントの草分けといえる『特務機関NERV』が開設されたのも、この年だった気がする。

自分はといえば、ちょうと高等専門学校に入学した年であり、高専という学校の性格なのか同じ学科の同期もあるいはサークル活動における先輩もTwitterをやっていたことでTwitterにのめりこみだしたような記憶がある。 この頃、ようやくはじめての携帯電話としてSC-02Bを手に入れたこともあって、通学の間などにTwitterに貼り付くような人生が始まったわけである。 今考えるとこのときに引き返しておけば、こんなにこじれた人間が生まれることもなかったような気がする。 当時Android向けのTwitterクライアントといえばtwiccaが最もメジャーなクライアントだったこともあり、twiccaをインストールして使っていた。 のちに、複数アカウントを管理したいと思うまではtwiccaがメインクライアントだった。 そんなこんなで、ゆったりとTwitterをやっていたわけだが、そんな人間を本格的にTwitterに叩き落とすツールが現れる。

Windows向けTwitterクライアントアプリTweenである。

Windows向けTwitterクライアントの代表といっても過言ではないこのクライアントの特徴は、異常に詰め込まれた情報とUserStreamにあった。 1ツイートが1行に対応し、それらがUserStreamの力を借りて時にはとてつもない勢いでUIの上を滑っていく。 Tweenは自分にとってTwitterを物理身体によるリアルタイムコミュニケーションを代替するにたるサービスであると思わせるのに十分な機能を持っていた。 このツールとの出会いが完全にその後ずるずるとTwitterを続ける理由を生み出したと言える。 リアルタイムでTLが更新されていくこと、もっというと自分のツイートやリプライに対してリアルタイムで反応が返ってくることが認識できるというのは革命的だった。 そう、リアルタイムである。

この頃のTwitterを眺めてみると、「コミュニケーションはすなわちリズムゲームのようなものだ」とする説を唱えるツイートが流れていた。 自分はその見解に全く同意せざるを得ない。 コミュニケーションにはリズム感が大事で、テキストベースでそれを体現するには常時サーバーなりあるいは相手方とつながっている必要がある。 その点で見ればUserStreamは、コミュニケーションのリズム感を担保することのできる極めて強力なツールだった。 結果として、ツイートを投げたほんの数秒後にふぁぼが返ってくる、あるいは10秒もしないうちに空リプが返ってくるなどの多種多様なコミュニケーションがそこに生まれたわけである。

そしてTwitterにハマりいくつかのクライアントを乗り換えていった。 WindowsはTweenからTweenがオープンソース化をやめたタイミングでOpenTweenに行き、複数アカウントの管理をし始めたタイミングでTweetDeckに流れ着いた。 Linuxは最初の頃ツイタマなどを使っていた記憶がある。いつの間にやらこれもTweetDeckに流れ着いた。WebUIは一つの正義であるという気がする。 Androidはtwiccaからtwitcleやjanetterなど様々なクライアントを試したあとにYukari for Androidにたどり着き今もそれを使っている。 これらのクライアントはいずれもUserStreamに対応している(あるいはしていた)し、UserStreamなしのTwitterというのは考えがたいものだった。 情報を発信すると同時にリアルタイムチャットツールに瞬時に切り替わるTwitterが好きだった。

そして、UserStreamの死

リアルタイム性を持ったテキストベースのコミュニケーションに魅せられたが結果、テキストベースの会話をリアルタイムで行うbotについて研究したいなどと願うようになった。 結果として、高専の卒業研究はそのような形で行うことになった。このときもUserStreamに非常に助けられた記憶がある。 UserStreamに繋ぎっぱなしで放置しておけば、人々の会話を大量に収集することができる。これらは、研究の助けになった。

2011年以降、Twitterは急速にそのユーザー数を拡大していったはずである。記憶はそうなっているが現実の事態であるか定かでない。 その結果として、Twitterは徐々に公益性を帯びるようになってきた。最近だとSNSから発信されたフェイクニュースが世間を賑わせるようになっている。 冷静な議論には十分な情報と時間が必要だ。ところが、Twitterが備えた高いリアルタイム性と、140文字に制限された情報はそのような冷静さをいともたやすく失わせる。 また、Twitterの経営上の問題もある。彼らはもはやユーザーに対してリアルタイム性のあるコミュニケーションを提供するという選択肢は取れなくなった。 あるいは、元より求めていたものはリアルタイム性の高いコミュニケーションではないのかもしれないが、その点はあまり詳しく知らない。

そして、この夏にUserStreamというリアルタイム性はTwitterから失われた。

これによって、人々が発信した内容について吟味する猶予を持つことが今までよりも少しはできるようになるのかもしれない。 それはTwitterを人々がその日のことをつぶやくツールから言論プラットフォームとしての責任ある形に移行することを促すのだろう。 ただ、それでも、多くの人は未だに与えられた情報の一部しか見ることがないし、CJKにおける140文字という制限は情報を伝えきるには難しすぎる。 十分な情報を提供するために用意されたスレッド機能も多く使いこなされているとは言い難いように感じている。 マイクロブロギングサービスを謳うにしては、発信される情報があまりにも少なすぎるのだ。

Twitterはさえずるツールであったはずなのに、利用者が増え公共性を求められる機会が増えたことで言論プラットフォームへと移行しなければならない時期が来た。 あるいはUserStreamという体力が必要なツールを維持するだけの力を失い、制約されたアクセス環境と広告という藁にすがりつくしかなくなったのかもしれない。 いわば幼年期の終わりなのかもしれない。 しかし、Twitterがこれから迎える成年期が必ずしも実りをもたらすものであるとは、個人的にはあまり考えられない。 Twitterで発信可能な極めて制約された情報が深い議論を生み出すようなプラットフォームへの移行を生み出すとは思えないし、 短文広告プラットフォームとしてその生涯を閉じるのではないかと思っている。 それでも、Twitterに魅せられ、もっと言えばUserStreamというリアルタイム性を持ったコミュニケーションに魅せられた人間としては、Twitterが少しでも長くその力を持って生き続けることを願わずにはいられない。

リアルタイムコミュニケーション中毒の行く先

Twitterからリアルタイムにコミュニケーションを行う機能はもはや永遠に失われた。 TweetDeckが残っている?REST APIを異常な回数叩くことであたかも疑似リアルタイムを作り出しているが、通知欄の挙動などを見れば到底リアルタイムとは言い難いことがわかる。 幸いにしてか、Twitter然としたSNSプラットフォームを作成しようという試みは様々に行われていた。 個人的な記憶の最も最初にあるのはGNU SocialなどのOStatusを採用した一連のマイクロブログサービス群であり、いくつかに登録した記憶がある。 これらはUIがイケておらず、また日本人ユーザーの数もそれほど多くなかったためになんだかなあと感じたことを覚えている。

そして、2017年にはmastodonが脚光を浴びた。 mastodonのような後発のサービスはTwitterの悪いところを見てとり、それらを改良して出来上がっていることから利用感もいい。 また、WebSocketを使ってサーバーに繋ぐことができるのでリアルタイム性もある程度担保されていると言える。 これから、UserStreamのようなものを使いたいと願うのであればmastodonに移住するよりほかないのだろう。

Windowsラップトップでイヤホン接続/非接続で音量を切り替える

TL;DR

  • ラップトップの場合、初期設定ではイヤホン接続/非接続で音量設定が切り替わらないことがある
  • Realtek HD オーディオマネージャで設定するとイヤホン接続/非接続で音量設定が切り替えられるようになる
  • 具体的には、デバイス詳細設定からマルチストリームモードを選択すれば良い
続きを読む