お元気そうで残念です

仕事とか趣味のメモを残します

Ubuntu Server 18.04 LTS にemacs 26.1をインストール

継続日数とか出せることに気づいたので気が向く限り継続しようかと思います。

タイトルのことをしたい場合はこちらのサイトが参考になります。

Install EMACS 26.1 on Ubuntu | AdminTome Blog

コマンドだけ抜き出したものがこちら。

sudo apt update && apt upgrade -y
sudo apt install build-essential libncurses-dev
wget http://mirrors.syringanetworks.net/gnu/emacs/emacs-26.1.tar.gz
tar -xvf emacs-26.1.tar.gz
cd emacs-26.1/
./configure --without-x --with-gnutls=no
make
sudo make install

このくらいの簡単な備忘録で数を稼ぐ作戦です。 それでは。

ちょっと使いやすくしたcutコマンド作成中

この記事はGo2 Advent Calendar 2018 - Qiitaの5日目の穴埋めエントリーです。

ApacheやHAproxyのログからgnuplotのグラフを生成するために、cutやawk, sedなどを組み合わせて使っているのですが、
そもそもcutでフィールド指定した順番どおりに出力できればawkを挟む必要がなく
その分処理時間減らせるのにどうして出来ないのか!という個人的なニーズから作成中です。

github.com

使い方はこんな感じ。

% who | ucut -d " " -f 2,1,4,2 
console joniyjoniy Nov console 
ttys010 joniyjoniy Dec ttys010 

awkを使うとこうなります。やっぱり、-fで指定できたほうが直感的で分かりやすいですよね?(多分)

% who | cut -d " " -f 1,2,4 | awk '{print $2" "$1" "$3" "$2}'  
console joniyjoniy Nov console
ttys010 joniyjoniy Dec ttys010

フィールド指定の部分以外はcutと同じようにしようと思っていますが、現在は-d区切りで標準入力から受け付ける処理しか出来てません。

以上とても簡単な紹介ですが、現在Go言語を使って開発しているCLIツールucutを紹介しました。
冒頭で処理時間についてのニーズを上げたのに、ベンチマーク取れていませんが、出来上がってきたらベンチマーク取ってこの記事を更新する予定です。

gatlingでconstantUsersPerSecをだんだん増やすためにjinja2にお祈りに行ったときの道中のこぼれ話

周囲が負荷テストでgatlingを使い始めて、自分も使ってみようと思い勉強してみました。

以下のような感じで負荷を徐々に増やして徐々に減らすテストを組もうとしたら案外苦戦したのでメモっときます。 もっと良い方法があったら教えてください!

f:id:joniy_joniy:20180511002147p:plain

injection単体ではどうか

普通にinjectionでひょいっとできると思って調査しましたが、微妙にニュアンスが違っていてダメでした。 前半の徐々に増加する部分に絞ってなぜダメだったか触れていきます。

1. rampUsers(nbUsers) over(duration)

期間durationに渡ってnbUsers数のリクエストをランプ関数に従って発射するというもの。

rampUsers(100) over(10 seconds)

とすると、10秒間で均等にリクエストを発射して、合計100リクエストになるように発射してくれます。

実行すると以下のようになります。

均等にリクエストを割り振ってくれるので、だんだん増やすことはこれ単体ではできません。

あと、もしリクエストが詰まって一気に消化される場合などランプ関数で想定していたよりも早くnbUsers数のリクエストが裁かれてしまった場合、それ以上のリクエストは生成されません。ちょっとやりたいことと違う。 f:id:joniy_joniy:20180511003055p:plain

2. rampUsersPerSec(rate1) to (rate2) during(duration)

初期値rate1数のリクエストを、期間durationに渡って、ランプ関数に従ってrate2数のリクエストへ徐々に増やしていくというもの。

これでいいやん、って思ったのですが試してみると1の問題点と同様の問題がありました。

rampUsersPerSec(100) to 500 during(10 seconds)を実行した結果が以下になります。

00:45:59から100リクエストずつで始まり、00:46:09で500リクエストで終わることを期待していましたが、同時リクエスト数は500まで上がる前に終わってしまいました。上がりきる前に計算したリクエスト数が終わってしまったようです。ちょっとやりたいことと違う。 f:id:joniy_joniy:20180511005247p:plain

3. splitUsers(nbUsers) into(injectionStep) separatedBy(duration)

duration期間ずつ間を挟みながら、injectionStepを繰り返して合計のリクエスト数がnbUsersになるまで発射するというもの。

splitUsers(1000) into (rampUsers(10) over (10 seconds)) separatedBy (10 seconds)

このシナリオだと、10秒渡って10リクエストを投げた後、10秒休むを100回繰り返します。 やりたいこととはだいぶ違っちゃいますね。ちなみに、実行した結果は以下のようになりました。長かった。

f:id:joniy_joniy:20180511014839p:plain

4. splitUsers(nbUsers) into(injectionStep1) separatedBy(injectionStep2)

injectionStep2を挟みながら、injectionStep1を繰り返して合計のリクエスト数がnbUsersになるまで発射するというもの。

splitUsers(1000) into (rampUsers(10) over (10 seconds)) separatedBy atOnceUsers(30)

このシナリオだと、10秒渡って10リクエストを投げた後、ドバっと30リクエストを投げるを100回繰り返します。 これも違いますね。

5. constantUsersPerSec(rate) during(duration)

期間durationの間常にrate数のリクエストを発射し続けてくれるもの。 基本的にはこれがやりたいことを満たしていますが、徐々に増やすためには似たようなコードをペタペタする必要があるのでちょっと...。具体的には以下のような感じです。これでやりたいことは満たしていますが、間隔やリクエスト数を変えると毎回弄るのが面倒なので一工夫挟みたいところです。

var waveInjections = Seq(
      constantUsersPerSec(10) during (10 seconds),
      constantUsersPerSec(20) during (10 seconds),
      constantUsersPerSec(30) during (10 seconds),
      constantUsersPerSec(40) during (10 seconds),
      constantUsersPerSec(50) during (10 seconds),
  )

  setUp(
    scn.inject(waveInjections).protocols(httpConf))

constantUsersPerSec(rate) during(duration)を自動生成する

Scalaでやってみる

scalaでシナリオを書けるのでforなりwhileなりでSeqに追加していけばいいのではと試してみました。
Ansibleで実行したいホストに設置するので、変数はAnsibleからとってくるようにしています。

var MAX_ACCESS = "{{ max_access }}".toInt   
var START_ACCESS = "{{ start_access }}".toInt   
var EACH_ACCESS = "{{ each_access }}".toInt 
var SEC = "{{ duration }}".toInt

略
var nb = START_ACCESS
var waveInjections = Seq(constantUsersPerSec(START_ACCESS) during (SEC seconds))
while ( nb <= MAX_ACCESS ) {
  nb = nb + EACH_ACCESS
  waveInjections = waveInjections :+ constantUsersPerSec(nb) during (SEC seconds)
}

SetUp(scn.inject(waveInjections).protocols(httpConf))

実行してみるとvalue during is not a member of Seq[Product with Serializable]と怒られてしまいました。
この書き方ではダメなようですが、Scalaを書くのが初めてなのでどう直せば良いのか分からない...

Jinja2で生成してみる

ならば慣れ親しんている(?)jinja2テンプレートを使って生成したものを配置してみようとやってみました。

略
  var waveInjections = Seq(
    {% set second = [duration * each_access /max_access] %}
    nothingFor({{ second[0] }} seconds),
    {% set nb = [start_access] %}
    {% for _ in range(1, 100) %}
      {% if nb[0] == max_access %}
      {% break %}
      {% endif %}
      constantUsersPerSec({{ nb[0] }}) during ({{ second[0] }} seconds),
      {% set _ = nb.append(nb.pop() + each_access) %}
    {% endfor %}
      constantUsersPerSec({{ max_access }}) during ({{ wait }} seconds),
    {% set nb = [max_access - each_access] %}
    {% for _ in range(1, 100) %}
      {% if nb[0] < start_access %}
      {% break %}
      {% endif %}
      constantUsersPerSec({{ nb[0] }}) during ({{ second[0] }} seconds),
      {% set _ = nb.append(nb.pop() - each_access) %}
    {% endfor %}
    nothingFor({{ second[0] }} seconds),
  )

  setUp(scn.inject(waveInjections).protocols(httpConf))

生成されたものが以下になります。
やりたかったことはできましたが、ゴリ推した感が強いですね...。
Scala勉強して再チャレンジしたいと思います。

  var waveInjections = Seq(
        nothingFor(2.0 seconds),
        constantUsersPerSec(10) during (2.0 seconds),
        constantUsersPerSec(20) during (2.0 seconds),
        constantUsersPerSec(30) during (2.0 seconds),
        constantUsersPerSec(40) during (2.0 seconds),
        constantUsersPerSec(50) during (10 seconds),
        constantUsersPerSec(40) during (2.0 seconds),
        constantUsersPerSec(30) during (2.0 seconds),
        constantUsersPerSec(20) during (2.0 seconds),
        constantUsersPerSec(10) during (2.0 seconds),
        nothingFor(2.0 seconds),
  )

  setUp(scn.inject(waveInjections).protocols(httpConf))

追記

こう書けば普通に動くので、Scalaだけで完結できました。スッキリ

  var nb = START_ACCESS
  var waveInjections = Seq(constantUsersPerSec(nb).during(SEC seconds))
  while ( nb <= MAX_ACCESS ) {
    waveInjections = waveInjections :+ constantUsersPerSec(nb).during(SEC seconds)
    nb = nb + EACH_ACCESS
  }

参考文献

Gatling Simulation Setup
Gatlingを使った負荷試験
制御構文
AnsibleのJinja2を活用する