セカイノカタチ

世界のカタチを探求するブログ。関数型言語に興味があり、HaskellやScalaを勉強中。最近はカメラの話題も多め

Windows Terminalで起動時にUTF-8(chcp 65001)を指定する

メモです。

Windows Terminalが実用的になってきました。以前は日本語の表示が怪しい部分があって導入を見送っていたのですが、最新版を確認したら直っていたみたいなので十分使えると思われます。

Windowsでターミナルを使うに当たり必要なのが、初期ディレクトリの指定と、文字コードをUTF-8に変更することです。そのための小技を会得しました。

設定はターミナルのタブの右側に出るプルダウンから開きます。するとJSONが開くので編集します。

{
  "guid": "{GUIDを生成して入れる}",
  "name": "xxx project",
  "commandline": "cmd.exe /k chcp 65001",
  "hidden": false,
  "startingDirectory": "D:\\path\\to\\directory"
},

まず、このようにcmd.exeを起動する際に chcp を指定してしまいます。これでサクッとUTF-8になるので便利です。

"commandline": "cmd.exe /k chcp 65001",

次に起動時のディレクトリを指定しておきます。自分はプロジェクトのディレクトリで起動したいので指定します。プロジェクトごとに設定を追加していこうと思っています。

"startingDirectory": "D:\\path\\to\\directory"

あと、GUIDは適当に生成します(「GUID 生成」でググって生成しました)。

これで快適なターミナルライフが送れるはず。

terminal

プログラミングの EASY⇔HARD と Simple⇔Complex

プログラミング界隈では、よく「SimpleとEasy」について議論されることが多いですが、だいたい紛糾します。

それは何故かというと、そもそもSimpleとEasyは、対立軸ではないからです。

Easy(簡単)の対義語は、Hard(難しい)です。に対して、Simple(単純)の対義語は、Complex(複雑)です。

それぞれ機軸が違う概念を比較するのですから、まとまった議論に向かうはずが無いのです。

それは、「長い」と「重い」を比べるようなものですが、長いものは総じて重いことが多いため、ヘタに議論が成り立ってしまうあたりが厄介なのです。

プログラミングにおいても、単純で簡単なものというのは、数多く存在しますし、複雑なものは難しいことが多いので、ここらの議論がごっちゃになるわけです。

これらの機軸を整理して考えると、議論はよりスムーズで発展的なものになるのではないかと思います。

自分の意見としては、プログラミングとは、「世界の複雑さを難しさに変換して圧縮する営み」だと思っています。つまり、現実世界は膨大な量の複雑さで溢れているため、何とかしてこれを圧縮して扱いやすくする必要があるわけです。

複雑さとは、「要素と要素の絡み合いの度合い」と言うことができるので、単純化すると「複雑さ=情報量」ということになると思います。

情報量が少なければSimpleになり、情報量が多ければComplexになります。

そして、情報量が一定なら難しいプログラムほど、よりSimpleにすることができます。Easy⇔Hardというのは、情報の圧縮力です。

だから、「簡単に書けるプログラミング言語」とか、「プログラミング不要で誰でも書ける」なんていう製品は、情報圧縮力が低く、取り扱える情報量の限界が低いということになります。

これは、物理法則のようにシンプルな法則で、基本的にプログラミングという営みはこの法則から逃れることができません。

後は、自分が扱う情報量を見積もって、必要な圧縮力を選定すれば良いということになります。

現代のコンピューティングの世界では、簡単で単純な用途から、複雑で難しい用途まで、あらゆるユースケースに応じたプログラミング環境が揃っていますから。

余談

余談ですが、この情報圧縮の考え方は、プログラミングに限ったことではありません。物理学や数学だって難しくてシンプルな式でより多くの現実の減少にマッチするものが、より高い圧縮率を持っていると考えることができます。

なんなら、仏教の教えだって、簡潔に私たちの認知の真実を言い表していますが、理解するのは難しいです。

この世のすべての事柄が、扱う情報量と圧縮率で表せると思うと面白いですね。

最も良い見積もり手法は見積もりをしないことだ

qtamaki.hatenablog.com

以前に書いたエントリーですが、もう3年も経っていました。それから状況が変わったかというと、システム業界の状況はあまり変わっていないように見えます。ただ、SIerは増々勢いを失い、自社製品の開発に携わるエンジニアの割合が増えたように思えます。

自身も、この記事を書いた頃は受託開発を行っていましたが、今では自社プロダクトの開発に携わるようになりました。

自社開発だからって、工数見積がなくなるわけではなく、今でも見積もりの問題は多くのエンジニアを悩ませています。

てなわけで、Qiitaでこんな記事を見かけたので、触発されて見積もりについて少し書きたいと思います。

qiita.com

この記事では、自社プロダクトをアジャイルで開発するというシチュエーションが前提として、様々な技法で「見積もりを正確に行うこと」を目指しています。また「状況に変化があったらアップデートすること」も大切だと言っているのだと思います。

確かに、正攻法だとこんな感じになると思いますが、自分は不真面目なので、搦め手から攻めたいと思ってしまいがちです。

冒頭の記事では、見積もりの内容よりも「覚悟」が大事だと語りましたが、自社プロダクトのようなケースだと、もう少し粒度を小さくできるので、覚悟を決めるよりも見積もり自体をなくしてしまって、「できた時が完成」方式にしてしまうのがたったひとつの冴えたやりかたって奴です。

「そんなの無理だ」と思った方も多いかとは思いますが、見積もり自体無理ゲーなので、見積もりを無くすのとどっちが無理ゲーか?という比較をする価値は十分にあると思っています。

そしてそのために、

  • 作業単位をなるべく細かくする
  • 管理者がある程度の作業量とリスクを判断できるようにする
  • 結果で判断する
  • チーム全体のスループットを定量的に測る
  • できないものはできない(あきらめる)

などの方法を試してみるのはどうでしょうか?

見積もりを無くすことによるメリットはこんな感じです。

  • 見積もりにかかる時間がなくなる
  • 余計なバッファを積まなくて良くなる
  • 積んだバッファを無駄に消費しなくて良くなる(小さな予算消化!)
  • リスクの顕在化が早くなる
  • 結果に注目し、正しい評価ができるようになる

全体的に、開発がスピードアップし、スループットが上がります。

管理者の仕事は、経営陣や上司が要求してくる「見積もりしろ!」という圧力をはねつけることです。

自身のチームのパフォーマンスを最大化するために必要な措置をとるのがマネージャーの仕事なので、安易にパフォーマンスを悪化させる不見識に屈してしまうことが無いように頑張って戦いましょう。

現代のビジネスでは、全てがダイナミックに変化し続けるので、ここのタスクの計画や締切よりも、スループットや柔軟性を以って組織の価値を判断するようにしていきたいものです。

もちろん、中には締切がマストなタスクもあるので、その場合は締切の設定とともに、そこに入る内容を取捨選択しましょう。予算・品質・納期は、全てをいっぺんに揃えることはできません。特に納期が絶対であるならば、予算と品質で調整するしか無いのです。

  • 締切から逆算する
  • リスク評価を最速で行う
  • バックアッププランを可能な限り用意する
  • 人員配置や補給など、最善を尽くす

などの手を尽くして戦うしかないです。

ご武運を!

Battle

Playframework の Future の挙動について調べたら Action と Action.async の差異は無かった

表題の通り。調べたら色々興味深いのでメモとして残そうと思う。文章がぶっきらぼうなのは許して。

Playframework では、 Action と Action.async を切り替えることにより、 Future を利用したノンブロッキング処理を Controller 内部にで行うことができる。

Future は ExecutionContext を必要とし、通常は implicit な変数を定義して Controller 内部で暗黙的に引き渡す。

Playframework のドキュメントでは、 controller の implicit パラメーターでデフォルトの ExecutionContext を受け取る方法が紹介されている。

class Samples @Inject()(components: ControllerComponents)(implicit ec: ExecutionContext)
  extends AbstractController(components) {

https://www.playframework.com/documentation/2.7.x/ThreadPools

デフォルトで渡される、 ExecutionContext は、 Akka のディスパッチャとなっており、 application.conf によって設定することができる。デフォルトでは、 ForkJoinPool 方式のディスパッチャが選択されるようだ。

akka {
  actor {
    default-dispatcher {
      fork-join-executor {
        # Settings this to 1 instead of 3 seems to improve performance.
        parallelism-factor = 1.0

        # @richdougherty: Not sure why this is set below the Akka
        # default.
        parallelism-max = 24

        # Setting this to LIFO changes the fork-join-executor
        # to use a stack discipline for task scheduling. This usually
        # improves throughput at the cost of possibly increasing
        # latency and risking task starvation (which should be rare).
        task-peeking-mode = LIFO
      }
    }
  }
}

余談ではあるが、 ForkJoinPool は、処理が fork しながら細分化し、終了(join)しながら統合していくような処理に適しており、タスクはスタックに積み上げられていく(らしい)。 async タスクで使用される Future は、ネストして処理を重ねていくことが多いため、マッチングが良いのかもしれない。

しかし、 Playframework(Akka) のデフォルト ExecutionContext は、内部で BatchingExecutor という仕組みを用いて実装されており、単一のリクエストにおいては、同一の Thread にてバッチ的に実行される。そのため、 ThreadPool の実装や Future の実装戦略は、あまり意味がなく、デフォルトの環境において、 Action と Action.async の差異は無い

独自のECを定義することにより、 BatchingExecutor の動きもなくなり、普通に Future 毎に Thread が割り当てられるようになり、レスポンスタイムは向上する(手元の環境では20%程)。

Playframework のデフォルト戦略では、リクエストの内部を細かく Thread で分解しても、 Thread 切り替えのオーバーヘッドによりシステム全体の利用効率は上がらないという判断なのだろうか?しかし、その場合、 ForkJoinPool を使うメリットは恐らく無いので、この判断の根拠が知りたい。

それと、 BatchingExecutor 環境であっても、 scala.concurrent.blocking { ... } で処理を囲むことによって、 Thread が消費されるようになる。それでも、 Await っぽい動きではなく、タスクが別 Thread に分配されるようになるだけなので、これを使ってタスクの分散を図ることができる(けど、回りくどいので独自で ExecutionContext を定義すればいいじゃんと思う)。

Futureのネストについて

さらに余談となるが、

Future { Future { Future { ... }}}

のように、 Future がネストされる処理では、外側の Future が保持している Thread が無駄になるのでは?という懸念があり、確かめてみたところ、 Future がネストしていても Thread の消費には影響が無いことが分かった。 Future はコードブロックを内包したクラスのインスタンスに過ぎないため、内部に Thread (になりうるコードブロック)を持ったオブジェクトが再帰的に重なって構築されるだけ。 Thread のスケジューリングは EC によって Future 構造とは独立して行われる。

Thread が枯渇してしまうのは下記のような場合のみである。

Future { Await.result(Future { Await.result(Future { ... })})}

Future の中で、中身を Await で取り出そうとすると、 Thread がブロックされ消費されていくので、 ThreadPool に設定された Thread 数を使い切るとフリーズする。

Await を使わない限り、 Future のネストや大量使用についての心配はあまりしなくても良さそう。

サンプルコード。

import java.util.concurrent.Executors
import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService, Future}
import scala.util.Success
import scala.concurrent.duration._
object Main {
  def main(args: Array[String]): Unit ={
    implicit val fixedEc: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(3))

    def createFuture(n: Int): Future[_] = {
      if(n > 0) {
        Future({
          println(s"future: ${n}, th: ${Thread.currentThread().getName}")
          createFuture(n-1)
        })
      } else {
        Future("fin")
      }
    }

    def evalF(fu: Future[_], n:Int): String = {
      println(s"evalF ${n}, th: ${Thread.currentThread().getName}")
      val r = Await.result(fu, Duration.Inf)
      r match {
          case _fu: Future[_] =>
            evalF(_fu, n+1)
          case s: String => s
      }
    }

    val fu = createFuture(100)
    evalF(fu, 0)
    fixedEc.shutdown()
  }
}

waterspout_noaa

スマートメーターから消費電力を取得してMetabaseでグラフ化した

久しぶりにプログラミング的な話題です。

最近、各ご家庭の電気メーターは、スマートメーターに置き換わっているようで、電力会社の検針とかが楽になるっぽいですが、ついでに「Bルートサービス」というサービスがあって、電気の利用者が電気メータの利用状況をリアルタイムに取得することができます。

電力会社へ情報を送るのがAルートで、家庭内に送るのがBルートという事らしいです。申し込むとIDとパスワードが発行されて使えるようになります。各社申し込み窓口を用意していると思いますので、お住いの地域の電力会社のHPなどを確認すると良いと思います。ちなみに自分の場合は、東京電力はWebで完結しましたが、東北電力は申込書を印刷して郵送でした。正確にはサポート窓口に電話して「え?」とか言われてドギマギした対応の上、担当部署から折り返し電話が来て、ようやく申込書の送付先を教えてもらえる感じでした。東北地方にはスマートメーターのBルートを利用しようとする人があまりいなかったようです。

スマートメーターは、外部危機から無線接続できるようになっていて、申し込みで貰えるのはそのためのIDとパスワードになります。接続するためには、Wifiとは違う規格の無線機器が必要になるので、購入する必要があります。

自分は、チップワンストップで、これを購入しました。

www.chip1stop.com

実は、今回のチャレンジを行うにあたり、下記のQiita記事を参考にさせてもらっています。ここで紹介されていた一番安い機器という事で購入しました。

qiita.com

この記事の通りに進めたらうまくいったので、素晴らしいです。感謝しかありません。

ということで、電力会社からIDとパスワードが届いて、USBドングルが届いたら準備完了です。

接続する

ドングルが届いたら開封してマシンに刺します。見た目はUBSメモリーみたいな機器です。

Linuxだとcuというコマンドがあってシリアルポートにコマンドが送れます。

cu -s 115200 -l /dev/ttyUSB0

「SKVER」と入力してエンターを叩くと何やらバージョン番号が表示されたら、とりあえず疎通確認は成功です。

シリアル通信機器というのは、古式ゆかしき仕様の周辺機器で、古くて遅いですが、仕組みが単純なんで案外あっさり繋がります。

シリアル通信って素晴らしいと思いました。

使う

上記サイトのソースコードにエラー処理や、積算電力量の取得処理などを加え、MySQLに投げるところまで機能追加したコードをgithubに公開しました。

github.com

自分のご家庭では、リモートのMySQLサーバーにデータを投げたかったので、sshトンネリングもしています。あと、実験でFirebaseの Cloud Firestore にも投げられるコード片が埋まっています。試したい方はどうぞ。

Metabase でグラフ化する

Metabase は、OSSなデータ可視化ツールです。本格的なデータ分析が簡単に行えるツールで、jarを展開して起動するだけです。

metabase.com

後は、「http://localhost:3000」にアクセスすると初期アカウント作成に移るので、作成してログインして使うだけです。DB接続も設定を作ればすぐできますし、グラフ化も適当にポチポチいじっていると出来ると思います(適当すぎる?)。

そうすると、こんな感じで電力消費量をグラフ化できる!やった!!

f:id:qtamaki:20190619195953p:plain

感想

やってみた感想ですが、「やってみてよかった」と思いました。

普段から「節電しなきゃ」という気持ちは心のどこかにあるのですが、電力消費量が分からないので、何が電力を消費しているのか?は、うすぼんやりとしかわかりません。

リアルタイムにフィードバックがあると、必要な処置というのもより具体的にハッキリとわかります。

現状のソースコードでは、非エンジニアの方にはちょっとハードルが高いと思いますので、できればもっと簡単に使えるように改良したいという気持ちです。

Oralce JDK の有償化後の今 OpenJDK ベースでベストな選択肢

さて、OracleがJavaの開発キットを有償化することを発表して1年半が経ち、実際に有償バージョンがリリースされて、更にJDK8がサポート対象外となりました。

qtamaki.hatenablog.com

これはだいぶ前に書いた記事ですが、その後も状況は刻々と変化していき、いろんなことが具体化してきたので、つらつらと書きたいと思います。

まず、最初に謝っておかなければいけないことがあるのですが、「JDKが有償化してもJREさえ更新しておけばOK」と書いたのは嘘でした。ごめんなさい。

当時見落としていたのか、その後方針が発表されたのかわからないのですが、Oracle社は、JDK11のリリースに伴い(JDK9から?)、公式JREの配布を止めてしまいました。

なので、JREはバージョン8以降、更新されることはありません。困った人も少なからずいるものと思われます。

JRE が必要な人は色々大変だとは思いますが、頑張ってください。

顧客(自分)が一番欲しかったもの

新たな選択肢を検討する前に、かつての Oracle JDK から、私たちはどんな利益を得ていたのでしょうか?

そして、リリースモデルが変更された今、どういった状態がベストなのでしょうか?

そこから考えていきます。

まず、サポートですが、電話やメールでの問い合わせをしていた開発者は、それほど多くは無かったと思います。そういった手厚いサポートが必要な人たちは、リリースモデル変更前から、Oracle社に対して対価を払ってサポート契約を結んでいたので、今後もお金で解決すれば問題ないでしょう。

そうではなく、公開されたものをダウンロードしてインストールして使っていた開発者が、JDK に望む要件を考えてみると、以下のようになると思われます。

  1. 開発や本番環境にフリーで使用できること
  2. JDK 一式がインストーラー又はZipを解凍してインストールできること
  3. Ubuntuで apt install できて apt upgrade もできること
  4. たまにパッチがリリースされ、セキュリティがそれなりに安全に保たれていること
  5. 一つのバージョン(少なくともソースコードの互換性が保たれたバージョン)が、数年単位で使用できること

このぐらいのことが、以前の Oracle JDK からは享受できていたと思われます。Oracleさん、ありがとう!

リリースモデル変更後はどうなるかというと、ザックリいうとフリーで使うためには、OpenJDK を利用すればよいのですが、リリース後の3ケ月後に1回パッチが出て、半年後には次のバージョンにアップデートされます。最新の状態に保とうとすると、移行期間なしで次々とメジャーバージョンアップを繰り返すという運用が必要になります。本番系で商用運用しているサーバーで、これはしんどい。

今、ベストな選択肢

ということで、 OpenJDK をベースに長期サポートを提供するベンダーがいくつか出てきましたので、それらを検討したいのですが、面倒なので結論から言います。

それは、 Azul SYSTEMS が提供する Zulu です。

Azul SYSTEMS の提供している比較ページがあるので貼っておきます。提供元の情報なのでお手盛り感はありますが、なかなか良さそうです。

Zulu Comparison Matrix - Azul Systems Inc.

商用サポートを受けるためには、最低1年間 $13,500 とお高いですが、そもそも Oracle JDK 時代もサポートを受けていなかった我々には無用です!

コミュニティバージョンのビルドは、無料でダウンロードして使用できる代わりに一切の保証がありませんが、パッチの提供期間は長く、LTSバージョンはなんと10年以上提供されるようです。それどころか、JDK7なども、いまだにパッチが出ています。すごいですね。これなら安心ですね。

更に嬉しいのが、 apt と yum のリポジトリが公開されていて、サーバー側でも、 apt install や yum install できそうです。サーバー構築時にリポジトリを追加する手間はかかりますが、これなら今まで通りの運用ができそうです。

難点を言うと、名前からそれが OpenJDK のビルド提供だとはとても思えないところでしょうか?^^;

まったく、 Java っぽくも JDK っぽくも OpenJDK っぽくもないので、なんか心的抵抗が強い。。。

Zulu で良さそう

とはいえ、名前の違和感は中身とは関係ないことですので、現時点の情報で判断すると、 Zulu を使っておけば良さそうです。

他のビルドも大きく劣るということはなさそうなので、運用の見通しが立つなら好きなものを使えばよいと思います。

異論や反論はお受けします。

※追記

Zulu のコミュニティビルドは、サポート期間も保証されていないという指摘をいただきました。現時点で、JDK7にパッチを提供しているぐらいなので、当面は大丈夫かとは思いますが、突然サポート方針が変更になる可能性が無いとも限りません。その辺のところは、無償利用に乗っかている立場なので、自己責任ということで理解して使用する必要がありますね。

zulu_wire_basket_5Div4716

人類の7割はプログラミングに向いてない

note.mu

というわけで、バズった記事に乗っかります。^^;

以前から、ちょいちょい言っているのですが、自分は、プログラミングの向き不向きが先天的に決まっているという仮説を強く信じています。

現場で長らくシステム屋をやってきての肌感覚なので、まさに「ソースは俺」なのですが、自分の感覚だと、プログラミングの向き不向きと人口分布を図にするとこんな感じになるはずです。

f:id:qtamaki:20190104175402p:plain
プログラマーの分布図

適当に描いた図なので、信憑性はゼロです。^^;

もちろん、「プログラミングの向き不向きに先天性は関係ない」という意見もあるでしょうし、「先天的な素養が関係するにしても、努力で克服できるレベルだ」という主張もあるでしょう。しかし、実際に現場で教えていたり、一緒にプロジェクトに従事していると、「どう頑張っても無理でしょ?」としか言いようのない人たちがいることも確かですし、プログラミングにおいては「努力」こそ最大の才能だと思いますので、「努力で克服する」というのは、自己言及的なパラドックスに陥っています。

自分は、コンピューティングが大好きなので、休みの日にプログラミングすることも、仕事で辛い目にあうことも(モノによってはですが)苦ではないです。しかし、コンピュータが好きではない人が、「嫌々」もしくは「仕事で仕方なく」やったとしても、伸びていく人は稀でしょう*1し、何より本人が不幸になるのが可哀想です。

ということで、どこかに分水嶺があって、好きな人は自分でどんどん学習して伸びていくし、苦手な人、興味のない人は、会社や学校で与えられた機会にしかコンピュータと接しないので、更に停滞するという感じになります。

これをどうにかする抜本的な対策は見つかりませんが、なるべく早期に自分に向いているか?の判断ぐらいつけさせてあげるのが良いのではないかと思います。

プログラミング義務教育化によって、「あ、俺向いてないや」みたいなのが、早期に判断できるというのは良いことだと思っています。

自分が、運動神経が無く、体育に全く向いていなかったように。

*1:居ないわけでは無いと思う。「YAWARA!」の主人公が柔道なんてやりたくないのに最強みたいな感じで