kurosame’s diary

フロントエンド中心です

Digdagのワークフロー実行時に見るテーブル

今やっていること

Digdagのキューを効率良く処理させたいため、digdag serverを動かすEC2のAuto Scaling Groupを構築し、その上でDigdagを動かしてみた

この時にキューの処理状況を見たいので、データベースを見たのだが、けっこうテーブルが多い。。 でもたぶん以下の2テーブルだけ見ておけば、大丈夫そうな気がしたので、簡単にメモっとく

queued_tasks

このテーブルで今どのくらいキューが溜まっているか見れる
タスク単位のキューが見れる
タスクが完了すると、そのキューは削除される

tasks

DigdagUI上のTasksとリンクしており、ワークフロー内のタスクのステータスを見ることができる
タスクを処理していくとstateカラムが随時更新されていく
AttemptIDごとに全てのタスクを消化するとテーブルからデータが削除される

ステータスの一例
7: Success
5: Planned
4: Running
0: Blocked
など

React Hooks について [ Basic Hooks編 ]

reactjs.org こちら公式サイトで Basic Hooks と呼ばれてる useState と useEffect と useContext のみ実装してみます
Additional Hooks については、また今度にしますが、useReducer など Redux の reducer のような機能もあって面白そうです

まだ Hooks は v16.7 の α 版の機能なので、以下を実行

yarn add react@16.7.0-alpha.0 react-dom@16.7.0-alpha.0 -D

今回作成したコードは以下のリポジトリにあります github.com ベースに使用したボイラープレートが TSX でしたが、今回の Hooks は TypeScript で書いてないです

useState

Function Component で State を扱えるようになる
useState に値を渡すとそれを初期値にしたStateそのStateを更新する関数を配列で返す

import React, { useState } from 'react'

const UseState = () => {
  const [count, setCount] = useState(1)
  return (
    <div>
      <p>########## UseState ##########</p>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <p>########## UseState ##########</p>
    </div>
  )
}

export default UseState

useEffect

React のライフサイクル関数の代わりとなるもの
useEffect の第 1 引数に実行する関数、第 2 引数に変更を watch する要素を配列で追加する
第 2 引数に指定した配列内の要素のいずれかが更新されたら、第 1 引数の関数を実行する

import React, { useEffect, useState } from 'react'

const UseEffect = () => {
  const [effect1, setEffect1] = useState(0)
  const [effect2, setEffect2] = useState(0)
  const [effect3, setEffect3] = useState(0)
  const [count, setCount] = useState(0)

  useEffect(() => setEffect1(effect1 + 1))
  useEffect(() => setEffect2(effect2 + 1), [count])
  useEffect(() => setEffect3(effect3 + 1), [])

  return (
    <div>
      <p>########## UseEffect ##########</p>
      <p>Effect1: {effect1}</p>
      <p>Effect2: {effect2}</p>
      <p>Effect3: {effect3}</p>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <p>########## UseEffect ##########</p>
    </div>
  )
}

export default UseEffect

effect1 は、useEffect で第 2 引数を渡してないので、常に第 1 引数の関数が呼ばれ続ける
⇒ このような使い方は通常やらないと思う

effect2 は、useEffect で第 2 引数に count を渡しているので、count が変更された時のみ第 1 引数の関数を呼び出す
⇒ componentDidMount + componentDidUpdate の呼び出しのように使えそう

effect3 は、useEffect で第 2 引数に空配列を渡しており、最初のマウント時のみ第 1 引数の関数を呼び出す
⇒ componentDidMount の呼び出しのように使えそう

useContext

Context を利用するための Hook

ContextAPI の Provider にセットした State を useContext で受け取ってみます

import React, { useContext } from 'react'

const Context = React.createContext()
const { Provider } = Context

// Function Component での Provider の作り方の正解がよく分からないので、一旦 class を使っている
class SetProvider extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 2
    }
  }

  render() {
    return (
      <Provider value={{ state: this.state }}>
        <UseContext />
      </Provider>
    )
  }
}

const UseContext = () => {
  const context = useContext(Context)

  return (
    <div>
      <p>########## UseContext ##########</p>
      <p>Context.count: {context.state.count}</p>
      <p>########## UseContext ##########</p>
    </div>
  )
}

export default SetProvider

React の Context API について

ContextAPI

  • v16.3 から追加された機能
  • React のみでいい感じの State 管理ができる
  • Redux とは別の選択肢ができただけと思って良い認識

従来の State 受け渡し

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 1
    }
  }

  render() {
    return (
      <div>
        親:
        {this.state.count}
        <Child count={this.state.count} />
      </div>
    )
  }
}

const Child = props => (
  <div>
    子:
    {props.count}
    <Grandchild count={props.count} />
  </div>
)

const Grandchild = props => (
  <div>
    孫:
    {props.count}
  </div>
)

ReactDOM.render(<Parent />, document.querySelector('#app'))

結果

f:id:kurosame-th:20181105172314p:plain

ContextAPI を使った State 受け渡し

const { Provider, Consumer } = React.createContext()

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 2
    }
  }

  render() {
    return (
      <Provider value={{ state: this.state }}>
        <div>
          親:
          {this.state.count}
          <Child />
        </div>
      </Provider>
    )
  }
}

const Child = () => (
  <div>
    <Grandchild />
  </div>
)

const Grandchild = () => (
  <Consumer>
    {({ state }) => (
      <div>
        孫:
        {state.count}
      </div>
    )}
  </Consumer>
)

ReactDOM.render(<Parent />, document.querySelector('#app'))

結果

f:id:kurosame-th:20181105173941p:plain

今回は State のみだったが、Action も同じように渡せる

考察

  • Redux でやってたことは普通に実現できそう
  • よく言われているが、小規模であれば Context API はありだが、大規模であれば Redux 等を使った方が良さそう
    • Provider が肥大化すると、メンテナンス性が低そう。ネストもするので、可読性も悪い

Spark チューニングメモ

チューニングした所

EMR クラスターを作ってる所

aws emr create-clusterしてる所で、渡すオプションを変えてみる

maximizeResourceAllocation を変えたりは、あまり効果なし

maximizeResourceAllocation は
maximizeResourceAllocation オプションを true にすることで、クラスター内の各ノードでリソース最大限に使用できるようにエグゼキュターを設定することができます。
らしい

Spark の実行オプションを変えてみる

spark-submit のオプションを変えてみる

この辺中心に色々変えたけど、あまり効果なし
--num-executors 2 \
--executor-cores 3 \
--executor-memory 12G \

num-executors は Executor の個数
executor-cores は 1Executor の CPU コア数
executor-memory は 1Executor のメモリ

一応 Driver のも少し変えたりしたけど、効果なし
--driver-cores 1 \
--driver-memory 5G \

Spark を Scala で書いているが、Scala コード自体のチューニングを見直す必要があるのだろうか