valid,invalid

関心を持てる事柄について

ISUCON11 ソロチームで参加して予選敗退しました

ISUCON11にソロチームBPM200で参加して予選敗退しました。

結果

  • 最終スコア: 13458
  • 最高スコア: 14484
  • 使用言語: Ruby

去年↓よりは1人でも戦えた気がしたものの順位上の結果としては大差なく終わってしまい残念。

ohbarye.hatenablog.jp

使用したツール

  • Vim
  • RubyMine
  • DataGrip
  • NewRelic
  • mysqldumpslow
  • top
  • git / GitHub

ちょっとしたコード変更はサーバ内でVimで書いてベンチマーカー回して良ければコミットして、複雑なコードの変更はRubyMine側でじっくり書いてからコミットするスタイル。

DBの中身を見たりクエリをExplainするのに最初はmariadbのREPLで頑張ってたのですが途中からDataGripでリモート接続して確認することにしました。クエリの補完や情報の見やすさなど、全てが圧倒的に優れているのでめっちゃ良かったです。

NewRelicは普段業務でも使うのでその延長で使わせてもらいました。スポンサー感謝です。

戦略

昨年と同じくソロなので時間は絶対に足りない、という前提のもと予めフォーカスするポイントはある程度決めておきました。

  • 1台構成でできるところまでやる
  • 素振りしてない計測ツールやプロファイラは使わない
  • アプリケーションのすべての仕様を理解しようとしない

振り返り

良かった点

  • 最初の環境構築の延長で使い慣れているツール(特にDataGrip)の設定をやった
  • めんどうなN+1のボトルネックから逃げずにSQLで勝負できた

良くなかった点

  • 全体的にアプリケーションコード側での解決に拘った
    • 12:30に9,000点まで伸ばせて前半の滑り出しは悪くなかったのですがそこからずっと伸び悩み
    • 多少時間をかけてでもNginxのチューニングや複数台構成に挑戦すべきところだったかなと思います(できたかどうかは別)

終了後に学んだこと

追試終了後の日曜以降に残った環境でいろいろ試してました。

  • APIとDBのサーバ分離
    • MySQLの設定周りでハマると思ったら意外とかんたんだったので素振りしておけばよかった
  • 繰り返し実行するコマンドをMakefile
    • サーバのrestartとかlogの削除とかそのへん。一人作業だからいいか…と言い訳して毎回typeしてたのですがMakefile書くぐらいはちゃんとやろう
  • NginxとAPIの通信をUnix domain socket化
    • 数字に効くのかはわからないのですが試しても良かった
  • kataribeやdstatなど使わなかった計測ツールの使い方を調べた
    • なにこれ、めっちゃ便利...ってなった

あと競技そのものとはあまり関係ないですがCloudFormationでの環境構築とても簡単で良かったですね。構成図を見たりしてました。

f:id:ohbarye:20210824001119p:plain
CloudFormationのDesignerから出力した図

すでに$17ぐらいかかっていたので気をつけよう…。


自分の引き出しが「API >> DB >>>>>> Nginx > インフラ周り」と偏り過ぎているのでボトルネックがわかっても打ち手が適切でなかったり、そもそも思いつかなかったりと、総合格闘技的な"力"不足を改めて感じるISUCONでした。

所感

2年連続でソロチームで出た所感としては、やはり、ISUCONはスキルポートフォリオの不足を知るとても良い機会だということです。

チームで出るならほとんどの場合は各自の得意領域で勝負をすることになると思うのですが、ソロなのでなんでも自分でやらなければいけない。そのぶんトラブルシューティング・課題発見・司令塔・問題解決力・実装力などすべてを合わせた総合格闘技力がモロに試されることになります。普段チームで開発しているとなかなか得難い体験だなと思います。

複数人で参加して効率重視で優勝を狙うところとは離れており*1、運営の意図とは異なるのかもしれませんがこのような楽しみ方ができるのもISUCONの好きなところです。

運営の皆様、本当にお疲れさまでした && ありがとうございました。


[おまけ] やったこと

ここからは競技時間内にやったことの羅列です。

環境構築: 1529

一人なのでまずは最初の1時間で落ち着いて開始できるように持っていくところ。

  • CloudFormationでの環境構築
  • サーバへのssh確認
    • 直前にマシンを交換してたので鍵がローカルになくてsshできずとても焦った
  • 環境チェッカーの実行
  • ローカルマシンのブラウザでアプリケーションが動いていることを確認
    • 去年はここを怠ったのでアプリケーションの挙動をコードから特性や仕様を理解しようとして時間を浪費した
  • git initしてGitHubにpush
  • 初期設定のままベンチマーカーを実行する

Ruby実装に切り替える: 4732

なぜか点が伸びた

[11:00] NewRelic導入: 1532

スッ...と下がった

NewRelicでmost time consumingが GET /api/trendとわかりました。

f:id:ohbarye:20210823001832p:plain
初期状態
ここまで一切コードリーディングしてなかったので、対象エンドポイントと周辺を読み始める。

N+1で明らかにマズいのだけどけっこう直すの重そうだな…と日和りましたが、ボトルネックから片付けないといけないことは学んできたので覚悟決めて倒すことに。

[12:30] GET /api/trendのN+1を倒す: 9035

かなり苦戦しつつもGET /api/trendのN+1を消し、クエリ1回で必要な全データを取れるようにしました。

途中クエリをミスってFailするようになってしまったバグの修正でけっこう時間がかかったものの、一気に点数が伸びて昼飯を食べる気が湧きました。

ベンチマーカー走行時に凡ミスでFailするとかなり心臓に悪いので、これ以降の修正は基本的にRubyのREPLでコードをある程度実行してからコミットすることにしました。

また、ボトルネックPOST /api/condition/:jia_isu_uuidになったのでこの辺を読んでいく。

f:id:ohbarye:20210823001858p:plain
ボトルネックが変わった

[13:00] [Revert] drop_probabilityの調整: 8685

「いっぱいデータが貯まったほうがスコアが伸びるんだな?」程度の仕様理解をしていたのでこの値をいじって点数の増減を確かめてみました。

  • drop_probability 0.5: 8685
  • drop_probability 0.7: 8815

結果、下げるほど点数が下がることがわかったので0.9に戻す。

[13:30] POST /api/condition/:jia_isu_uuidのbulk insert化: 9149

コードを読んで遅そうなところはinsertがN回走るところだったのでbulk insert化したところ微増。

NewRelicでは依然としてこのエンドポイントが遅いままだったので「うーん、非同期化しないとダメか...?いや、構成変更の素振りが足りないから手を出すのは危険な気が…」と逡巡。

[14:30] indexをisu_condition (jia_isu_uuid, timestamp)に追加: 9909

NewRelicで見えるAPIレイヤのメトリクスでは手を出せる改善箇所が定まらなくなったため、MySQL slow query logを出力してクエリ傾向を見てみる。

isu_conditionテーブルのRows_examinedの数値が異常に高いクエリがいっぱいあった。初期のベンチマーカー走行時は高々1,000程度しかレコードがなかったもののこの時点で21,118件のレコードが入っていたのでインデックスを貼ることにした。

このあとしばらく迷走します。

[15:00] GET /api/trend のsortで減点されていたのを修正: 6858

deductionが20ほど出てて不穏だったので直した。N+1直したときのクエリにORDER BYDESC付け忘れがあった。

なぜこれで点が下がるの...?と思ったところ、ユーザーが増えたせいみたいだ。

revertするか悩んだが後々活きてくることに期待してそのままいくことにした。

[15:10] 毎回static fileをreadするのをやめる: 6574

ボトルネックじゃないところに手を出し始めているので良くない兆候。しかも点が下がっている

Nginxのtry_files思いつきたかったな〜

[15:30] drop_conditionを思い切って0.1に下げる: 9358

打つ手を見失って実験しただけなのだけど、今度はなぜか伸びている...! のでこのままいく。

[16:30] GET /api/isu のN+1を倒す: 9266

GET /api/trend と同様の倒し方。こちらも結構手こずった

[17:00] GET /api/isu/:id/icon をキャッシュさせる: 9320

画像は変更されないようなのでNgnxで GET /api/isu/:id/iconexpires つけてキャッシュさせるようにした。

[18:10] 計測ツールをオフにする: 13020

しばらく見てないのでNginxのログ出力、MySQL slow query log、NewRelicをオフにしたところようやく10,000点超えた

[18:20] Pumaをcluster modeで動かす: 14328

ずっと1台でRubyプロセスのCPUが100%に張り付いているのは気になっていたが手が回っていなかった...。puma -w 2でcluster modeでPumaを起動したところやや伸び。CPUは2つのRubyプロセスが60%程度になりました。

以下を試したがあまり伸びませんでした。

  • preload: 13542
  • worker数の調整: 12982

[18:40] 祈りのラストベンチマーカー: 14484

特に何をするわけでもなく祈りながらベンチマーカーを実行したところこれまでで最高スコアになりました。

*1:もちろん勝つ気持ちでやってますが

デスクチェアの座面クッションを掃除した

"腰を破壊する自宅デスク環境"を改善して健康被害から卒業した - valid,invalid に書いた通り、先日中古でオカムラのコーラルチェアを購入した。

椅子自体の性能は初日からめちゃくちゃ気に入ったのだが、中古ということもあり 座面がお世辞にもキレイとは言えなかった ため、自分で掃除してみた。

結果

写真の明るさや彩度がブレてしまったが Before / After はこんな感じ。

← Before | After →

多少ヨゴレを強調するように撮ったとはいえ、Beforeを改めて見返すとヤバい。昔に働いていた会社の倉庫に眠ってたボロ椅子を思い出す。二度と座りたくない!!

掃除のやり方

オカムラ公式サイトのやり方やネットで見かけた記事を参考に、以下の道具を用意した。

  • 粘着カーペットクリーナー(通称コロコロ) or 掃除機
  • アルカリ系の汚れ落とし
  • タワシ or 歯ブラシ
  • 吸水タオル
  • (任意)ドライヤー

1. 表面のほこりやチリをコロコロや掃除機で除去する

掃除の邪魔になりそうなほこりやチリには最初に退場いただく

2. アルカリ電解水をかけまくる

ここからが本番

有機物の汚れ(汗、皮脂、食べ物、飲みもののしみなど)はアルカリ電解水で浮かせて拭き取るのが有効らしい

最初は遠慮気味に吹きかけていたが、けっこうビシャビシャになるまでかけないと汚れが浮き出なさそうだったので容赦なく噴射

皮膚や喉が弱い人は手袋やマスクをしながら作業したほうが良さそう

3. タワシや歯ブラシでこする

うちにはタワシがなかったので使い古した歯ブラシで実行

アルカリ電解水を噴射しただけでは汚れが浮いているのかどうかまったくわからないが、歯ブラシでゴシゴシこすり始めるとブラシがみるみる汚れていく…

うわ〜〜〜(自主規制)

4. 吸水タオルで拭き取る

ブラシに付着した汚れを拭き取ったり、座面を直接タオルで吹いたりしていく

何度もこすっていると徐々にタオルが汚れていく

ある程度こすって吸水タオルがビシャビシャになった頃、水場でタオルを絞ると濁った水が…

うわ〜〜〜(自主規制)


2~4を何回か繰り返した後、ドライヤーで乾かして汚れの落ち具合をチェックして良さそうなら終了。

本当にこれで落ちるのか?と半信半疑だったので1周目は半分だけやってみた。すると違いが明らかになってきたので勢いづいて2周やったところ当初よりかなりマシになった。

←1周目 | 2周目→

アルカリ電解水で濡れていると汚れている箇所がわかりづらくなるので、ドライヤーでいったん乾かした後に残っている箇所をさらに重点的に掃除。

最終的には3周したところでこんな感じ。

写真で見るとまだまだ落とせそうな箇所があるが、通常の照明下、肉眼ではほとんど気にならない程度にまでキレイになった。

感想

オフィスバスターズのような専門業者であればある程度クリーニングしてから発送してくれそうな気がするが、個人間取引ということである程度は覚悟して購入したので文句は言えず。まぁ、座面以外は目立った汚れがなかったので良かった。

前提として、オフィスチェアはどんなに良いものでも使用していると必ず汚れたり状態が悪くなっていくので掃除が必要とのこと。ならば新品を購入してもいずれはこの状況に遭遇するはず…それが早いか遅いか、それだけ…

なのではあるが、掃除過程で予想以上の汚れを観測してしまいメンタルにダメージが…。

椅子自体はとても気に入っているので 定期的に汚物は消毒 していきたい。

SQLでパーセンタイル値を求める

SQLでパーセンタイル値を求めたいことがあり、Calculate Percentile Value using MySQL - Stack Overflowを参考に実現できた。

実例

口座 (accounts) テーブルで残高 (balance) column の95パーセンタイル値を求める。

SELECT balance
FROM (SELECT @row_num := @row_num + 1 AS row_num, balance
      FROM accounts t,
           (SELECT @row_num := 0) counter
      ORDER BY balance) temp
WHERE temp.row_num = ROUND(.95 * @row_num)
;

95パーセンタイル以下の値を持つレコードに絞って平均を求める。

SELECT AVG(balance)
FROM (
      SELECT @row_num := @row_num + 1 AS row_num, balance
      FROM accounts t,
           (SELECT @row_num := 0) counter
      ORDER BY balance
     ) temp
WHERE temp.row_num <= ROUND(.95 * @row_num)
;

解説

一番内側のクエリで、指定のカラムを昇順で並べつつ行番号を割り振る。

SELECT @row_num := @row_num + 1 AS row_num, balance
FROM accounts t,
     (SELECT @row_num := 0) counter
ORDER BY balance

以下のような結果が出力される。

row_num balance
1 1232
2 122090
3 134243
4 230909
5 390901

↑のクエリで得られるレコードが100件あるとしたら、95番目の値が95パーセンタイル値になる。

この中から95%目(というのも変な表現だが)の行だけを選択するにはWHERE temp.row_num = ROUND(.95 * @row_num)で絞り込めば良い。

95パーセンタイル値以下のレコードに絞るのであればWHERE temp.row_num <= ROUND(.95 * @row_num)


PERCENTILE_DISCみたいな良い感じのウィンドウ関数があればよいのだが、使えない環境もある。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_WF_PERCENTILE_DISC.html

環境

zshの起動がいつの間にか速くなっていた

zshの起動が遅かったのでzprofでプロファイリングしながら起動速度を3倍速くした - valid,invalid からしばらく経ち、久々にzshの起動時間を計測してみた。

前回

起動1秒でたまにイラッとする程度。

for i in $(seq 1 10); do time zsh -i -c exit; done
zsh -i -c exit  0.79s user 0.40s system 108% cpu 1.100 total
zsh -i -c exit  0.78s user 0.39s system 108% cpu 1.070 total
zsh -i -c exit  0.77s user 0.39s system 108% cpu 1.069 total
zsh -i -c exit  0.79s user 0.39s system 109% cpu 1.083 total
zsh -i -c exit  0.78s user 0.38s system 108% cpu 1.065 total
zsh -i -c exit  0.80s user 0.40s system 108% cpu 1.099 total
zsh -i -c exit  0.79s user 0.40s system 109% cpu 1.090 total
zsh -i -c exit  0.80s user 0.40s system 107% cpu 1.110 total
zsh -i -c exit  0.79s user 0.40s system 108% cpu 1.100 total
zsh -i -c exit  0.80s user 0.40s system 108% cpu 1.100 total

今回

前回同様まずはおおまかな起動時間を測ってみた。

$ for i in $(seq 1 10); do time zsh -i -c exit; done
zsh -i -c exit  0.49s user 0.25s system 109% cpu 0.676 total
zsh -i -c exit  0.48s user 0.23s system 109% cpu 0.650 total
zsh -i -c exit  0.49s user 0.24s system 109% cpu 0.661 total
zsh -i -c exit  0.48s user 0.24s system 110% cpu 0.658 total
zsh -i -c exit  0.48s user 0.23s system 110% cpu 0.648 total
zsh -i -c exit  0.49s user 0.24s system 111% cpu 0.651 total
zsh -i -c exit  0.48s user 0.24s system 110% cpu 0.649 total
zsh -i -c exit  0.48s user 0.24s system 110% cpu 0.652 total
zsh -i -c exit  0.48s user 0.23s system 110% cpu 0.643 total
zsh -i -c exit  0.49s user 0.24s system 110% cpu 0.654 total

そこまで遅くなかった。というか、計測してなかったけど前回よりいつの間にか早くなっていた。

また、前回ボトルネックの一端であったkubectlの補完(とkubernetes関連のutil)を今はオフれる*1ことに気づいたので、オフにしてみたら、さらに速くなった。

$ for i in $(seq 1 10); do time zsh -i -c exit; done
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.420 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.420 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.421 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.423 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.419 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.419 total
zsh -i -c exit  0.21s user 0.20s system 95% cpu 0.421 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.417 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.419 total
zsh -i -c exit  0.20s user 0.20s system 95% cpu 0.422 total

いつの間にか早くなっていた理由

この2年ぐらいでそんなに.zshrcいじったっけ?と思ってdiffしてみたらけっこう変更してた。

計測してないが、おそらく高速化に寄与したであろう変更は

  • preztoやめてoh-my-zshにした
  • plugin managerをantigenに寄せて、ついでに使ってないpluginを消した
  • antigenをv2にした
  • zshをupdateした

あたり。

定期的にpluginを消したりソフトウェアをupdateするのは大事だなぁと改めて思ったところだが、antigenのメンテナンス止まっているのか... また移行しないと...

環境

*1:kubernetes使っていないため

MutationObserver

JavaScriptでDOMを監視して何かしらのコールバックを実行する際にMutationObserverが使える。

仮想DOM全盛時代でなくとも、jQueryでもvanilla JSでもイベントハンドラを自由に設定できるようなWebフロントエンドの世界で使い道あるか?と思っていたが、利用しているSaaSASPにユーザースクリプトを埋め込むケースなど、自身ではコントロール下にないサイトで何かやるときに使える。

Example

.cardセレクタで取得できるDOMに子要素が追加されたのをトリガーにコールバックを実行する例。

.cardの下に消したい要素.noiseがいたら取り除く。

 const mutationObserver = new MutationObserver(() => {  
   if ($('.noise').length) {
     $('.noise').remove();
   }
 });
 
 mutationObserver.observe(document.querySelector('.card'), { childList: true });

他にも属性・テキスト・子要素など監視対象を細かく指定できる。


直近で役に立ったのは、Zendeskヘルプセンターの表示を動的に切り替えるカスタムスクリプトを書いたとき。

ユーザー操作に応じてZendeskが何らかのDOM操作を行うのをトリガーとし、DOM操作に追従して見た目をコントロールしたいときにMutationObserverが使えた。

Zendesk本家の挙動はブラックボックス*1で、動的に謎のDOMが減ったり増えたりするのでシンプルなイベントハンドラでは対応ができなかった。


試してないけど、はてなブログJavaScriptを実行して広告を消したりもできるのかもしれない*2

*1:正確にいうと多少はリバースエンジニアリングできるが

*2:僕は広告表示されて構わないので無課金ですが、広告非表示は有料会員の機能なので消したいならちゃんと課金しましょう

NameError uninitialized constant ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick

ActiveStorageで画像アップロードを行ったあとに非同期に実行される画像の解析処理で NameError ActiveStorage::AnalyzeJob uninitialized constant ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick エラーが出た。

処理を行っているのはActiveStorage::Analyzer::ImageAnalyzer#read_imageの中。

https://github.com/rails/rails/blob/v6.1.4/activestorage/lib/active_storage/analyzer/image_analyzer.rb#L31-L49

def read_image
  download_blob_to_tempfile do |file|
    require "mini_magick"
    image = MiniMagick::Image.new(file.path)

    if image.valid?
      yield image
    else
      logger.info "Skipping image analysis because ImageMagick doesn't support the file"
      {}
    end
  end
rescue LoadError
  logger.info "Skipping image analysis because the mini_magick gem isn't installed"
  {}
rescue MiniMagick::Error => error
  logger.error "Skipping image analysis due to an ImageMagick error: #{error.message}"
  {}
end

raiseされるのはL46のrescue節の中でMiniMagick::Error定数を参照しようとしたとき。 このタイミングでrequire "mini_magick"されていないので定数探索のときにActiveStorage::Analyzer::ImageAnalyzer以下を探すが見つからず、ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick

L33でrequire "mini_magick"されているはずなのに...と思ったが、発生原因は以下の通りだった。

  • ブロック内の処理以前、download_blob_to_tempfile内で別のエラーがraiseされている
  • L33でrequire "mini_magick"する前にL46に到達し、定数が見つからずにNameErrorになる

別のエラーが何かというと、workerを実行するコンテナがS3の特定バケットに対する権限を持っておらず403 Forbiddenが返されている、というものだった(よくよくbacktraceを見ればAws::S3::Errors::Forbiddenが出力されていたことに同僚が気付いた)。

バケットを作るときに、アクセスするコンテナの指定を僕が忘れていただけだったので、権限をつけてもらって解決。


Sentryに飛んできたエラークラスが事象の根本となる問題を表していない(まれによくある)ので戸惑ったが解決できてよかった。

"腰を破壊する自宅デスク環境"を改善して健康被害から卒業した

この数ヶ月で自宅のデスク環境を大きくアップデートしたので記録に残しておきます。

当記事がリモートワークないし家で作業する機会が多い人の参考になれば幸いです*1

変更前後のようす

Before

作業環境にこだわらずガジェットにも興味が薄い人間だったので聞く人によっては卒倒しそうな環境で2020末までずっと仕事や自宅作業をしていました。

変更以前の写真がなかったので当時の自宅のようすを超技術で再現すると、こうです*2

すでに腰痛や肩こりを抱えている方、つまりHPが1桁台で状態異常の方が利用したら1ヶ月と持たずに身体が破壊されるのではと思える環境でしたし、かくいう私も何度か破壊されました

破壊されつつも自宅に机やイスを設置するスペースがなかったので、リモートワークがメインになった2020年からも1年ぐらいこの環境で働いていました。まぁ、世間が急速にリモートワーク対応していった昨年の2020年4~7月頃は無職だったので、デスク環境にさほど関心を払っていなかったのでした。乗り遅れたな…からのもう今更いいかな…っていうレイトマジョリティ以下のアレでした。

After (HEAD)

変更後、2021年7月現在の状態はこんな感じです。めっちゃ映える感じでもないですが実用性十分で健康被害を80%ほど抑制(体感比)するのにも成功しています。

着席時: デスク高さ 71.5cm

スタンディング時: デスク高さ 104.0cm

机上にはディスプレイとラップトップのみ。かなり殺風景ですが実用性重視なのでヨシ!

デスク下にはテレビ台を流用した棚+筆記用具、ケーブルボックス、シュレッダー、ルーター(死角)などを置いています。

シュレッダーは個人情報の破棄用途ですが、たまに書き物をしたあとに即シュレッドできて便利です。

かかった費用

かかった費用の合計は152,492円。フリマアプリに眠っていた"銭こ"が少しあったのでそのぶん割り引いて、実際の支出は93,706円でした。

No 品名 購入価格 定価
1 LG 27インチ ディスプレイ 46,890 57,980
2 FlexiSpot EJ2 脚 + 天板 32,650 46,800
3 Umi チェアマット 2,999 2,999
4 モニターアーム 8,953 12,101
5 オカムラ コーラルチェア (used) 61,000 195,250
小計 152,492 315,130
ポイント利用 -58,786 -
総計 93,706 -

ギリ「給付金で整備した」と言えるレベルの出費。

個別に購入したときは気にならなかったのに振り返ったら意外とかかったな…と思ったものの 定価と比較したら221,424円も得してるな! と考えたら気分が明るくなってきました。

変更履歴

ここから、After (HEAD) に至るまでの履歴です。

v1: こたつと座椅子

  • 山善のこたつテーブル
  • 座椅子、ときどき骨盤クッション

外付けディスプレイもキーボードもマウスもありません。 漢は黙ってラップトップ単騎。

冬場のこたつでプログラミングは良いものでした。

v2: LG 27インチディスプレイ導入

LG モニター ディスプレイ 27UK850-Wはたしか2021年1月にAmazonのセールで見かけて購入しました。

デカさをケチりたくはなかったのですが、こたつテーブルの上に他にもいろいろ置かなければならなかったのでこのサイズしか置けなかった…。

いやまぁ、さすがにオフィスワーク時はディスプレイ使っていましたし、業務上必要な資料なりWebサイトなりコードなりを読み込む時にあると便利なことぐらい、知っていましたが…15インチのラップトップ単体のときより視線移動が減って目が疲れにくくなるとは、ね…。

v3: FlexiSpot EJ2 導入

2021年6月、引越。ここから改革の狼煙が上がる

引越しに伴ってこたつテーブル・座椅子を手放すことになり、作業環境の改善が急務になりました。

作業環境として優れていないとはいえ机と椅子の両方を一度に手放すという暴挙の背景には、「限界を決める"部屋-ハードウェア-"は前住居よりやや広くなり机やイスを置くスペースが作れたので、せっかくなら以前よりマシな環境を作ろう」という漆黒の意思。あと、 たった数日でもストレッチと運動をサボると身体のどこかのパーツが軋むのでそろそろ逆張りも潮時かな? という気持ち。

スタンディング状態で仕事をしたり、PC作業よりも高さが必要な手書き作業をやったり、体格が異なる家族が使う可能性も考慮して、電動昇降式デスクを絶対買うと決意しました。

「毎回調整するのは大変なので高さを記憶するメモリ機能がついていてほしいが、それ以外での要求は特にないーーー」その程度の軸で電動昇降式デスクをいくつか調べた結果、FlexiSpotかサンワサプライの製品が良さそうとわかってきました。

最終的には価格で決め、FlexiSpot EJ2と天板のセットを購入。 天板DIYに興味はあったが環境の改善が急務だったので速度を優先。

FlexiSpotのサイトでセール & クーポンを使って32,650円。

購入した2日後にAmazonプライムデーセールでEJ2がさらに安い25,000円で販売しているのを見たときは気絶しそうだったが、天板をつけると35,000円になっていたので何も問題なかった。システムオールグリーン...

注文から3日後に到着。組み立ては1時間ぐらいかかったのと、机を起こす作業は1人ではかなりきつかったので妻に手伝ってもらいました。

机の高さに合う椅子が家になかったためピアノ椅子を高くして暫定的に使うことにしたのですが…これは大間違いだった。この時期は2週間ぐらいだけどめっちゃ辛かった。本当に辛かった。ピアノ椅子をオフィスチェアとして利用するのはおすすめしません

座椅子でも壁でもなんでもいいのですが、座り作業で背中を預けられないと一日中自力で上半身を支えなければならない。それが不可能なので気づくと机に肘をついたり悪い姿勢を取るようになっていました。1日が終わるころには疲労困憊です。

スタンディングデスクに切り替えたり、ラップトップをデスクから離れたところに持っていって布団や膝上に置いたりしましたがなかなか厳しいものがあった。

良い机だけあってもダメということがよくわかった。

v3.1: チェアマット

乗せるオフィスチェアもないのにチェアマットとは…と思いつつ、FlexiSpot EJ2がかなり重いのでフローリングが心配になって購入。

うちは掃除機ないので(主にクイックルワイパーで床掃除をしている)チェアマット上の掃除は粘着カーペットクリーナー(通称コロコロ)とファブリーズなどで対応しています。

今回はデスクもチェアマット上に置いていますが、フローリングに直置きする場合はデスクの足にカグスベ〜ルのような緩衝を置くと傷もつかず移動も楽で良いらしいとのことです。

v3.2: モニターアーム

LGのディスプレイにもともと付属していたモニタースタンドで十分と思っていたが、自在に位置・角度・距離を制御でき、デスクも広くなってとても良いものです。

難点を挙げるなら

  • 机と壁の間に距離を開けないといけないこと
  • 天板が痛む可能性があること

今のところ机に傷はついてないけれどもモニターアームを動かしたときに机との接触部が動くことがまれによくあるんですよね〜。天板を気遣うあまりネジを締めきれていないのかもしれない。気になってきたら補強プレートを買うかもしれません。

v4: オカムラ コーラルチェア

これが最大のメジャーアップデート。

ピアノ椅子があまりに辛かったのでイスならなんでも良いと思いかけていたが、せっかくなので椅子のことも色々調べてみた。にわか知識ながら、自分にとってMUSTな要求は可動肘・ハイバック・座面調整・シンクロロッキングあたりらしい。

あまりにこだわると沼っぽいこと、どんなに高級な椅子でも身体に合わないものは辛いらしいことがわかった。なので、アイリスオーヤマ新宿に一度だけ出向いて「シンクロロッキング...シンクロロッキング...」とつぶやきながらオカムラ・イトーキ・ハーマンミラーエルゴヒューマン等々の名前だけは聞いたことあるブランドの椅子に試座してみた。

けっこう人が多くて落ち着いて見られなかったのと、知識不足で細部まで機能を余すことなく試すことはできなかったが、正直、展示されているようなブランドの椅子ならどれでもいいのでは? と思えた。強いて言えば、出社していた頃にオフィスで使っていたバロンチェアやそれに近いやつは"馴染む"感じがあった。

新品に十数万かける度胸はなかったので中古で正常稼働するものを、~6万円の予算で探すことにした。

オフィスバスターズを見ながら各製品の中古相場をだいたい把握し、最終的にはオカムラのコーラルチェアをフリマアプリで61,000円で購入した。"オフィスチェアについて語るスレ"民いわく「アンチオカムラでもコーラルだけは認める」ぐらい優秀らしい(ネットの情報を鵜呑みにするの図)。

  • 型番 CQ8ABW-FSH3
  • メーカー希望小売価格: 195,250円
  • 新品実売価格: 130,000~140,000円

個人間売買よりも専用業者(オフィスバスターズ etc.)から買ったほうが安心だったかもしれないが、コーラルはバロンやシルフィーほど多く出回っていないのでオフィスバスターズに在庫がなかったこと、中古相場より安めだったこと、フリマアプリの残高があったのでシュッと使えて出費が抑えられることが決め手になった。

最後の点は市場関係なく完全に個人的なファクタ。引越しで諸々を売却処分した結果、アプリ内に売上残高が60,000円近くあったので実質2,000円ちょっとの出費で済みました。

到着後は以下の動画を参考にしつつ椅子と机の高さを調整したり、座面をセルフクリーニングして"仕上げ"ました*3

www.youtube.com

前環境が悪すぎたので伸びしろしかなかった わけですが、コーラルで数日過ごした結果、やはり 1日の終りの疲労感が圧倒的に違う

ピアノ椅子では終業後は「もう座っていたくない」という気持ちでベッドに倒れていたが、今や業務が終わったあとでもそのまま読書や趣味でPC触ったり、「オレは今、コーラルに座っている」という多幸感に包まれたりしている。

あとは妻を椅子に乗せてグルグル回すアトラクションをやっている。

総合的な感想

もともとデスク環境へのこだわりはまったくなく、むしろ こだわらないほうがかっこいいとまで思っている逆張りのフシ があったわけですが、ある程度整備した現状の自宅デスクを改めて見ると..."愛-かな-"しい...。

出社メインで仕事していた頃、当然そこにはデスクやイスやディスプレイがあった。しかしながら環境が整備されたオフィスで仕事しても自宅の上記のような環境でやっても別に生産性はさほど変わらないなと思っていた。

まぁ、劣悪な環境は健康に影響を及ぼし、長期的には生産性を損ねるんですが…。そう、健康面でいうと良い環境で仕事していようとデスクワークしてる時点で腰痛や肩こりとの戦いは続くし、4年前ぐらいからずっと冒されていて結局のところ運動や生活習慣の改善でなんとか改善しつつ運用している。

良い道具は身体へのダメージを軽減はするが回復はしない、道具よりも生活習慣のほうがはるかに大事だという考えは継続したいと思います。

今後の課題

ラップトップ単体で作業しているときは気にならなかったものの、椅子と机が揃うと適切な位置に置けるキーボードやトラックパッドや良質なコンデンサマイクが欲しくなってくるし、デスク上に何らかを置くスペースはあるので実用性ありそうな機器や道具の追加も検討の余地がある。

ただしこれらは本稿では十分に論じることができなかったので今後の課題としたい

参考

*1:と言いつつ今回の出費を少しでもまかなえればと思い、当記事の商品リンクはおおむねアフィリエイトリンクになっています

*2:いらすとや https://www.irasutoya.com/ の画像を使用しています

*3:セルフクリーニングはけっこう大変だったので別途記事にしてみたい