fitbit versaを購入したので開封の儀

スマートウォッチ的なものが欲しいなーと思ったので、fitbit versa を購入しました。 fitbit versaはその名の通り、fitbit が今年(2018)の6月に発売したスマートウォッチです。トップの写真からもわかるように、若干Apple Watch に似ています。 元々、Huawei Watch が欲しいなーと数年前に思っていたんですが、(当然ながら)新しいモデル が出ており、これがまた初代のHuawei Watchとは全く方向性の違うスポーツタイプ。これはちょっと・・・と言うことでPebble もいいな、と探してみると、いつの間にやらサポートが終わってしまっていました。よくよく調べると、Pebbleはfitbitに買収された とのことでした。かといってApple Watchを買うかというと、私はAndroid ユーザですから、そういう選択肢はありませんでした。 そうこう考えながらいろいろ検索したりなんかしていたんですが、fitbit versaが実質的にPebbleの後継であるという情報を見たり聞いたり しました。お値段もお手頃で、これならまぁいざ微妙でも、買い換えもできるかな、という気持ちもあり、購入に踏み切りました。(fossilの新しいやつもよさげなんですが、ドルで見た金額と円で見た金額が大幅に違って萎えました) 外箱はこんな感じです。fitbit versaは、通常モデル(シリコン?ゴム?のバンド)が3種類と、SPECIAL EDITION(布バンド)が2種類の計5種類で展開されています。元々海外モデルではSPECIAL EDITIONにのみNFCが搭載されているという違いがあったようなのですが、日本版では機能的違いは無いようです。 通常モデルの黒と、SPECIAL EDITIONのグレーですごく悩みました。本体の色はグラファイトの方が良さそうだし、バンドも布の方がよさげに見えたんですが、布バンドは濡れたら乾くまで時間かかりそうなので、ゴムバンドのほうが良いのかな・・・と・・・(店頭で悩み続けたので若干怪しかったかも?)。でもまぁ、本体の色はブラックよりグラファイトの方がよさげでしたし、ゴムバンドは純正の交換バンドとして売ってるから、後で買うこともできるか、ということでSPECIAL EDITIONのグレーにしました。今回ビックカメラで買ったんですが、ビックカメラではカードの様なものをレジに持って行くんです。で、商品を受け取ってみたら箱の右下に「PLUS EXTRA CLASSIC BAND」の文字・・・。 帰ってから開封してみたら、案の定通常モデルと同じクラシックバンドが付属してました。ついてるなら早めに言ってほしかった・・・あれだけ店頭で悩んだ私の時間とは・・・。! 本体の画面を保護していたフィルムを取ってみて気づいたんですが、小さなクッションのようなものがついてました。ボタンが押ささらない様にとの配慮なんでしょうけど、こういう細かい気遣いは初めて見たので少しだけ感動しました。 非常に軽く、そしてエッジが削られているので薄く見えるため、非常にスマートです。写真で見る限りではベゼルが結構幅広なのが気にかかった(最近はZenfone 5Zを使っていることもあり、ベゼルは小さい方がいいなーと思っていた)のですが、実際画面をつけてみると、意外と気になりませんでした。 元々腕時計など、腕に何かをつけるという習慣がないので、どうなるかわかりませんが、しばらく使ってみようと思います。

2018-09-01 · nasa9084

趣味サーバーのインフラをKubernetesで整えた件

趣味でサーバー運用をしています。札幌在住の大学生時代から運用を開始し、引っ越しに伴い朝霞へ移設、現在はコミュニティで使用している自宅外のラックへ移設されましたが、変わらず動いています。 この「趣味サーバー」は購入当初からKVMをベースとした(OpenNebula を使用しています)プライベートクラウド基盤として使用してきました。今も変わらずベースはOpenNebula/KVMなのですが、この度晴れてKubernetes を中心とした構成に組み替えたのでご紹介します。 尚、サーバ台・電気代・インターネット代を除くソフトウェア料金は基本的に無料で済んでいます。 物理層 このプライベートクラウド基盤は3層で構成されています。 その最も下の層が物理層です。その名の通り物理サーバそのものですね。物理サーバとしてDELLのR410(ヤフオクで1万弱で購入・4コア8スレッド×2、メモリ16GB)とDL360Gen6一号機(会社の処分品をもらってきた・4コア4スレッド×2、メモリ24GB)、DL360Gen6二号機(会社の処分品をもらってきた・4コア8スレッド×2、メモリ24GB)の三台で、それぞれubuntu 16.04LTSがインストールされています。落ち着いたら18.04LTSにアップデートしたい。 基本的に電源やLANは冗長化されておらず、電源やNICに問題があると即死亡となります。 VM層 物理層の上に構成されているのがVM層です。OpenNebula/KVMを使用しており、Web UIからポチポチッとVMを作成できます。今回Kubernetesで整える前は、VMとしてnginx インスタンスを作成し、外からの80/443ポートへのアクセスを捌くリバースプロキシとして使用していました。本ブログも長らく単体VM上のDocker コンテナとして稼働していました。基本的にVMにはCentOS 7をインストールしています。 今回の構成変更で、VMは基本的にKubernetesのノードとして使うように変更、直接VM上で動作しているのはオブジェクトストレージを提供するminio とブロックストレージを提供するGlusterFS のみとなりました。 尚、GlusterFSクラスタの構成にはheketi を使用しました。 コンテナ層 最も上の層がコンテナ層です。ここまでの話からわかるように、Kubernetesクラスタを構成しています。四台のCentOS 7をクラスタノードとして使用、Kubernetes自体の構成管理はkubespray を使用しています。現在はKubernetes 1.11.1です。本ブログもKubernetes上のコンテナとして動いています。 Persistent VolumeとしてVM上に構成したGlusterFSを使用、本ブログ等のバックアップ先としてminioを使用しています。 当初はVM上に構成したnginxインスタンスをそのままリバースプロキシとして使用していましたが、本ブログを含めたアプリケーションを順次Kubernetesクラスタ上のコンテナとして移設していった結果、nginxのVMだけ別になっていることに不便を感じるようになりました(リバースプロキシの設定は手作業で設定しなければなりませんし・・・)。しかし、VM上のnginxリバースプロキシを廃するためには、二つの問題点がありました。 素KubernetesではIngress が使用できないため、ホスト名ベースの振り分けが出来ない Let’s Encrypt の証明書を管理するVMがいなくなる これらを解決しないことにはnginx VMを削除できません。 解決のためにまず、kind: Ingressを使用するための実装としてingress-nginx を使用することにしました 。Ingressが使用できるようになることで、クラスタ外のリバースプロキシを挟まずともホスト名ベースの振り分けが出来るようになります。 ingress-nginxはService type: NodePortでも使用できるのですが、折角なのでService type: LoadBalancerを使用したいですよね?type: LoadBalancerを使用するための実装としてMetalLB を使用することにしました 。これにより、ingress-nginxに対してクラスタ外のIPアドレスを割り当てることが出来るようになります。 次に、Let’s Encryptの証明書を管理するため、cert-manager を導入しました。cert-managerはkubesprayの導入時にアドオンとしても導入することが出来、今回はkubesprayのアドオンとして導入しました。これはその名の通り、証明書をKubernetesのリソースとして管理することが出来るツールです。最初はLet’s Encryptのacme api v02に上手くアクセスできない、ワイルドカードでの証明書取得が出来ないなど躓きましたが、Let’s Encryptに上手くアクセスできない問題は最近のkubesprayで比較的新しいバージョンのcert-managerを導入することで解決できました。ワイルドカードでの証明書が取得できない問題は、元々webroot(HTTP01)で証明書を取得していたのが原因のため、DNS01へ切り替えました。Gehirn DNS を使用していましたが、上手くいかなかったためCloudflare DNS に切り替え、事なきを得ました。 これらにより、nginx VMを廃し、ルーターでの80/443のNAPT設定をすべてKubernetesクラスタへと向けることが出来るようになりました(OpenNebulaやminio等へのアクセスはtype: ExternalNameを使用)。 VMがぐっと減り、ストレージ用途以外のVMを直接触らなければいけないことも減りました。めでたしめでたし。 使っているものまとめ Ubuntu CentOS Kubernetes (GitHub ) ...

2018-08-23 · nasa9084

confd + initContainerでAlertmanagerの設定をSecretに逃がす

TL;DR Alertmanagerの設定には一部Secretが含まれる バージョン管理システムに入れたくない initContainerでconfdを使って設定ファイルを生成する Alertmanagerの設定の一部をSecretに格納できる confd kelseyhightower/confd は非常に軽量な設定ファイル管理ツールです。基本的にはテンプレートエンジンですが、多くのバックエンドデータストアからデータを持ってきて、設定ファイルに書き出すことが出来ます。 また、事前処理や事後処理を行うことが出来るので、例えば設定ファイルを書き換えたあと、リロードする、というところまでconfdで行うことが出来ます。 Install Go言語で書かれているため、インストールは非常に簡単で、バイナリをダウンロードしてきて実行権限を与え、パスの通ったところに置くだけです。バイナリはリリースページ からダウンロードすることが出来ます。 使用方法 confdを使用するためには、三つのものを用意する必要があります。 テンプレートリソース テンプレート データストア テンプレートリソース テンプレートリソースには、どのテンプレートを使用して、どんなキーでデータストアからデータを取り出し、完成した設定ファイルをどこに置くのか、事前処理・事後処理はどんなものかを記述します。書式はTOMLで、慣れ親しんだ(慣れ親しんでない?)iniファイルの様に気軽に書くことが出来ます。/etc/confd/conf.d以下に配置します。 テンプレート テンプレートはその名の通り、設定ファイルのテンプレートです。ここに、データストアから取り出したデータを合わせて設定ファイルを作成します。書式はGo言語のtext/template に準じます。/etc/confd/templates以下に配置します。 データストア そして、データストアにデータを入れる必要があります。 confdは、データストアとして、次のものをサポートしています(2018/08/20現在) etcd (GitHub: coreos/etcd ) consul (GitHub: hashicorp/consul ) dynamodb redis (GitHub: antirez/redis ) vault (GitHub: hashicorp/vault ) zookeeper (GitHub: apache/zookeeper ) rancher metadata-service (GitHub: rancher/rancher , rancher/metadata ) AWS Systems Manager パラメータストア 環境変数 ファイル Alertmanager Alertmanager はPrometheus からのアラートを受け取り、適切にハンドルするためのアプリケーションです。Alertmanagerの設定はYAMLで記述するのですが、SMTPのパスワードやSlack のIncoming Webhook URL 等、平文でバージョン管理システムに入れるのは躊躇われるデータを含みます。しかし、環境変数などから設定をすることも出来ないため、平文で記述するか、何らかの方法で設定ファイルを編集してから使う必要があります。 特に、Prometheus/AlertmanagerはKubernetes と併せて使用されることが多いため、出来ればKubernetesのSecret機能を使用したいところです。 そこでconfdをinitContainerで使用して、設定ファイルを生成します。 まず、テンプレートを作成します。Alertmanagerの設定ファイルを用意し、後から挿入したい部分をテンプレート文字列で置換しておきます。 1 2 3 4 5 6 7 8 9 10 global: slack_api_url: {{getenv "ALERTMANAGER_SLACK_URL"}} route: receiver: slack receivers: - name: slack slack_configs: - channel: "#alert" 今回は例なので、細かい設定の一切を省いた形にしました。上記の内容で、alertmanager.yml.tmplとして保存しました。 ...

2018-08-20 · nasa9084

ファイナルカツカレーをつくった

連休も終わりで、明日から出社するのがつらいのでファイナルカツカレーを作りました。 ファイナルカツカレーは要するに、ファイナルカレーにカツを乗せたものです。 ファイナルカレーはいちばんおいしい家カレーをつくる に書かれているカレーで、我らがバイブルであるめしにしましょう(4) で紹介されています。 素晴らしいカレーであるとのことなので、やはりカツは素晴らしいカツを乗せたいものと思いますので、超級カツ丼 の時にもやった、低温調理カツでやっていきます。 まずはタマネギを炒めていきます。これは一個分です。結構大きめのタマネギを買ってきました。 割とざっくりした粗みじん切りです。昨日包丁を研いだので目が痛くない。 強火で炒めて、焦げ付きそうになったら少し水を足す、という作業を繰り返します。 良い感じになったら香味野菜類を追加します。にんじん・セロリ・ニンニク・ショウガ・ホールトマトですね。めしにしましょうではミキサーでやっていく風に書かれていましたが、我が家にはミキサーが無く、このために買うのも何かと思ったので、にんじんはみじん切り、セロリとニンニク・ショウガはすりおろしてみました。ニンニクをすりおろす小さいおろし金でセロリみたいな大きいものをすりおろすのはつらいです。ホールトマトは缶でしか売ってなかったので余りました。どうしよう。 ここでバターをちょいと加えます。切れてるバターが便利でした。 水分が飛んできたらスパイスを足します。ターメリック・レッドチリ・クミン・コリアンダーです。これらは基本のカレー を作るのにも使える、基本的なスパイスなので、まぁ買っておいても良いでしょう。我が家は以前基本のカレーを作るのに買ったので、冷蔵庫に入ってました。 もうペーストです。ドライカレーとかの方が近い見た目。鍋を振るとひっくり返せます 肉です。豚肩ロースを適当な大きさに切り、梅酒と少々の醤油につけたものです。1時間くらい前につけて冷蔵庫にぶち込みました。梅酒は自家製です。今年つけたのを使いました。カツを乗せるので肉はいらないかとも思ったのですが、一応。 ペーストに肉をぶち込みます。つけ汁もそのまま。ちょっと緩くなります。 このまま少し炒めます。 良い感じになったのでコンソメ汁を投入。300mlのお湯にコンソメキューブを溶かしたものです。300ml入る良い感じのマグカップが無くて難儀。ローリエとはちみつ、醤油を加えて煮込みます。45分ほど煮込んだら、カレールゥを適当に突っ込みます。 煮込んでいる間にカツをやっていきます。カレーにカツをのせることで人間は幸せになるのです。これは昨晩仕込んだ豚肩ロースで、Anova を使用して、62度で24時間やったものです。めしにしましょうではカツをやるのに63度12時間でしたが、24時間やるつもりだったので1度下げました。それにしてもまずそうである。 切ったもの。断面は素晴らしいですね。カツにしましょう。 カツです。 断面。スマホです。むしろこのまま食べたくなってきます。 実は以前にも一度、五島軒 のカレー缶を使ってカツカレーを作ったのですが、超級カツを乗せるとカレーが見えなくなるのが欠点です。左上のお茶はジャスミン茶です。沖縄でさんぴん茶を飲んでから飲めるようになりました。というかむしろハマってます。 ファイナルカツカレーは、罪の味がします。人間が幸せになるためにはやはりカレーにカツをのせねばならないと、そう感じるものです。ファイナルカレー自体は少し薄い味というか、もういっこカレールゥを足してもよかったかもしれないです。

2018-08-15 · nasa9084

外部サービスをIngress backendとして使用する

TL;DR Service type: ExternalNameを使用する External Service Kubernetes では、Ingress を使用することで、ホスト名ベースのロードバランシング/リバースプロキシを行うことが出来ます。その際、プロキシ先としてKubernetes上のService を指定するのですが、場合によってはKubernetesクラスタ外のサービスをプロキシ先としたい場合があります。例えば、弊宅の環境では、次の様にプロキシしています。 基盤であるOpenNebulaのダッシュボード以外は*.web-apps.techとして、Kubernetesへとルーティングしています。 ところで、本ブログは現在Kubernetes上へ移行作業中です。今のところはまだ、Kubernetes上へ載せていません。しかし、折角プロキシの設定が減っているので、blog.web-apps.techもIngressリソースとして管理したいです。 そこで使用できるのがService type: ExternalNameです。ExternalNameとして外部サービスを登録することで、Ingressのバックエンドとして使用できるようになります。 設定 設定はごく簡単で、次の様にします。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 --- apiVersion: v1 kind: Namespace metadata: name: external-services --- apiVersion: v1 kind: Service metadata: name: ghost namespace: external-services spec: type: ExternalName externalName: 192.168.1.41 # 本ブログのローカルIP 今後も何かの拍子でKubernetesに載せたくないサービスが増える可能性もあるため、external-servicesとして名前空間を分離しました。このように設定すると、kubectlからは次の様に見えます。 ...

2018-08-07 · nasa9084

ingress-nginxを使用してオンプレでもIngressを使用する

TL;DR ingress-nginxを使用するとオンプレでもIngressを使用出来る MetalLBと組み合わせる Ingress IngressはKubernetes の機能の一つで、L7 LoadBalancerの機能を持ちます。先日紹介した type LoadBalancerは、L4 LoadBalancerで、クラスタ内のDNSで名前解決をし、IP制限などをすることが出来ます。それに対し、Ingressでは、HTTPSの終端となることが出来、ホスト名ベース・パスベースのルーティングを行うことが出来ます。 通常、オンプレでKubernetesを構築した場合、Ingress Controllerと呼ばれる、Ingressを作成する機能が無いためにIngressを使用することが出来ません。 しかし、折角Kubernetesを使用しているのに、ホスト名ベースのルーティングをクラスタ外のロードバランサーに設定するのは面倒です。 どうせならIngress、使いたいですね? そこで使用できるのがingress-nginx (GitHub: kubernetes/ingress-nginx )です。ingress-nginxはその名のとおり、nginxを使用したIngress Controllerです。Ingressリソースの作成時に、nginxの設定をConfigMapとして保存することでIngressの作成を実現します。 Install MetalLBをインストール している場合、次の二つのコマンドを実行することでインストールできます。 1 2 $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/cloud-generic.yaml 二行目のコマンドはドキュメント上では docker for macのコマンドとして記載されていますが、type: LoadBalancerが使用できるクラスタ一般で使用できます。 インストールが完了したら、ingress-nginxのサービスにIPアドレスが割当たります。 1 2 3 4 $ kubectl get svc -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default-http-backend ClusterIP 10.233.50.56 <none> 80/TCP 2d ingress-nginx LoadBalancer 10.233.47.246 192.168.1.100 80:30431/TCP,443:30017/TCP 2d 実際にブラウザでingress-nginxのIPアドレスにアクセスしてみて、default backend - 404と表示されれば正常に動作しています。 ...

2018-08-06 · nasa9084

MetalLBを使用してオンプレでもtype: LoadBalancerを使用する

TL;DR MetalLBを使用することでオンプレ(not on OpenStack)に構築したk8sでもtype: LoadBalancerを使用できる type: LoadBalancer kubespray 等を使用して、Kubernetes をオンプレ(on OpenStackを除く)で構築した場合、通常、type: LoadBalancer を使用することができません。これは、type: LoadBalancerは通常CloudProviderにより管理されており、オンプレ(on OpenStackを除く)でk8sを構築した場合にはCloudProvider連携が無いためです。 しかし、k8sを使用するからにはtype: LoadBalancerも使用したいですよね?NodePortなどで代用するにも、ポートがバラバラになってしまって面倒です。 そこで使用できるのがMetalLB (GitHub: google/metallb )です。 MetalLBを使用すると、type LoadBalancerの作成をフックしてアドレス割り当てとアドレスの広報を行ってくれます。 Layer 2 mode MetalLBにはLayer 2 mode(以下L2 mode)とBGP modeがあります。これらのモードはアドレス広報の仕方が違い、L2 modeではARP/NDPで、BGP modeではその名の通りBGPでアドレスの広報を行います。通常、自宅を含むオンプレ環境ではBGPを使用していないと思いますので、L2 modeについて解説します。 L2 modeでは、特定のノードへアクセスを集中させ、kube-proxyによって各サービスへトラフィックを分配します。そのため、実態としてはロードバランサーが実装されている訳ではないことに注意が必要です。単体ノードにアクセスが集中するため、これがボトルネックとなり得ますし、アクセスが集中することになるノードが何らかの理由でアクセスできなくなった場合、フェイルオーバーに10秒程度かかる可能性があります。 requirements & installation 導入は非常に簡単ですが、以下の要件を満たしている必要があります。 他にネットワークロードバランシングの機能が無いKubernetes 1.9.0以降 MetalLB対応表 に記載のあるネットワークで設定されていること これに加え、MetalLBで使用することのできるIPv4アドレスを用意しておく必要があります。 私の環境ではk8sのノードが192.168.1.0/24にあるため、192.168.1.100から192.168.1.159までの60個のアドレスをMetalLB用としました。 要件を満たしていることが確認できたら、MetalLBのインストールを行います。 MetalLBをインストールするには、次のコマンドを実行します。 1 $ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.2/manifests/metallb.yaml Helm を使用してインストールすることもできますが、Chartが最新版ではないので注意しましょう。 次に、次のようなConfigMapを作成します。 1 2 3 4 5 6 7 8 9 10 11 12 apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - 192.168.1.100-192.168.1.159 これでMetalLBのセットアップは完了です。パブリッククラウドで使用するように、type: LoadBalancerを作成するとアドレスプールからIPアドレスが割り当てられ、アクセスできるようになります。 アドレスプールは複数用意することができ、特定のアドレスプールからIPを割り当てたい場合はtype: LoadBalancerのアノテーションにmetallb.universe.tf/address-pool: <ADDRESS_POOL_NAME>を追加します。 ...

2018-08-05 · nasa9084

Liveness/Readiness Probe

Kubernetes によるヘルスチェックには、Liveness ProbeとReadiness Probeと呼ばれる二つのものがあります。これらは混乱しがちな一方、日本語による情報が多くない(2018/07/26現在で、Google検索の1ページ目にヒットするのが4件ほど)ため、ここで一つ情報をまとめておきます。 共通 Liveness ProbeとReadiness Probeの設定は共通で、DeploymentやPodのマニフェスト内で、containersの中にlivenessProbeとreadinessProbeとしてそれぞれProbe spec を記述します。 次の項目を設定することが出来ます。 failureThreshold Success状態の時、何回失敗したらFailureになるか。最小で1回。 Default: 3 initialDelaySeconds コンテナが起動してからヘルスチェックを始めるまでの秒数。 Default: 0 periodSeconds ヘルスチェックの間隔。最小で1秒 Default: 10 successThreshold Failure状態の時、何回成功したらSuccessになるか。最小で1回。 Default: 1 timeoutSeconds ヘルスチェックのタイムアウト秒数。最小で1秒。 Default: 1 httpGet ヘルスチェックでアクセスするhttpエンドポイントの情報を書く。 httpGetの項目は次の様な項目を持ったobjectを書きます。 host 対象のホスト名。 Default: PodのIP httpHeaders リクエストのカスタムヘッダ指定。{name: HEADER_NAME, value: HEADER_VALUE}の形のオブジェクトの配列で書く。 port アクセスするポート番号または名称 path アクセスするパス。 scheme アクセスする際のスキーム。 Default: HTTP Liveness Probe 一つ目はLiveness Probeです。公式ドキュメント には次の様に書いてあります。 livenessProbe: Indicates whether the Container is running. If the liveness probe fails, the kubelet kills the Container, and the Container is subjected to its restart policy . If a Container does not provide a liveness probe, the default state is Success. ...

2018-07-26 · nasa9084

Future Pattern

Future Patternは非同期処理パターンの一つで、ある処理を別のスレッドなどで実行し、結果を後で(=未来で)受け取るような処理に用いられるデザインパターンです。 特徴としては、外側に見えている関数などの処理を実行するオブジェクトは、処理を別スレッドに委譲し、後で結果を得ることの出来るFutureと呼ばれるオブジェクトを即座にメインロジックへと返却することです。 言葉で書いても、何だかよくわからないので、コードを見てみましょう。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /* package, import part */ func main() { in := make(chan int) out := Double(in) // この時点では結果は得られない go func() { for i := 0; i < 10; i++ { in <- i } close(in) }() for d := range out { fmt.Println(d) // ここで結果を得る } } func Double(in <-chan int) <-chan int { out := make(chan int) go func() { for i := range in { out <- 2 * i } close(out) } return out // Futureオブジェクト } main関数から呼び出されたDouble関数は、与えられた数を二倍する関数ですが、二倍する処理は呼び出された時点では実行せず、即座にchannelを返します。この、変数名outのchannelがFutureオブジェクトです。 そのため、数を二倍した結果は、Double関数を呼び出した時点では得られず、後でoutchannelから得ることとなります。 ...

2018-07-04 · nasa9084

array/sliceに対する存在確認関数のベンチマーク

Pythonでいうところの、次の様な条件式を実現する関数を書きたかった。 1 2 3 4 5 ls = ["foo", "bar", "baz"] s = "baz" if s in ls: print("FOOBAR!") 対象がリストの時、普段なら普通にfor文を回すのですが、今回やりたかったのは定数値の一覧にあるかどうか、だったのと、定数の数も少なかったので、とりあえずで以下の様に実装していました。 1 2 3 4 5 func something(s string) error { if s != "foo" && s != "bar" && s != "baz" { return errors.New("value invalid") } } 流石に雑すぎるので、リファクタリングしよう、と思ったのですが、「はて、for文挟んだら遅くなったりしないだろうか」などと考えてしまったのでベンチマークを取りました。 TL; DR 素直にfor文を回しても大して問題はなさそう result 今回取ったベンチマークは6種類です。 for-range文を回す for文を回す map[string]struct{}を集合として取り扱ってみる &&, ||でつなぐ switch文を使う sort.SearchStrings()を使う 6番目のsort.SearchStrings()を使う方法はstackoverflow に書いてあった方法で、二分探索をしてくれるというのでやってみました。 結果は次の通り。 BenchmarkInByForRange-4 200000000 9.34 ns/op 0 B/op 0 allocs/op BenchmarkInByFor-4 100000000 10.1 ns/op 0 B/op 0 allocs/op BenchmarkInByMap-4 200000000 7.79 ns/op 0 B/op 0 allocs/op BenchmarkInByAnd-4 1000000000 2.85 ns/op 0 B/op 0 allocs/op BenchmarkInBySwitch-4 2000000000 1.39 ns/op 0 B/op 0 allocs/op BenchmarkInBySortSearchStrings-4 10000000 179 ns/op 32 B/op 1 allocs/op まぁ予想通りではあるものの、sort.SearchStrings()を使う方法は遅いですね。これはこの関数の「事前にリストがソート済みであること」という条件のために関数内でソートをしてるからだと思われます。(実際、ソート済みのリストを使って、関数内でソートをしないようにすると1/4くらいにはなる) ...

2018-06-26 · nasa9084