2016年 04月 17日

大量のファイルのバックアップにNASを使うのは適切なのか?

すこし昔書いたGoogle Keepのメモを発掘してきました。

NASの維持コスト

電気料金 を30円/kWh、NAS の消費電力を 20W で計算すると、446円/月。24時間動かすので思いのほか電気料金がかかっていることになり、初期コストも含めて考えると、オンラインサービスと案外競合する。

NAS の特徴は

  • 良:データが手元にある安心感
  • 良:LANで完結するので速度が早い
  • 悪:災害によってデータ消失が起こる
  • 悪:自分でメンテする必要があり、故障が起こると思いがけずコストがかかる

オンラインサービスの維持コスト

オンラインサービスの特徴

  • 良:災害があってもデータが失われない
  • 良:自分でメンテナンスする必要がない
  • 悪:大量のデータの取り出しが難しいことがある
  • 悪:ネットワーク経由でしか入出力できないことがあるので速度が遅い
  • 悪:サービスが終了することがある

Google Drive

エンドユーザ向けサービスだが値下げによりかなり安価になっている。
1TBプランが月額$9.99、30Tまではほぼ$0.01/GBとなる。Nearline とほぼ同じだが、容量を使いきっていなくてもプラン容量分課金される点で異なる。
取り出しは当然無料だが速度の保証はない

Dropbox

エンドユーザ向けのサービス。有料プランは1TBのみで、月額1200円。1TB 以上のプランがないので、それ以上になる予測がたつ場合選択肢にあがらない。

Amazon Clould Drive

エンドユーザ向けサービス。有料プランの最大が1TB、1TBのとき年額40000円。月額換算で3333円とかなり高い。

ただし、プライム会員(3900円/年)の場合、写真データ(RAWも含む)が無制限となっており写真だけ上げるなら異常に安い。しかしこの手の無制限サービスはすぐ終了する予測しかない。

Amazon Glacier

約1円/GB
取り出しコストが大変複雑。月あたり使用容量の5%までを1時間あたりに分散してゆっくり取り出せば (約0.0067%/時) 無料。つまり取り出しソフトウェアがちゃんとしていれば、20ヶ月で常に無料で全量を取り出し可能

Google Cloud Storage Nearline

約1円/GB ($0.01/GB)
取り出しも$0.01/GBと書いてあるが、実際はこれに加えて転送量課金がある。$0.12/GB

なので、1TB ダウンロードしようとすると16000円ぐらいかかる。純粋に従量課金なので Glacier より料金はわかりやすいが、無料の範囲というのは存在しないので、ダウンロードでは必ずこの金額必要になる。

エンドユーザ的には価格で Google Drive に対するメリットがない。

Firefox の開発者ツールのほうが HTTP2 でサーバプッシュされたコンテンツがわかりやすい

Firefox だと上記のようにリクエストが消滅してタイミングも全てない表示になるみたいです。

Chrome の Network タブだとプッシュしてもキャッシュからひいてくる時間を表示しているのか区別できなくてモヤっとします。

ref. lowreal.net のHTTP2/HTTPS 化を実施 | tech - 氾濫原

2016年 04月 15日

JavaScript の必要ないソーシャルボタン

JSなしのソーシャルボタンというのを作ってみました。このサイトの各エントリ下部に実装されているものです。

動機

各サービス、JS を読みこんでボタンを表示するタイプのものをメインに提供していますが、ソーシャルサービスへのシェアという機能で外部リソースの読み込みとJSの実行が発生するのは、提供される機能に対して割に合わないのではないかと思っていました。

実際ウェブサイトのパフォーマンスチューニングをしていると、細かいボタンのJSのダウンロード・パース・実行・表示後のリフローが結構多くて気になります。

実装

サービス

  • Facebook
  • Twitter
  • Google+
  • LINE
  • はてなブックマーク

HTML+CSS+各サービスのアイコン画像(5つ)です。

各サービスのアイコンをSVGにしたかったのですが、各サービスのブランドガイドラインを読んでいると面倒になったのでオフィシャルなものを使っています。オフィシャルにSVG版が提供されていれば悩まないんですが、はてなブックマークしか提供していないようでした。

使っている画像はオフィシャルのものですが、さらに optipng や svgo をかけてあります (一部の画像にしか効きませんでしたが)。

LINE it! はスマフォかつアプリが入ってないと機能しません。JS版のボタンはスマフォの場合だけ出すような判定も入っているようです。テストページでは出しわけをしていませんが、このサイト内では画面サイズが小さいときだけ出るようにしています。

ソーシャルサービスに一括でして予約投稿してくれる buffer

https://buffer.com

buffer というのをちょっと使ってみようとしています。予め Facebook / Twtter などを接続して、スケジュールを設定しておくと、buffer 経由で投稿したときにいい感じにマルチポストするというツールです。

スケジュールの設定がおもしろくて「このサービスはこの時間帯に投稿すると効果がたかいぞ!」みたいなことをサジェストしてくれて、それを時刻に設定できます。

buffer への投稿自体は chrome 拡張経由で手動でやってみています。

使い続けるかはよくわかりませんが、現在 Twitter とか Facebook を見ないようにしているので、buffer のような別サービスを挟んでおけば、うっかり見ることも減って良さそうです。

SVGフォントのグリフを個別のSVG画像に変換する

[tech] JavaScript の必要ないソーシャルボタン | Fri, Apr 15. 2016 - 氾濫原 これを作るとき、最初のうちは全てSVGにするぞと意気込んでいて、Ligature Symbols に含まれるものをSVGに変換したらいいのではないかと、いろいろ試していました。

結局その方法はやめたのですが、SVG フォントから、個別の SVG ファイルに変換するスクリプトを雑に書いたので残しておきます。SVG フォント全体だとファイルサイズが大きすぎるので、必要なファイルだけ普通の SVG 画像として抽出するということです。

以下のように perl + XML::LibXML で書きました。グリフ名を引数に与えると、該当するグリフを個別の .svg に書き出します。LigatureSymbols でしか試していませんが、SVG フォントなら他のでもいけるかもしれません。

#!/usr/bin/env perl

use utf8;
use strict;
use warnings;
use v5.10.0;
use lib lib => glob 'modules/*/lib';

use XML::LibXML;

open(my $fh, "<", "LigatureSymbols-2.11.svg") or die "cannot open < input.txt: $!";
my $font = do { local $/; scalar <$fh> };
close $fh;

my $doc = XML::LibXML->load_xml( string => $font, load_ext_dtd => 0 );
my $xpc = XML::LibXML::XPathContext->new($doc);

# get copyright metadata
my $original_metadata = $xpc->findvalue('/svg/metadata');
my $units_per_em = $xpc->findvalue('/svg/defs/font/font-face/@units-per-em');
my $ascent = $xpc->findvalue('/svg/defs/font/font-face/@ascent');
my $bbox = $xpc->findvalue('/svg/defs/font/font-face/@bbox');

for my $glyph_name (@ARGV) {
	my $glyph = $xpc->findnodes(sprintf('/svg/defs/font/glyph[@glyph-name="%s"]', $glyph_name))->[0];
	my $horiz_adv_x = $xpc->findvalue('./@horiz-adv-x', $glyph);

	my $document = XML::LibXML::Document->new('1.0', 'UTF-8');
	my $svg = $document->createElement('svg');
	$svg->setAttribute('width',  $horiz_adv_x);
	$svg->setAttribute('height', $units_per_em);
	# $svg->setAttribute('viewBox', $bbox);
	$svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg');
	$document->setDocumentElement($svg);

	my $metadata = $document->createElement('metadata');
	$metadata->appendChild($document->createTextNode($original_metadata));
	$svg->appendChild($metadata);

	my $path = $document->createElement('path');
	$path->setAttribute('transform', sprintf("scale(1, -1) translate(0,%s)", -$ascent));
	$path->setAttribute('fill', '#fff');
	$path->setAttribute('d', $xpc->findvalue('./@d', $glyph));
	$svg->appendChild($path);

	warn "write to $glyph_name.svg";
	say $document->toString(1) ;

	open(my $fh, ">", "$glyph_name.svg");
	print $fh $document->toString;
	close $fh;
}
2016年 04月 14日

デザインの調整

ずっと中途半端なデザインだなと思っていたので、改めて全体を見直しました。

大きい画像は devicePixelRatio に基いて大きい画像をロードするようなスクリプトを書いていたのですが、面倒なので最近になって常に 2048px の画像を読みこむように変えました。

しかし画面の表示は 960px 程度を最大にしており、Retina でも若干の無駄があるのが気になってきました。ということで、まず 1024px を最大幅にできるようにしました。

しかし、意外ともう少し狭い幅で見ることも多い気がするので (特に開発ツールを横に開いていると結構画面が狭い)、その場合幅だけ変えたバージョンをメディアクエリでだしわけしています。

スマートフォン向けにはさらに狭い幅向けのバージョンをメディアクエリでだしわけていますが、これはほぼ今まで通りです。

また、大きい画面の場合、photo タグが設定されているエントリと、それ以外のエントリで画像の幅を変えるようにしました。tech カテゴリでも無駄に横幅が大きい画像になっていて一画面の情報量が少なかったので、これで見易くなった気がします。

しかし、テキストの幅を制限しつつ画像は大きく表示したいと思うと、自分のデザイン能力だと綺麗にいかず難しく感じます。

STM32F103 C8 T6 の安いボードでLチカ (platformio + mbed)

STM32F103 C8 T6 の安いボードが ebay で売っているので買ってみました。水晶が実装済み基板が 300円程度。届いたボードに実装済みの外部水晶は8MHz (内蔵RCと周波数は一緒) のようです。また 32.768k の水晶もついています。他に実装されているのはLDOやUSBコネクタぐらいです。

なお USB デバイスを作りたい場合 RC オシレータだとクロック精度が足りないので外部水晶は必須です。

買ったのはこれです: http://www.ebay.com/itm/201529768817

型番について

STM32F103 C8 T6 という型番の読みかた

  • C: 48pins
  • 8: 64kbytes Flash
  • T: LQFP パッケージ
  • 6: -40〜85°C

をあらわしています。STM32F103x8 (64k) や STM32F103xB (128k) はスペックシート共通になっています。 (ピン数とFlashのサイズの違いのみなので)

特徴

以下個人的に良さそうと思った点です。

  • STM32F103 は USB 1.1 FS (フルスピード=12Mbps) に対応している
  • ADC が2つある (チャンネル数は10)
    • 同時サンプリングができそう

Cortex-M3 なので M0 よりはパフォーマンスが良さそうです。一方 FPU や DSP 関係の命令 (SIMDとか) は M0 同様ありません。

クロック

SYSCLK (システムクロック) は

  • HSI
    • High Speed Internal ?
  • HSE
    • High Speed External ?
  • PLL

の3種類のクロックソースがあります。

HSE はさらに HSE バイパスと HSE クリスタルとに別れています。バイパスは発振器のクロックを直接入れるモードです。

PLL のクロックソースにはHSIとHSEがどちらも使えるようになっています。

このボードの場合

8MHz の外部水晶がついてるので、8MHz の HSE を PLL のクロックソースとして 72MHz にします。USB 用のクロックもここから作ることになっています。

  • PLL 入力クロックソースは HSE、分周なし
  • PLL逓倍を9倍に (8 * 9 = 72MHz)
  • USBプリスケーラは1.5に (72MHz / 1.5 = 48MHz)
  • APB1 は2分周 (72MHz / 2 = 36MHz)

みたいになりそうです。が、とりあえず mbed 環境で動かしてみるためクロック設定は無視します (mbed 側で 72MHz に適当に設定されます)

書きこみ (Lチカ)

例によって環境を整える部分は platformio でやります。

platformio.ini は以下のようにします。nucleo_f103rb は型番違いですが、ほぼほぼ互換性があります。nucleo_f103rb の外部水晶も 8MHz のようで、この場合 mbed の初期化コードは一切変更なしでいけそうです。

本来 boards の追加をもっと簡単にできたらいいのですが、現状の platfromio だとそういうことはできなそうです。

# platformio.ini
# nucleo_f103rb は f103c8t6 とフラッシュサイズとピン数以外は互換
# 外部クロックも 8MHz で同じのためそのまま使える
[env:stm32f103c8t6]
platform = ststm32
framework = mbed
board = nucleo_f103rb

Lチカはこのようにしました

#include "mbed.h"


DigitalOut led(PC_13);
// Serial serial(USBTX, USBRX);


int main() {
	for (;;) {
		led = 1;
		wait(0.5);
		led = 0;
		wait(0.5);
	}
}

PC_13 はボード上のLEDに繋がっています。nucleo_f103rb だと LED1 は PA_5 のようなので、ジェネリック名ではなくピン名で直接指定しています。

書きこみはこれまた ebay で購入した st-link2 を使いました (約400円)。Mac の USB ポートに繋ぐと特に何もしなくても認識するようでした。

ボードと st-link を接続して、USB 接続すると、基板上にも電源供給されます (別途電源供給はいらないようです)

書きこむためまず st-util を起動します。platformio で ststm32 環境をセットアップしておくと st-util もインストール済みのため楽です。

$ ~/.platformio/packages/tool-stlink/st-util
2016-04-14T00:48:41 INFO src/stlink-common.c: Loading device parameters....
2016-04-14T00:48:41 INFO src/stlink-common.c: Device connected is: F1 Medium-density device, id 0x20036410
2016-04-14T00:48:41 INFO src/stlink-common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2016-04-14T00:48:41 INFO gdbserver/gdb-server.c: Chip ID is 00000410, Core ID is  1ba01477.
2016-04-14T00:48:41 INFO gdbserver/gdb-server.c: Target voltage is 3254 mV.
2016-04-14T00:48:41 INFO gdbserver/gdb-server.c: Listening at *:4242...

こんな感じで gdb server として立ちあがります。

別のターミナルから gdb server に接続してバイナリを送りこみます。

$  ~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gdb .pioenvs/stm32f103c8t6/firmware.elf 
> target extended-remote localhost:4242
> load
> cont

これでLチカできました。

ref

2016年 04月 13日

筋の悪さ

JS しか書いてないんだなって人は筋悪いものをありがたがっていたりする印象はある。しかし筋悪いものをありがたがるみたいなのはどこにでもいるので、JSがどうとかは直接は関係がないはずではあると思う。JSしか書いてない人とPHPしか書いてない人は似たようなもんで、単に広範囲の知識に興味がないだけな気がする。

それはともかく「これは筋悪そうだな」っていう感覚がどこからくるのかよくわかってないので、現時点で思いつく限り雑にメモしておく。

割の合わなさ

「これは何の問題を解決してるんだろう」と思ってドキュメント読んだりソース読んだりした結果、大したことを解決してなくて、その割に実装量が多いとか学習コストが高いと、筋悪いなあと思う。

フットプリントや学習コストに対して提供されるモノが「割に合わない」のは筋が悪く感じる。

将来性のなさ

「あ、これはただの流行だな」みたいな、5年後には消滅してるなというものは筋が悪い。

標準にそういう機能入るよ、みたいなのを全然違うインターフェイスで実装してたりするのとかがあてはまる。標準で議論されている機能なら、ポリフィルにするのが最も将来無駄にならない。

HTTP2 に向けてキャッシュフレンドリーなリソース構成にしていこうな、という昨今で、何でもかんでもパックや!みたいなのも、今はぎりぎりいいかもしれないけど、既に筋悪い感じがする。

プログラムの見方を変えないラッパー

たとえば Promise はコールバックのちょっとしたラッパーぐらいの機能しかないが、プログラムの見方を変えるという重要な役割を持っているので、意味がある。

しかし単にシンタックスシュガー的なものしか提供していないとかで、何もプログラムの見方が変わっていないのにラッパーがかぶさっているのは、ライブラリとしての意味がない。

「プログラムの理解を助ける」という役割はとても重要だけど、そういう視点で作られているライブラリかどうか、それが割に合うかは難しい。

しかし最悪なのは書き手にとってしかメリットがないというもの。特に実装を全て読まないと使えない系は要注意で、そういう書き手のオナニーで変なラッパーが挟まってるみたいなのは読み手がとても苦労する。これはメリットがないというよりも明確に将来にわたって害となる。

ただし実装を全て読まないといけないものが全てだめかというとそういうわけでもない。実装は読まないと危険だけど可読性はあがるので割に合うこともある。

フルスタック

フレームワークのレールから外れた瞬間アホみたいなマジカルコードを書くことになる。レールから脱線すると必ずハマる。そしてフレームワークの枠組み内で収まるようなアプリケーションはない 。

もし使う場合コピペで実装できる以外のことをしないことがポイントで、「ここはこう書きたいんだ!」という自我を捨ててコピペする機械として生きなければならない。

実際のフルスタックというのは検索して出てきたstackoverflowのコピペで全部やりますよという意味で、なんでもできるという意味ではない。

HTTP2 で何をサーバープッシュすべきか

意外と何をプッシュすべきか悩んだのでひとまず現時点での自分の結論をまとめました。

CSS は必ずプッシュ・JSは場合による

サイトの構成によりますが、ページの表示に必要なものは全てプッシュするべきのようです。

  • CSS の全て
  • ページの根幹に関わるJSの全て

サーバプッシュの目的

まずサーバプッシュの目的を改めて確認しておくと、これはクリティカルレンダリングパスを削減するためです。

クリティカルレンダリングパスについては クリティカル レンダリング パスのパフォーマンスを分析する | Web Fundamentals - Google Developers がわかりやすいです。

サーバープッシュなしの場合 HTML+CSS 構成のページはクリティカルレンダリングパスが必ず2以上になります。つまり最低でもRTTの2倍の時間がページ表示に加算されます。

これをサーバプッシュで行う場合、HTML+CSSを一度に送り返すので、クリティカルレンダリングパスは1になります。

イメージとしてはHTML内の外部CSSが全てインライン style 要素にしてある場合に似ています。ただしサーバプッシュの場合、適切なキャッシュを効かせることができるケースがあるので、インライン style 要素よりも効率的です。

JSをプッシュすべきか

これは場合によると思っています。JSがないとページの表示に致命的な不具合がある場合、サーバープッシュしないと意味がありません。

一方、JS がページのインターフェイスの向上のために使わていて、とりあえずの表示に関係がない場合、JS をプッシュした分、ファーストペイントが遅れます。

そういうわけでなので、JS をプッシュすべきかどうかは場合によるので簡単に決められない気がしています。

理想のサーバープッシュ

理想のサーバープッシュを考えるにあたって、ロードされるリソースの分類をしてみます。

クリティカルリソース (ブロッキングアセッツ)

ファーストペイントのために必要なリソース

  • CSS
  • ブロックする JS (async/defer のない script 要素)
  • HTML

DOMContentLoaded リソース

DOMContentLoaded までに必要なリソース

  • defer された script

onload リソース

onload までに必要なリソース

  • 画像
  • async された script

どうプッシュするか

最終的に必ずロードされるリソースなら、プッシュしてしまっていいはずです (初回ロードの場合)。

  1. クリティカルリソース
  2. DOMContentLoaded リソース
  3. onload リソース

の順に全てプッシュするのが理想そうです。ただ、現時点で任意の順番に優先順位を明確に決めて送信することはできないような気がしてます。

プルリクエストを送るときは大抵気が重い。

たとえ明かなバグ修正、すなわちマージされる公算が大きくても、些細なことでケチがついたりする。これがさらに機能追加みたいな「マージしてもしなくても本流には関係ないね」みたいなのは、マージされる公算がさらに低くてさらに気が重い。

まずプルリクエストを送るケースってのは、別にプルリクエストを送りたくてやってるわけではなく、そのプルリクエストに含まれるコードが自分に必要だからやってるに過ぎない。つまり最悪自分のレポジトリに置いておけばいいのだが、本流に取り込まれていれば今後のバージョンアップで機能が壊れることが減る (ついでに他に困ってる人がいたら助かるかもしれないね)。そういう保守的なモチベーションで動いていることであって、元気良くプルリクを送っているわけではない。

そういうわけで、大抵の場合プルリクエストを投げた時点で「XX だ! とか言われてDISられそうだ」とか「コードスタイルがあってない!!とか言われてリジェクトされないか」とか「オレのところだとテストが通らん!とか言われないか」とか気が滅入る妄想に支配され、燃えつきており、あとはもう勝手にしてくれ (コミュニケーションはしたくないぞ) という気分になっている。


最近良くあるのが、プルリクエスト送る前にコミュニケーションしろ!みたいなルールを強いているプロジェクトで、こういうのはほんとどうしようもない。死ぬほど困っているとか、仕事でやるとかじゃないならプルリク送る気がしない。コミュニケーションしたくないからコード書いてプルリクしてんのに、コミュニケーションを強要してくるのはどういうことなのか。かつて github に感じた居心地の良さはここにはない。