前に環境構築についての記事を書いたのですが、初学者向けにパッと見て分かるようにフローチャートにしました。
Google ドライブ 図形描画のファイルはこちらです。コメントを付けることができます。
会社が 4K ディスプレーなのもあって、家でプログラミングしてたら画面が窮屈に感じてきてうちも 4K ディスプレーを導入しました。
特に Elm の標準のフォーマットが密度低いのでフル HD だと不便だったのが最後の引き金でした。
4K かつ HDR にしました。
KEIAN 28インチ4K対応LEDモニター KWIN28 ゲーミングモニター
4K で High DPI 設定による高精細は言わずもがな HDR も綺麗ですね。
綺麗なんだけど Windows で HDR 出力をオンにしたときの SDR(今までのダイナミックレンジを表すレトロニム)コンテンツが白くかすんでしまって Windows で HDR オンにするのは時期尚早な感じがします。
PS4 をせっかく Pro 買ったのに今まで full HD の SDR でしか出力してなくもったいなかったのがやっともったいなくなくなり、Windows がいまいちでもとりあえず満足です。
HDMI にバージョンがあることを知らず PS4 Pro から 4K 60Hz が出ず後悔しそうでしたが、ディスプレーの HDMI 入力端子によってバージョン 1.4 と 2.0 が違うらしく挿し直したらちゃんと出力してくれました よかった。
ディスプレー買って初めて輝点があったのでちょっと凹んだんですが、グレー一色表示とかしなければ意外とめだたなくてよかったです。 でもやっぱり今度から輝点黒点保証付けて買おうかな。
……
…………
と、これだけでは終わらず右下のディスプレーも新しく買ってて、こっちはフル HD だけど Adobe RGB カバー率 99% のカラーキャリブレーションディスプレーです。
10bit カラーでもあります。
デジカメで Adobe RGB で撮ってましたがこれまで sRGB でしか見れてなく、見れないものを画像編集しててモヤモヤしてたのが、やっと本当の色を見ることができます。
特に緑の鮮やかさに差が大きいらしいのでわざとそういうの撮って比較したいですね。
カラーキャリブレーションの機能はこれ単体ではできなくカラーセンサーがまた高いのだけどそれは先の話ということで……
4K かつ Adobe RGB にすればよかったじゃんという意見はごもっともなんだけど14万円とかして用途別に2台買う方がやすいんですよね……
この記事は Haskell Advent Calendar 2019 の6日目の記事です。
postgresql-pure は Haskell の PostgreSQL ドライバー(クライアントライブラリー)で次のような目標で開発しました。
簡単に使用方法を説明します。
下記のようなテーブルがあるとします。
CREATE TABLE person ( id serial PRIMARY KEY, name varchar(255) NOT NULL ); INSERT INTO person (name) VALUES ('Ada');
このとき ghci で下記のように実行できます。
> :set -XOverloadedStrings > :set -XFlexibleContexts > :set -XDataKinds > :set -XTypeFamilies > :set -XTypeApplications > > import Database.PostgreSQL.Pure > import Data.Default.Class (def) > import Data.Int (Int32) > import Data.ByteString (ByteString) > import Data.Tuple.Only (Only (Only)) > import Data.Tuple.List.Only () > import Data.Tuple.Homotuple.Only () > > conn <- connect def > preparedStatementProcedure = parse "" "SELECT id, name FROM person WHERE id = $1" Nothing > portalProcedure <- bind @_ @2 @_ @_ "" BinaryFormat BinaryFormat (parameters conn) (const $ fail "") (Only (1 :: Int32)) preparedStatementProcedure > executedProcedure = execute @_ @_ @(Int32, ByteString) 0 (const $ fail "") portalProcedure > ((_, _, e, _), _) <- sync conn executedProcedure > records e [(1,"Ada")]
重要な部分を抽出すると parse
、bind
、execute
の順に呼びだし、最後に sync
でサーバーに送信します。parse
・bind
・execute
は入出力のない関数であり、リクエストのビルダーと対応するレスポンスのパーサーを構築しています。そしてそのビルダーとパーサーを sync
が使用して送受信を行ないます。bind
がモナド値を返すようになっているのは失敗する可能性があるためで、型は MonadFail m => m a
となっており IO a
ではありません。
型適用が所々に明記されていますが、これは ghci で実行しているので結果の使用部分からの推論ができないためで、実際のコードではほとんどの場合で型適用の明記は必要なくなります。
postgresql-pure では、タプルによる要素数の不一致を型検査で検出するインターフェース Database.PostgreSQL.Pure
(上記の例)と、しないインターフェース Database.PostgreSQL.Pure.List
と、HDBC 互換インターフェース Database.HDBC.PostgreSQL.Pure
の3つを提供しています。
高速化に寄与した技術を説明します。
まずは Haskell 一般に関連するものについての技術です。
送信と受信のたびに byte string を確保することを避けました。約 3 kB 以上のメモリーを確保すると暗黙のグローバルロックがかかります1。送受信のたびに確保するのをやめ、代わりにバッファとして確保した領域を何度も再利用するようにしました。手動によるメモリー管理のために bytestring パッケージの Data.ByteString.Internal.mallocByteString
と network パッケージの Network.Socket.sendBuf
と recvBuf
を使用しました。
mallocByteString :: Int -> IO (ForeignPtr a) sendBuf :: Socket -> Ptr Word8 -> Int -> IO Int recvBuf :: Socket -> Ptr Word8 -> Int -> IO Int
接続時に mallocByteString
で2つのバッファを確保します。送信するメッセージは Data.ByteString.Builder.Extra.BufferWriter
によって構築し、受信するメッセージは Data.Attoparsec.parseWith
でパースします。
ShortByteString
を使用するLISP のシンボルのような短い文字列には ShortByteString
を使用しましょう。ShortByteString
は ByteString
よりもオーバーヘッドが少なく、またヒープフラグメンテーションを引き起こしません。ShortByteString
には length
や index
のような簡単な操作だけが提供され複雑な操作は提供されていません。このライブラリーではサーバーのパラメーターを保存するために使用しました。
次に PostgreSQL 固有の効率化について説明します。
PostgreSQL プロトコルには2つの問い合わせ方法があります。ひとつは簡易問い合わせで、もうひとつは拡張問い合わせです。簡易問い合わせには最小限の機能しかなくプリペアドステートメントやバイナリーフォーマット、結果を1レコードずつフェッチすることなどはサポートされていないので、このライブラリーでは拡張問い合わせを採用しました。
PostgreSQL プロトコルは TCP の上で動作し、複数のメッセージは結合してひとつの TCP ペイロードに格納することができます。
下記の図はメッセージをひとつずつ送信した場合を表しています。
メッセージを結合した場合は下記のようになります。
メッセージを結合することで送受信するデータ量を減らし、またシステムコールの回数も減らすことができます。
下記のような単純な定数値のみの問い合わせを秒間何回問い合わせられるかを計測しました。定数値を使用したのはサーバーがボトルネックにならないためです。
SELECT 2147483647 :: int4, 9223372036854775807 :: int8, 1234567890.0123456789 :: numeric, 0.015625 :: float4, 0.00024414062 :: float8, 'hello' :: varchar, 'hello' :: text, '\xDEADBEEF' :: bytea, '1000-01-01 00:00:00.000001' :: timestamp, '2000-01-01 00:00:00.000001+14:30' :: timestamptz, '0001-01-01' :: date, '23:00:00' :: time, true :: bool;
環境は下記の通りです。
計測結果を下に示します。縦軸は秒間リクエスト数で横軸はスレッド数です。
このライブラリーも postgres-wire も約4スレッドまではほぼ同じパフォーマスです。それ以上になると postgres-wire が線形比例を下回っていくのに対し、このライブラリーはより線形に近くなっています。
(比較対象は開発途中でのベンチマークにおいておそかったものを除去しています。)
postgresql-pure は IIJ イノベーションインスティテュートの業務として作成されました。
Haskell の開発環境を構築する方法は何通りかあり、新しいツールが出ると「今はこれだ」とほめるブログも公開されますがそれが初学者を混乱させることがよくあります。
本記事ではビルドツールのインストールにしぼり、開発支援、例えば ghc-mod・haskell-ide-engine・hhp には言及しません。
いくつか典型的な構築方法を確認した後、新たに私が作成したツールを紹介しより初学者を混乱に落とし入れます。
Haskell 解説書史1の第1波から第3波までのデファクトスタンダードであった重鎮 Haskell Platform です。コンパイラー GHC とパッケージマネージャー Cabal、それにいくつかの準標準ライブラリーをまとめてインストールできるツールでこれをインストールするだけで入門書のコードはすぐ動くというようなものです。
現在では Windows 向けにのみ提供されています。Haskell Platform のページでは macOS 向けには下記で紹介する Stack がすすめられています。Linux 向けには Stack と、同じく下記で紹介する Ghcup またはディストリビューション付属のパッケージマネージャー(apt や yum など)がすすめられています。
前世紀、人々は依存地獄に苦しめられていました。その苦しみを取り除くために救世主がごとく現れたのが Stack でした。
依存地獄とは依存ライブラリーのバージョン解決時に遭遇する問題でこれを解決しなければビルドができません。例えば A と B というパッケージに依存していたとしましょう。A はまた C に依存し同じく B は C に依存していたとします。このとき、A が要求する C のバージョンと B が要求する C のバージョンが同じであれば何も問題はありません。問題があるのは同じでない場合です。A または B 自体のバージョンを下げるなどして C のバージョンが合うように調整しないといけません。
OK
- A
- depends C-1
- B
- depends C-1
Error
- A-3
- depends C-2
- B-1
- depends C-1
Resolve (e.g.)
- A-2
- depends C-1
- B-1
- depends C-1
Stack は、主要なライブラリーに関してこの問題が解決されたバージョンのセットとそれをビルドできる GHC バージョンをペアにしたものを resolver として管理し提供しました。
また、ライブラリーや GHC のインストールされる場所をグローバルではなく隔離された場所にすることで、1つのマシンに入っている別々のプロジェクトが別々のバージョンのライブラリーや GHC を利用することを容易にしました。当時の Cabal はそれができませんでした2。
これによって、ユーザーは resolver を指定することで依存地獄を見ることなくアプリケーション開発ができ、また複数プロジェクトの開発でわずらわされることがなくなりました。
Cabal は環境構築ツールではありませんが Stack と比較するという意味でここで紹介します。
Cabal は Haskell 標準のパッケージマネージャーで、Haskell Platform でインストールされますし、Stack も Cabal をラップして使用しています。
Stack が大躍進を遂げたことで、それまでライバルのいなかった Cabal にも変化が求められました。これまで Cabal のサブコマンドだった build などは v1-build とされ、新たに互換性のない v2-build が導入されました。v2-build では Stack の特徴の1つである「隔離してインストールする」機能が搭載されグローバルを汚染することがなくなりました(注:コメントを参照)3。build サブコマンドは v1-build の別名でしたが Cabal 3.0.0.0 でついに v2-build に変更されました。
この大幅改善によって一時は Stack に移行していたユーザーの一部は直接 Cabal を使うように戻ったようです。
世の中では Haskell 以外の言語も生まれ進化しています。その内の1つに Rust があります。Rust はコンパイラー rustc とパッケージマネージャー Cargo の管理のために Rustup を開発しました。
Rustup は指定したバージョンの rustc と cargo をインストールする機能と、rustc コマンドで実際に呼び出されるコンパイラーを切り替える機能のあるものです。これと同じものを GHC も導入し ghcup としました。これによって複数の GHC をインストールしそれを切り替えて使用することが簡単にできるようになりました。
Ghcup と Cabal の v2 をインストールし、Stack が提供するライブラリーバージョンのセットを Cabal から使うとほぼ Stack がやっていたことができるようになります。
私にとって Ghcup には1つ問題があり、それは Ghcup が sh 製であることです。私は Windows ユーザーで PowerShell を常用しています。これまでは Stack を使ってきていましたが、GHC を切り替える機能が欲しくなり同様の機能を持つ Ghcups を作りました。Ghcup と PowerShell(PS)のかばん語です。
実装の話をすると、Rustup や Ghcup は rustc や ghc をシンボリックリンクとして実際の実行ファイルを指すようにしていますが、Windows ではシンボリックリンクの生成は管理者権限を必要とするため使いたくありません4。Ghcups では環境変数 Path を編集することで実現することにしました。副効果として、その Path の編集は1つの PowerShell プロセスに閉じるため複数の PowerShell があるときに同時にそれぞれ別々のバージョンを指定することができるようになりました。欠点としては PowerShell を経由しない GUI アプリケーションに対しては影響を及ぼせません。
GHC と Cabal のインストールは現状 Chocolatey に依存しています。これは実装を省いてとりあえず動くものが欲しかったのでこうなっています。要求があれば非依存にするかもしれません。
私の私感ですが次のように選ぶのがよいかと思います。
Ghcups を使って環境構築し切り替えをするところまで説明します。
実行ポリシーを設定して管理者権限で PowerShell を起動します5。
powershell -ExecutionPolicy Bypass
PowerShell Gallery に公開しているので Install-Module
でインストールできます。
> Install-Module ghcups
インストールが終わると同じく管理者の PowerShell にて下記のように Chocolatey をインストールします。ユーザーの PowerShell で実行した場合は自動的に管理者権限の PowerShell が起動するようになっているのでユーザー権限でも構いません。
> Import-Module ghcups > Install-Choco Getting latest version of the Chocolatey package for download. Getting Chocolatey from https://chocolatey.org/api/v2/package/chocolatey/0.10.15. Downloading 7-Zip commandline tool prior to extraction. Extracting C:\Users\KAZUKI~1\AppData\Local\Temp\chocolatey\chocInstall\chocolatey.zip to C:\Users\KAZUKI~1\AppData\Local\Temp\chocolatey\chocInstall... Installing chocolatey on this machine We are setting up the Chocolatey package repository. The packages themselves go to 'D:\chocolatey\lib' (i.e. D:\chocolatey\lib\yourPackageName). A shim file for the command line goes to 'D:\chocolatey\bin' and points to an executable in 'D:\chocolatey\lib\yourPackageName'. Creating Chocolatey folders if they do not already exist. Chocolatey (choco.exe) is now ready. You can call choco from anywhere, command line or powershell by typing choco. Run choco /? for a list of functions. You may need to shut down and restart powershell and/or consoles first prior to using choco. Ensuring chocolatey commands are on the path Ensuring chocolatey.nupkg is in the lib folder
GHC と Cabal のインストールとその切り替えは下記のようにします。ユーザーの PowerShell にて下記のようにセットアップします。管理者権限でないことの確認をされますがそのまま実行して大丈夫ですので y を選択してください6。
> Import-Module ghcups > Install-Ghc 8.8.1 Chocolatey v0.10.15 Chocolatey detected you are not running from an elevated command shell (cmd/powershell). You may experience errors - many functions/packages require admin rights. Only advanced users should run choco w/out an elevated shell. When you open the command shell, you should ensure that you do so with "Run as Administrator" selected. If you are attempting to use Chocolatey in a non-administrator setting, you must select a different location other than the default install location. See https://chocolatey.org/install#non-administrative-install for details. Do you want to continue?([Y]es/[N]o): y Installing the following packages: ghc By installing you accept licenses for the packages. Progress: Downloading ghc 8.8.1... 100% ghc v8.8.1 [Approved] ghc package files install completed. Performing other installation steps. The package ghc wants to run 'chocolateyInstall.ps1'. Note: If you don't run this script, the installation will fail. Note: To confirm automatically next time, use '-y' or consider: choco feature enable -n allowGlobalConfirmation Do you want to run the script?([Y]es/[A]ll - yes to all/[N]o/[P]rint): a Downloading ghc 64 bit from 'https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-unknown-mingw32.tar.xz' Progress: 100% - Completed download of D:\chocolatey\lib\ghc.8.8.1\tmp\ghcInstall (377.31 MB). Download of ghcInstall (377.31 MB) completed. Hashes match. D:\chocolatey\lib\ghc.8.8.1\tmp\ghcInstall Extracting D:\chocolatey\lib\ghc.8.8.1\tmp\ghcInstall to D:\chocolatey\lib\ghc.8.8.1\tools... D:\chocolatey\lib\ghc.8.8.1\tools Extracting D:\chocolatey\lib\ghc.8.8.1\tools\ghcInstall~ to D:\chocolatey\lib\ghc.8.8.1\tools... D:\chocolatey\lib\ghc.8.8.1\tools PATH environment variable does not have D:\chocolatey\lib\ghc.8.8.1\tools\ghc-8.8.1\bin in it. Adding... Hiding shims for 'D:\chocolatey\lib\ghc.8.8.1\tools'. Environment Vars (like PATH) have changed. Close/reopen your shell to see the changes (or in powershell/cmd.exe just type `refreshenv`). The install of ghc was successful. Software installed to 'D:\chocolatey\lib\ghc.8.8.1\tools' Chocolatey installed 1/1 packages. See the log for details (D:\chocolatey\logs\chocolatey.log). > Install-Ghc 8.6.5 (省略) > Install-Cabal 3.0.0.0 (省略) > Set-Ghc 8.8.1 > ghc --version The Glorious Glasgow Haskell Compilation System, version 8.8.1 > Set-Ghc 8.6.5 > ghc --version The Glorious Glasgow Haskell Compilation System, version 8.6.5
Haskell ユーザーで PowerShell ユーザーの方がいればぜひ試してみてください7。
cabal-dev を使えばできた。↩
v2 は常用していないのでまちがっていればツッコミがほしい。↩
追記:ジャンクションなら管理者権限は必要なかった。↩
“Chocolatey detected you are not running from an elevated command shell (cmd/powershell).” の確認をしないオプションをご存じの方いれば教えてください。“Do you want to run the script?” の確認はしたいです。↩
Set-ExecutionPolicy
を使用してグローバルに制限を緩める方法がよく紹介されますがセキュリティの観点からこちらの方をすすめます。ショートカットをオプション付きで設定して作成するとよいです。↩
何人いるんだろう。↩
いろいろなソフトウェアがデフォルトで何でも C ドライブを使う。
C ドライブが手狭になってきたのでいくらかのデータを別ドライブに移行する方法をメモしておく。
Stack(Haskell)のリソースはユーザー環境変数 STACK_ROOT
の指すディレクトリーに保存される。デフォルト値は C:\sr である。パス長制限の問題があるので浅い場所がよい。D:\stack に変更した。
Stack によってインストールされる GHC や MSYS2 は LOCALAPPDATA
\Programs\stack にある。これは STACK_ROOT
\config.yaml に local-programs-path を記載すると変更できる。非 Windows 環境では STACK_ROOT
\programs らしいということもあり D:\stack\programs に変更した1。
STACK_ROOT
\config.yaml に記載する Non-project-specific config と STACK_ROOT
\global-project\stack.yaml に記載する Project-specific config は別物なので注意する。
75 GB ぐらいだった。
Chocolatey のリソースはシステム環境変数 ChocolateyInstall
の指すディレクトリーに保存される。D:\Chocolatey に変更した。choco.exe
は ChocolateyInstall
\bin にあるのでシステム環境変数の Path
に追加しておく2。
いくつかのパッケージの実行ファイルが保存される場所はユーザー環境変数 ChocolateyToolsLocation
によって示される。D:\tools に変更した。
Zenza Bronica S 系用接写リングの説明書(をスキャンしたものをプリントしたもの)を入手したので文字データに起こした。
この接写リングは4個(C-A C-B C-C C-D)で1組になっています 使用できるレンズも 40 mm~200 mm までと巾広く 標準レンズ使用の場合で等倍までの近接撮影ができます 4個の接写リングは撮影の目的に合わせ ご自由に組合せてご使用ください 別表は S2 型・C2 型カメラに 接写リングと交換レンズを組合せた場合の撮影倍率と露出倍数の関係を示します
(表)
● 被写体に近接するに従って フィルム面とレンズの距離は遠くなり 実際のレンズの明るさ(F値)は減少します 表中の露出倍数を参考にして露出時間を増加してください
● 接写には ブロニカ TTL 露光計の併用をおすすめいたします 露出倍率などに関係なく 指針を 0 に合わせるだけで 正しい露光が得られ 完全に遮光されたピントフードがついていますので映像は明瞭です