kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Code School の講義「Assembling Sass」で Sass に入門した

今まで使う機会がなくて未経験だった Sass に入門した.今さら Sass って言われる気もするけど,最近担当しているプロジェクトでフロントエンド技術の理解が必要になり,幅広く学ぶことにした.最近 Vue.js を学んでいるのも同じ理由だったりする.Sass を学んだメモを残しておこうと思う.

sass-lang.com

"Code School : Assembling Sass" を受講した

最近は動画コンテンツで学ぶことが多くなっていて,今回は「Code School : Assembling Sass」の LEVEL 1 を受講してみた.LEVEL 2 からは有料(毎月 $29)になってしまうので,他のコースも同時並行で受講する場合は払っても十分に効果が得られそう.今回は LEVEL 1 だけでも十分に楽しめた.

www.codeschool.com

  • LEVEL 1 : Foundation
  • LEVEL 2 : Variable
  • LEVEL 3 : Mixin
  • LEVEL 4 : Extend
  • LEVEL 5 : Directive
  • LEVEL 6 : Math + Color
  • LEVEL 7 : Responsive

なお,LEVEL 1 は YouTube にも動画が公開されている.

www.youtube.com

1.1 Sass, Not SASS

  • Sass を作った人って Haml を作った人だったんだ!知らなかった!
  • メタ言語としての「Sass」は「SASS」ではなく「Sass」と表記するのが正しい

1.2 SCSS: Sassy CSS

  • 記法は .scss.sass がある
  • 一般的には CSS ライクな .scss が普及している

1.3 Commenting

  • Sass のコメント記法は2種類ある
  • /* */ を使うと,コンパイル後にも反映される

1.4 Importing

  • パーシャルテンプレートを作ってインポートすることができる
    • @import を使う
    • テンプレートのファイル名は _ から始める
@import "buttons";

1.5 Nesting Selectors

以下のようにネストした Sass を書く.

.content {
  border: 1px solid #ccc;
  padding: 20px;
  h2 {
    font-size: 3em;
    margin: 20px 0;
  }
  p {
    font-size: 1.5em;
    margin: 15px 0;
  }
}

コンパイルをすると,ネストした構造がフラットに展開される.

$ sass application.scss --style expanded
.content {
  border: 1px solid #ccc;
  padding: 20px;
}
.content h2 {
  font-size: 3em;
  margin: 20px 0;
}
.content p {
  font-size: 1.5em;
  margin: 15px 0;
}

また,コロンを使うと,スタイルの名前空間(プレフィックス)を定義できる.

.btn {
    text: {
        decoration: underline;
        transform: lowercase;
    }   
}

例えば,上記のように text: と書いておくと,自動的に展開される.これは便利そう!

$ sass application.scss --style expanded
.btn {
  text-decoration: underline;
  text-transform: lowercase;
}

1.6 The Parent Selector

& を使うと,親のセレクターと合わせることができる.

.content {
  border: 1px solid #ccc;
  padding: 20px;
  .callout {
    border-color: red;
  }
  &.callout {
    border-color: green;
  }
}

&.callout と書くと .content.callout のように展開される..content .callout.content.callout の違いは,セレクターが階層で出現するか,同時に出現するかの違いとなる.

$ sass application.scss --style expanded
.content {
  border: 1px solid #ccc;
  padding: 20px;
}
.content .callout {
  border-color: red;
}
.content.callout {
  border-color: green;
}

hover などの状態を表現するときに & を1番よく使う.

a {
    color: #999;
    &:hover {
        color: #777;
    }
    &:active {
        color: #888;
    }
}

このように,展開することができる.

$ sass application.scss --style expanded
a {
  color: #999;
}
a:hover {
  color: #777;
}
a:active {
  color: #888;
}

1.7 Nesting Pitfalls

  • ネストしすぎると可読性が悪くなる
  • 3,4階層になったらリファクタリングを検討する

"Sass Basics" を読んだ

「Code School : Assembling Sass」を受講した後は,公式ドキュメントの「Sass Basics」を読みながら他の機能を試した.気になったポイントをザッとまとめる.

sass-lang.com

sass --watch

コンパイル結果を標準出力に表示することもできるけど,アウトプットファイルを指定すると,コンパイル結果を書き出すことができる.さらに --watch を使うと,SCSS を更新したら自動的にコンパイルできるようになる.また,コンパイル時に --style expanded を付けると,カッコの位置なども見やすく表示される.

$ sass --watch app/sass:public/stylesheets
$ sass --style expanded --watch app/sass:public/stylesheets

Mixin

Mixin の考え方が Sass にもあると知れて良かった.

@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
     -moz-border-radius: $radius;
      -ms-border-radius: $radius;
          border-radius: $radius;
}

.box { @include border-radius(10px); }

上記のように @mixin で Mixin を定義して @include で読み込むことができる.また引数を渡すことができるため,汎用的な Mixin を作ることもできる.

継承

Mixin とは異なり,階層関係が成り立つ場合は継承を使う.

%message-shared {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

.message {
  @extend %message-shared;
}

"ドットインストール" を見た

最後にドットインストールを見たところ,Code School のカリキュラムにも含まれていた Sass の機能も紹介されていて,参考になった.

  • @for
  • @while
  • @each
  • @function

特に色を変更する関数 lighten()darken() は非常に便利そうだった.以下のように割合を指定すると,自動的に色を変更してくれる.ただエンジニアの観点だと便利だけど,デザイナーの観点だと計算すると逆に読みにくくなる可能性もありそう.

$color: #ff0000;

p {
  color: lighten($color, 30%);
}
$ sass application.scss --style expanded
p {
  color: #ff9999;
}

ドキュメントを読むと,他にも多くの関数が用意されていた!おおー.

まとめ

  • 今さらながら Sass に入門した
    • 今回は "Code School" と "ドキュメント" と "ドットインストール" を活用した
  • オブジェクト指向のプラクティスを CSS に適用できるのは非常に良かった

受付を担当した「Redash Meetup #1」開催レポート

レポート記事を書くのが少し遅くなってしまったけど,今週火曜に id:ariarijp と一緒に「Redash Meetup #1」を開催した😃

redash-meetup.connpass.com

「Redash Meetup #1」と言っても「Redash Meetup コミュニティ」としては3回目の開催で,過去2回はハンズオンイベントだった.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

運営

今回も id:ariarijp に頼りっぱなしで,connpass 運営も当日の設営も,ほぼ全てやってもらった.なのに登壇もされていて,コミュニティに対する姿勢が素晴らしいなと思う.本当にお疲れさまです💪

今回僕は受付を担当していた.遅れて来る人もいるかなーと思って,ずっと受付に座って待っていたので,登壇をじっくり聞くことができなかったし,参加者の皆さんとお話することもできなかったのは少し残念だった.当日キャンセルはあるだろうなーと思っていたけど,無断キャンセルもそこそこ多かった...!うううー

Redash 導入事例から考える OSS BI 導入チェックリスト @ariarijp

Redash を導入して,データ分析の権威化を民主化した素晴らしい事例だった.段々と Redash の依存度が高くなり,Redash に障害が起きるとどこかしらの業務に支障が出るという話もあるあるな感じ.Redash に限らず,流行りのツールを導入するのは簡単だけど,普及させるのは難しく,そのためにも「導入チェックリスト」を意識しておくと良さそう.Redash 関連のネタをたくさん持っているのに,あえて正攻法な話題で登壇されているあたりに余裕を感じた.次は LT を!

speakerdeck.com

ジモティーでの Redash 利用事例 @kyoshida

Redash のプルリクを眺めていると,よく見る @kyoshida さんの登壇だった.おー!有名コミッターだ!という感じ.プロフィール画像を表示できるようにしたり,Fork 機能を修正したり,実際に運用しながら困った部分に対してコントリビュートされているプロセスが非常に良かった.40人なのに「クエリ数 2300」は相当多いと思うなー!僕のところもまだ 500 以下なのに.あと「社内 Redash 勉強会」を開催されたという話はもっと深く聞いてみたかった.

speakerdeck.com

僕と Redash と Athena @dyuju_you

Athena でよくある「クエリ破産」の課題に対して,「LIMIT」と「PARTITION」の制約を実装して改善された話だった.特に「PARTITION」に関しては Glue のカタログ情報を参照できるように機能改善をされていて,なるほど勉強になる!

github.com

(資料公開待ち)

Redash ユーザーのための Metabase 入門 @manabusakai

約1年振りに @manabusakai さんに会えた!というのがまず嬉しかった.そして,最近よく耳にするようになった Metabase の紹介とデモの発表で,非常に流れが良かった.SQL を書かずに Question で GUI を作っていくあたり,エンジニアじゃなくても気軽に使える可能性もありそう.気になるぞ!

speakerdeck.com

Redash v4

1週間前に Redash v4 Beta のアナウンスがあり,正式リリースの日が近付いてきた.デザインも大幅に変わり,久し振りに大きなアップデートになると思う.また,ほんの少しながらコントリビュートをしたので,アナウンスにアカウント名を書いて頂くことができて,感動!もっともっと使って,コントリビュートを続けていくぞー🎉

discuss.redash.io

なお,引き続き好評の「Redash ハンズオン」も Redash v4 に対応する予定で,そろそろ準備を進めないと...!

github.com

関連記事

既に多くの参加レポートが公開されていて,非常に嬉しい!

ariarijp.hatenablog.com

techblog.oscasierra.net

medium.com

blog.zuckey17.org

Vue.js の基礎を学ぶために LearnCode.academy の学習動画を活用したら最高だった

LearnCode.academy とは?

www.youtube.com

LearnCode.academy という YouTube チャンネルがあり,Vue.js や React + Redux などを解説した,無料の学習動画が公開されている.今回受講したのは「Vue Tutorial」で,全9回となっている.合計しても「約1時間程度」なので,スキマ時間を活用して気軽に学ぶこともできる.「Vue.js は気になるけどまだ試したことがない」という人にオススメ!

  • Vue Tutorial #1 - Vue JS Tutorial for Beginners #1 setting up an app
  • Vue Tutorial #2 - Vue.js filters and computed data
  • Vue Tutorial #3 - Vue.js directives and event listeners
  • Vue Tutorial #4 - Break up your app into Vue Components
  • Vue Tutorial #5 - AJAX data and Lifecycle Methods
  • Vue Tutorial #6 - Full REST Example
  • Vue Tutorial #7 - Scaling Vue with Single File Components
  • Vue Tutorial #8 - Vue Router
  • Vue Tutorial #9 - Scaling Vue.js Data with Stores

なお,動画の中で実装されているコードは全て GitHub に公開されているので,動画を見ながら写経しても良いし,最初に Vue.js アプリケーションを動かしてから動画を見ることもできる.

github.com

Vue Tutorial #1

まず,雛形となる index.html に,マウントポイントとなる div を作成した.

<div id="app"></div>

次に,Vue インスタンスを作成する.

  • el ... マウントポイントとなる要素のセレクター
  • data ... 処理するデータオブジェクト
  • template ... テンプレート

Vue.js のテンプレートは Mustache 構文になっているので {{john.name}} のように書けば,データオブジェクトの値を反映することができる.

const app = new Vue({
  el: "#app",
  data: {
    bobby: {
      name: "Bobby Boone",
      age: 25
    },
    john: {
      name: "John Boby",
      age: 35,
    }
  },
  template: `
    <div>
      <h2>Name: {{john.name}}</h2>
      <h2>Age: {{john.age}}</h2>
      <h2>Name: {{bobby.name}}</h2>
      <h2>Age: {{bobby.age}}</h2>
    </div>
  `
})

www.youtube.com

Vue Tutorial #2

複雑なロジックはテンプレートに書くのではなく,computed を使って共通化できる.すると {{bobbyFullName}} のように書けるようになる.

const app = new Vue({
  (中略)
  computed: {
    bobbyFullName() {
      return `${this.bobby.first} ${this.bobby.last}`
    },
    johnFullName() {
      return `${this.john.first} ${this.john.last}`
    }
  },
  (中略)
})

ただし,これだとオブジェクトのデータごとに書く必要があるため,filters を使ってさらに共通化できる.すると {{bobby | fullName}} のように書けるようになる.これは bobby というデータオブジェクトを fullName にパイプで渡しているイメージになる.

const app = new Vue({
  el: "#app",
  data: {
    bobby: {
      first: "Bobby",
      last: "Boone",
      age: 25
    },
    john: {
      first: "John",
      last: "Boone",
      age: 35,
    }
  },
  computed: {
    johnAgeInOneYear() {
      return this.john.age + 1;
    }
  },
  filters: {
    ageInOneYear(age) {
      return age + 1;
    },
    fullName(value) {
      return `${value.last}, ${value.first}`;
    }
  },
  template: `
    <div>
      <h2>Name: {{john | fullName}}</h2>
      <h2>Age: {{john.age | ageInOneYear}}</h2>
      <h2>Name: {{bobby | fullName}}</h2>
      <h2>Age: {{bobby.age | ageInOneYear}}</h2>
    </div>
  `
})

www.youtube.com

Vue Tutorial #3

次は v-for ディレクティブを使って,配列のデータオブジェクトを表示することができた.

<div>
  <h2 v-for="friend in friends">{{friend | fullName}}</h2>
</div>

さらに v-model ディレクティブを使うと,自動的に値を書き換えるフォームを作ることができた.これはスゴイ!公式ドキュメントを読んだら,v-modelv-bind:valuev-on:input のシンタックスシュガーと書いてあった.

<div>
  <h2 v-for="friend in friends">
    <h4>{{friend | fullName}}</h4>
    <input v-model="friend.first"/>
    <input v-model="friend.last"/>
  </h2>
</div>

最後は v-on:click でボタンにイベントをバインドした.なお,公式ドキュメントに computedmethods の違いはキャッシュで,計算結果をキャッシュできる場合は computed を使うべきと書いてあった.

vuejs.org

const app = new Vue({
  (中略)
  methods: {
    decrementAge(friend) {
      friend.age = friend.age - 1;
    },
    incrementAge(friend) {
      friend.age = friend.age + 1;
    },
  },
  template: `
    <div>
      <h2 v-for="friend in friends">
        <h4>{{friend | fullName}}</h4>
        <h5>age: {{friend.age}}</h5>
        <button v-on:click="decrementAge(friend)">-</button>
        <button v-on:click="incrementAge(friend)">+</button>
        <input v-model="friend.first"/>
        <input v-model="friend.last"/>
      </h2>
    </div>
  `
})

www.youtube.com

Vue Tutorial #4

Vue コンポーネントを使うと,Vue インスタンスの定義をさらに細分化することができる.ただし,Vue コンポーネントの中のデータは外部から参照できないため,子コンポーネント側で props オプションを使って,親コンポーネントからデータオブジェクトを受け取る必要がある.Vue.js で画面設計をするときに,Vue コンポーネント設計が重要になるという話がよくわかった.

Vue.component('friend-component', {
  props: ['friend'],
  filters: {
    ageInOneYear(age) {
      return age + 1;
    },
    fullName(value) {
      return `${value.last}, ${value.first}`;
    }
  },
  methods: {
    decrementAge(friend) {
      friend.age = friend.age - 1;
    },
    incrementAge(friend) {
      friend.age = friend.age + 1;
    },
  },
  template: `
    <div>
      <h4>{{friend | fullName}}</h4>
      <h5>age: {{friend.age}}</h5>
      <button v-on:click="decrementAge(friend)">-</button>
      <button v-on:click="incrementAge(friend)">+</button>
      <input v-model="friend.first"/>
      <input v-model="friend.last"/>
    </div>
  `
});

const app = new Vue({
  (中略)
  template: `
    <div>
      <friend-component v-for="item in friends" v-bind:friend="item" />
    </div>
  `
})

www.youtube.com

Vue Tutorial #4 が完了した段階で,以下のようなアプリケーションが実装できた.

f:id:kakku22:20180218050849p:plain

(画面イメージ)

Vue Tutorial #5 & Vue Tutorial #6

Vue インスタンスの el を削除しても,コンソールで app.$mount("#app") と実行すれば手動でマウントできることを試した.そして,Vue インスタンスには多くのライフサイクルがあり,例として beforeMountmounted を学んだ.今回は fetch() を使って API を呼び出し,その結果をデータオブジェクトとして利用する一般的な構成を作成した.

また,データを削除する場合は,添字を指定してデータオブジェクトから削除することで,リアクティブに反映される.関連するディレクティブで言えば,v-on:click だけではなく v-on:keyup.13 を使って Enter 押下のイベントを取得したり,v-ifv-else を使ってテンプレートの分岐なども書けた.

const app = new Vue({
    el: "#app",
    data: {
      editFriend: null,
      friends: [],
    },
    methods: {
      deleteFriend(id, i) {
        fetch("http://rest.learncode.academy/api/vue-5/friends/" + id, {
          method: "DELETE"
        })
        .then(() => {
          this.friends.splice(i, 1);
        })
      },
      updateFriend(friend) {
        fetch("http://rest.learncode.academy/api/vue-5/friends/" + friend.id, {
          body: JSON.stringify(friend),
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
          },
        })
        .then(() => {
          this.editFriend = null;
        })
      }
    },
    mounted() {
      fetch("http://rest.learncode.academy/api/vue-5/friends")
        .then(response => response.json())
        .then((data) => {
          this.friends = data;
        })
    },
    template: `
    <div>
      <li v-for="friend, i in friends">
        <div v-if="editFriend === friend.id">
          <input v-on:keyup.13="updateFriend(friend)" v-model="friend.name" />
          <button v-on:click="updateFriend(friend)">save</button>
        </div>
        <div v-else>
          <button v-on:click="editFriend = friend.id">edit</button>
          <button v-on:click="deleteFriend(friend.id, i)">x</button>
          {{friend.name}}
        </div>
      </li>
    </div>
    `,
});

www.youtube.com

www.youtube.com

Vue Tutorial #7

ここから少し難易度が上がり,vue-cli + webpack で Vue.js の環境構築をしながら「単一ファイルコンポーネント」を学んだ.具体的には Tutorial 4 で学んだ Vue コンポーネントを .vue という拡張子のファイルに分割していくことになる.このときに,Vue コンポーネントの中にスタイルも含めるという考え方は個人的には新鮮だった.確かにスタイルまで揃ってこそのコンポーネントだからスッと理解できた.ただし,コンポーネントが増えてくるとスタイルを共通化したくなる未来もありそうで,そのあたりは外部ファイルを読み込むことになるらしく,公式ドキュメントにも書かれていた.またコンポーネント間でスタイルが競合する場合は <style scoped> でスコープを狭めることができる.

vuejs.org

以下に App.vue を載せておく.他のコードは GitHub を参照してもらえればと!

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <HelloWorld/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

www.youtube.com

Vue Tutorial #8

次は Vue Router を使って SPA を実装した.SPA のルーティングなので,基本的にはハッシュイベント(URL 末尾の #)をルーティングする.今回書いた router/index.js は以下のようになる.

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Account from '@/components/Account'
import Contact from '@/components/Contact'
import Friends from '@/components/Friends'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: HelloWorld
    },
    {
      path: '/friends/:id/:age/:weight',
      name: 'Friends',
      props: true,
      component: Friends
    },
    {
      path: '/contact',
      name: 'Contact',
      component: Contact
    },
    {
      path: '/account',
      name: 'Account',
      component: Account
    }
  ]
})

なお,Vue コンポーネント側でルーティングパラメータは {{$route.params.id}} のように取得できるけど,以下のように props で定義してしまう方法もある.

<template>
  <div>
    <h1>Friends</h1>
    {{id}}
    {{age}}
    {{weight}}
  </div>
</template>

<script>
export default {  
  props: [
    'id',
    'age',
    'weight',
  ]

}
</script>

www.youtube.com

Vue Tutorial #8 が完了した段階で,以下のようなアプリケーションが実装できた.

f:id:kakku22:20180218050925p:plain

(画面イメージ)

Vue Tutorial #9

最後は Vue.js で Store パターンを実装した.以下のような stores/FriendStore.js を用意して,データオブジェクトの操作を Store に閉じ込めている.このあたりは一般的なアーキテクチャなので,特に悩む部分はなかった.今回の Tutorial 対象ではないけど,Flux / vuex の実装は試してみたいと思う.

const FriendStore = {
  data: {
    friends: ["bobby", "billy"],
  },
  methods: {
    addFriend(name) {
      FriendStore.data.friends.push(name);
    }
  }
};

export default FriendStore;

あとは Vue コンポーネントから Store を呼び出せば,あとはリアクティブに実装ができる.

<template>
  <div>
    <h1>My Friends</h1>
    <li v-for="friend in FriendStore.friends">{{friend}}</li>
    <input v-model="newFriend" v-on:keyup.13="addFriend(newFriend)" />
  </div>
</template>

<script>
import FriendStore from "../stores/FriendStore"

export default {
  data() {
    return {
      newFriend: null,
      FriendStore: FriendStore.data,
    };
  },
  methods: {
    addFriend(name) {
      FriendStore.methods.addFriend(name)
      this.newFriend = null;
    }
  }
}
</script>

www.youtube.com

Vue Tutorial #9 が完了した段階で,以下のようなアプリケーションが実装できた.

f:id:kakku22:20180218050939p:plain

(画面イメージ)

まとめ

  • LearnCode.academy「Vue Tutorial」を受講して,はじめて Vue.js を試してみた
  • 「Vue.js は気になるけどまだ試したことがない」という人にオススメ!
  • MVVM な設計,コンポーネント思想,便利な Vue ディレクティブなど,Vue.js を採用するメリットを感じることができた
  • 公式ドキュメントも,日本語ドキュメントも,非常に詳しく書かれていて素晴らしかった

開発ツールなど

今回はじめて Vue.js を書いたので,まだ深く使えていないけど,VS Code + Vetur でコードを書いて,デバッグのときは Chrome 拡張の vue-devtools を使った.

github.com

github.com

関連記事

jQuery を活用して SPA を実装するのを学ぶには「サーバーレスシングルページアプリケーション」もオススメ!

kakakakakku.hatenablog.com

多くの NoSQL に対応したベンチマークツール YCSB を試した

YCSB とは?

YCSB (Yahoo! Cloud System Benchmark) は,NoSQL / KVS に特化したベンチマークツールで,とにかく多くのデータストア(計40種類程度)をサポートしている.例えば以下など.最近 Memcached のベンチマーク目的で使うことがあったため,まとめておく.

  • Aerospike
  • Cassandra
  • DynamoDB
  • Elasticsearch
  • Memcached
  • MongoDB
  • Redis
  • Riak

github.com

YCSB 概要

コマンドタイプ

YCSB には2種類のコマンドタイプがある.load はロード系のベンチマークで,run は参照系のベンチマークになる.

$ ./bin/ycsb.sh load
$ ./bin/ycsb.sh run

ワークロードテンプレート

YCSB にはデフォルトで6種類のワークロードテンプレートが用意されている.

$ ls -1 workloads/workload[a-z]
workloads/workloada
workloads/workloadb
workloads/workloadc
workloads/workloadd
workloads/workloade
workloads/workloadf

ワークロード名だけを見てもよくわからなかったけど,実際の定義を見ると以下のように分類できる.

ワークロード名 概要
workloada Read 50% / Update 50%
workloadb Read 95% / Update 5%
workloadc Read 100%
workloadd Read 95% / Insert 5%
workloade Scan 95% / Insert 5%
workloadf Read 50% / Read Modify Write 50%

より詳細な違いはドキュメントを見るとわかる.

ただし,ワークロードテンプレートの初期値は以下のようになっていて,負荷が低く設定されている.

  • recordcount=1000
  • operationcount=1000

よって,ここはコマンドで上書きして実行することができる(以下はコマンド例).

$ ./bin/ycsb run memcached -P workloads/workloadc -p "memcached.hosts=memcached" -p 'operationcount=100000'

繰り返し実行する場合は,独自ワークロードファイルを作ることもできる.詳しくはドキュメントに載っている.

ランタイムパラメータ

ワークロードとは別にランタイムパラメータを指定することもできる.

  • -threads
    • スレッド数
    • デフォルトはスレッド 1 なので,ベンチマークのときはもっと増やす
  • -target
    • 秒間の処理数
    • デフォルトは可能な限り性能を出すようになっている
  • -s
    • ステータス表示
    • 10秒おきにベンチマークのステータスが表示される

詳しくはドキュメントに載っている.

ベンチマーク結果

Wiki から引用すると,以下のような結果が出力される.ベンチマークの目的にもよるけど,一般的には [OVERALL],Throughput(ops/sec) と,各操作の AverageLatency(ms)MinLatency(ms)MaxLatency(ms) あたりを見ておくと良さそう.

[OVERALL],RunTime(ms), 10077
[OVERALL],Throughput(ops/sec), 9923.58836955443
[UPDATE], Operations, 50396
[UPDATE], AverageLatency(ms), 0.04339630129375347
[UPDATE], MinLatency(ms), 0
[UPDATE], MaxLatency(ms), 338
[UPDATE], Return=0, 50396
[UPDATE], 0, 0.10264765784114054
[UPDATE], 2000, 0.026989343690867442
[UPDATE], 4000, 0.0352882703777336
[UPDATE], 6000, 0.004238958990536277
[UPDATE], 8000, 0.052813085033008175
[UPDATE], 10000, 0.0
[READ], Operations, 49604
[READ], AverageLatency(ms), 0.038242883638416256
[READ], MinLatency(ms), 0
[READ], MaxLatency(ms), 230
[READ], Return=0, 49604
[READ], 0, 0.08997245741099663
[READ], 2000, 0.02207505518763797
[READ], 4000, 0.03188493260913297
[READ], 6000, 0.004869141813755326
[READ], 8000, 0.04355329949238579
[READ], 10000, 0.005405405405405406

YCSB Memcached binding インストール

GitHub Releases は最近更新されていないため,自分でビルドする.今回は Amazon Linux で Memcached にベンチマークを実行するための環境構築を試した.ただし,AWS では侵入テストだけではなく,負荷テストも事前申請が必要になることがある.最悪の場合はネットワークを遮断されることもあるので,気軽に実行せず,注意すること.

インストール手順は GitHub の通りに進めることができた.Maven は現時点で最新の 3.5.2 にした.

$ wget http://ftp.tsukuba.wide.ad.jp/software/apache/maven/maven-3/3.5.2/binaries/apache-maven-3.5.2-bin.tar.gz
$ sudo tar xzf apache-maven-*-bin.tar.gz -C /usr/local

(中略)

$ git clone https://github.com/brianfrankcooper/YCSB.git
$ cd YCSB
$ mvn -pl com.yahoo.ycsb:memcached-binding -am clean package

YCSB Memcached binding 実行

あとは想定するワークロードでベンチマークを実行する.以下にサンプルを載せておく.

  • workloadc (Read 100%)
    • threads 10
      • 操作回数 : 100000
      • 秒間 : 3000
      • 秒間 : 10000
      • 秒間 : 100000
    • threads 1024
      • 操作回数 : 100000
      • 秒間 : 3000
      • 秒間 : 10000
      • 秒間 : 100000
$ ./bin/ycsb run memcached -threads 10 -target 3000 -P workloads/workloadc -p "memcached.hosts=memcached" -p operationcount=100000
$ ./bin/ycsb run memcached -threads 10 -target 10000 -P workloads/workloadc -p "memcached.hosts=memcached" -p operationcount=100000
$ ./bin/ycsb run memcached -threads 10 -target 100000 -P workloads/workloadc -p "memcached.hosts=memcached" -p operationcount=100000
$ ./bin/ycsb run memcached -threads 1024 -target 3000 -P workloads/workloadc -p "memcached.hosts=memcached" -p operationcount=100000
$ ./bin/ycsb run memcached -threads 1024 -target 10000 -P workloads/workloadc -p "memcached.hosts=memcached" -p operationcount=100000
$ ./bin/ycsb run memcached -threads 1024 -target 100000 -P workloads/workloadc -p "memcached.hosts=memcached" -p operationcount=100000

まとめ

  • NoSQL / KVS に特化したベンチマークツール YCSB を試した
  • YCSB は Memcached / Redis / DynamoDB など,多くのデータストアをサポートしている
  • ワークロードも柔軟に設定することができる
  • 大規模なベンチマークをする場合は,負荷テストの事前申請をしておくこと

Mackerel Meetup #11 で「ECS モニタリング」の事例紹介をしてきた

Mackerel Meetup #11 に参加して,コンテナ関連の事例紹介をしてきた.参加レポートを書く!(全ての資料が公開されたら追記する予定)

mackerelio.connpass.com

The 2018 Mackerel Product Roadmap

  • 最近リリースしたオススメ機能
    • アクション支援
    • プラグインレジストリ
    • イベント通知
    • キーボードショートカット
    • 公開グラフ
  • ロードマップ
    • アラートグループ
    • コンテナサポート
    • カスタムダッシュボード V2
    • 機械学習の活用
    • Prometheus Affinity

非常にワクワクする発表だった.「コンテナサポート」はとにかく期待で,課金体型の見直しだけじゃなく,コンテナフレンドリーな仕組みでリリースされると良いなと思う.あと「カスタムダッシュボード V2」も気になる.

speakerdeck.com

AWS で実現した Mackerel 時系列データ1分粒度長期保存の裏側

Diamond の話は何度聞いてもキレイなアーキテクチャだなと思う.データストアとして,Redis と DynamoDB と S3 を活用しているという話で,DynamoDB のアイテムに TTL を付与して,有効期限が切れるタイミングで Lambda を起動して,S3 に保存する.また,S3 に高頻度で書き込むときにも,キーを分散させたり,ウォームアップを申請したり,リクエスト数をモニタリングするなど,知見だった.

speakerdeck.com

seesaa meets Mackerel

  • オンプレ時代には独自のツールで監視をし,運用担当が張り付いていた
    • 過去のメトリクスを残す作りになってなかったり,ツール自体の負荷が高くなったり
  • Mackerel を導入して運用不可を
  • Mackerel Day の事例紹介が刺さった
  • プリンタなどのオフィス機器もモニタリングしている

speakerdeck.com

Mackerel で ECS をどこまでモニタリングできるのか

今回「コンテナ関連の事例紹介をして欲しい」と話を頂いていたので,運用中の ECS モニタリングの話,そして今後の展望として Fargete モニタリングの話をした.勉強会のスケジュールが全体的に押していたので,遅れを取り戻すために超早口で話した結果,前提知識がないと理解が追い付かないような雰囲気になってしまって反省している.

そもそも「ECS 使ってる人はいますか?」と聞いたら半分以下で,そうなの?という気持ちだったし,ロードマップのところで「コンテナサポート」の発表があったので,新機能がリリースされたらオワコンになる事例に興味を持ってもらえるのだろうか?という感じで,直前で不安になったという背景もある.それでも懇親会では参考になったと言ってもらえたりして,救われた感がある.

speakerdeck.com

発表の中でも紹介した「新 ECS モニタリング」の仕組みは以下の記事に詳しく書かれている.現在運用している仕組みは微妙な点が多くあるので,近々作り直したいなと思っている.

okzk.hatenablog.com

まとめ

  • ロードマップは非常にワクワクする内容だった
    • 特に「コンテナサポート」と「Prometheus Affinity」に期待
  • ECS モニタリングの事例紹介をした
    • 資料をしっかりと作ったので,少しでも参考になれば嬉しい

関連記事

公式ブログにレポートが出てる!

mackerel.io

ElastiCache ではなくて Redis Cluster on EC2 で運用している理由も書かれてた!(懇親会で聞きたかったけど聞けなかった)去年末にオンラインリサイズ機能がリリースされてるから,ElastiCache 3.2.10 を使えば無停止にシャードを増やせるはず.

astj.hatenablog.com

詳しくまとまってる!僕の発表は別記事に...?w

dev.classmethod.jp