Web Speed Hackathon 2023 21位 132点 やったこと
- 概要
- リーダーボード
- スコア遷移
- コンテスト中にやったこと
- loading=“eager”から"lazy"にする f63158b
- Imageサイズ最適化 -> WebP (50MB -> 7MB) 1cd1cfc
- NODE_ENVをproductionで提供 6bc1207
- react.helmetの依存削除 49d67e3
- svgリサイズ (10857.78k → 2.55k) 5e9dbd9
- lodashの依存削除してbundleサイズ削減 c6cef64
- product/3 の mp4のロードが長すぎるためwebmに修正 (24.5MB -> 9.6MB) 8d45c77
- bundleサイズ削減 d56ff14
- ApolloClientのfetchPolicy変更 8d45c77
- 依存関係がない非同期処理をPromise.allして並列に処理 898c084
- フォント読み込み設定 d51d934
- ヘッダーと今週のおすすめは先に画像ロードするようにする 7df56d8
- aタグ遷移してるのでSPAに治す 7df56d8
- viteのbrotli提供 a8c314c
- 静的ファイルのキャッシュ max-age=3600 a8c314c
- dynamic import f724af6
- 最終
- できなかったこと
- 感想
概要
激重サイトを見た目(画像やCSS)は変更しないで、軽くしようというやつです。
得点はlighthouseの指標を元に計算されます。
リーダーボード
レギュレーション違反を除き、全体 21 th / 58 でした
Web Speed Hackathon 2023 リーダーボード
スコア遷移
コンテスト中にやったこと
リポジトリをforkして
fly.ioにデプロイ -> https://holy-wave-858.fly.dev/
何も変えずにlighthouseで初回計測
loading=“eager”から"lazy"にする f63158b
大量に画像を読み込んでいるので遅延読み込みに変更
Imageサイズ最適化 -> WebP (50MB -> 7MB) 1cd1cfc
public/images/avatars/ 配下のpngをwebpに変換するコマンド
imagemin public/images/avatars/* --plugin.webp.quality=95 --plugin.webp.preset=icon --out-dir=public/images/avatars/
画像の参照パスをsqliteで管理していたので、sqlite3のmedia_fileの.jpgを.webpに変える
sqlite> select * from media_file; sqlite> select replace(filename,"jpg","webp") from media_file; sqlite> update media_file set filename=replace(filename,"jpg","webp"); sqlite> select * from media_file;
NODE_ENVをproductionで提供 6bc1207
NODE_ENV developmentだと無駄なものを読み込むのでproductionに変更
react.helmetの依存削除 49d67e3
Webページのタイトル変更にしか使ってなかったためdocument.titleに変更
svgリサイズ (10857.78k → 2.55k) 5e9dbd9
開発者ツールのnetworkタブを見てヘッダーロゴのsvgがやたら重いため調査・修正
lodashの依存削除してbundleサイズ削減 c6cef64
fast-deep-equalを使う
https://note.com/green_grass_grow/n/n0703595eafb9
lodash (69.9kB) -> fast-deep-equal (852B)
product/3 の mp4のロードが長すぎるためwebmに修正 (24.5MB -> 9.6MB) 8d45c77
ffmpeg -i 001.mp4 -strict -2 001.webm ffmpeg -i 002.mp4 -strict -2 002.webm ffmpeg -i 003.mp4 -strict -2 003.webm sqlite3 databases/database.seed.sqlite sqlite> select * from media_file; sqlite> select replace(filename,"mp4","webm") from media_file; sqlite> update media_file SET filename=replace(filename,"mp4","webm"); sqlite> select * from media_file;
getMediaType関数も修正
bundleサイズ削減 d56ff14
https://zenn.dev/manalink_dev/articles/vite-bundle-analyzer
date-time-format-timezoneが大きく、chromeでは標準でついているので削除
ApolloClientのfetchPolicy変更 8d45c77
https://www.apollographql.com/docs/react/data/queries/#cache-and-network
cache-firstに変更
依存関係がない非同期処理をPromise.allして並列に処理 898c084
https://zenn.dev/lollipop_onl/articles/mistake-promise-all
フォント読み込み設定 d51d934
必要なフォントだけ読み込むように変更 https://zenn.dev/neriko/articles/3b55c547a07c8d22c9f1
ヘッダーと今週のおすすめは先に画像ロードするようにする 7df56d8
aタグ遷移してるのでSPAに治す 7df56d8
viteのbrotli提供 a8c314c
https://github.com/vbenjs/vite-plugin-compression
静的ファイルのキャッシュ max-age=3600 a8c314c
dynamic import f724af6
最終
- First Contentful Paint 16.0s -> 1.9s
- Speed Index 25.9s -> 3.0s
- Largest Contentful Paint 36.5s -> 9.2s
- Time to Interactive 31.5s -> 2.7s
- Total Blocking Time 11310ms -> 310ms
- Cumulative Layout Shift 0.8 -> 1.363
Cumulative Layout Shiftだけ悪化したどうして…
できなかったこと
ログインページ周りのパフォーマンスチューニング
graphqlとwasmのパフォーマンスチューニング
本来の画像が読み込まれる前に画像のプレースホルダーを入れて画像領域確保
CloudFlareを使用してCDN配信 (DNS設定反映が間に合わなかった)
https://nobunobu1717.site/?p=3142
感想
今までISUCONでバックエンドのパフォーマンスチューニングをやったことはあったのですが、フロントエンドのパフォーマンスチューニングは初めてだったので新鮮でした。
すぐに自サイトに適用できそうな画像系のテクニックなどすごく実践的でした。
上位陣のチューニング方法を見つつ精進したいです。
2022年振り返り
今年の振り返りを箇条書きでまとめます。
1月
- 内定者バイトと研究頑張ってた
- 修士論文提出
2月
- 本審査終了無事卒業確定 (大関先生・田中先生・張山先生ありがとう😭)
- エルデンリングにはまる。3日間で30時間超える。バイトとこればっかりやっていた。
3月
- モラトリアム謳歌
- 社会人までの手続いろいろ済ます (親知らず抜いたり (?))
4月
- 新社会人都会デビュー。土日はめっちゃ出歩いてた (田舎もん)。
- テクレジという会社から徒歩5分の好立地に住んでたので、朝昼晩会社で飯を食べた
- 同期と研修をした
5月
- 仙台に帰ってくる。チーム開発研修していた。Next.js, Recoil, Spring Bootのテックスタックでアプリ作った
- 一人だけパワーが違う人いたので、めっちゃ助かった (もう即戦力中途でいいのでは)
今日のHirai氏
— Baplisca (@sooooouls) 2022年5月11日
フロント・バックエンド・企画で3つに分裂してた pic.twitter.com/CpmNc8quoo - 楽天イーグルスが絶好調なのもあり、毎日野球見て過ごす
6月
- インターンと内定者アルバイトをしていたチームに2ヶ月ぶりに戻る。その日にはもう開発していた (?)
- 初めて京都に遊びに行った
7月
- 前期で一番大変だった開発を終える
- 凄腕メンターが会社を辞める (もっと一緒に働きたかった・・・)
ワイの配属初日に、インターンとアルバイトでお世話になった凄腕メンターが辞める報告を受けて、脳が破壊されている
— Baplisca (@sooooouls) 2022年6月6日
ンゴゴゴゴゴ🥺wwww - 会社の同期と出たISUCON12予選落ち (
SQLiteが悪い)
8月
- チームにインターン生がきた ( ?? 「俺が上司だ!」)
- お盆期間に北海道観光してた。夏の北海道は最高
9月
- スプラにハマり散らかす
- 自分にとって大きめなリリースを終える
10月
- SQL Contestに出る 38th / 188
- CSMの資格を取った
スクラムマスターになりました pic.twitter.com/T8DehbFdH7
— Baplisca (@sooooouls) 2022年10月23日
11月
- 弊社オンサイトテックカンファレンスの運営をした。(DeveloperIOの偉い人や、ウルシステムズの社長が講演してた。
一体いくら払ったんだ弊社) - 仙台のオフライン勉強会に初参加・初発表
- ドラム式洗濯乾燥機デプロイ。人生変わりました。
ドラム式デプロイ中 pic.twitter.com/fJ81yt7Die
— Baplisca (@sooooouls) 2022年11月12日
12月
- いろいろ仕事納める
- 昇給し、給料が少し増えた
- ボーナスあったけぇ・・・
AtCoder水色になりました
Bapliscaです。
先日のAtCoder Beginner Contest 193で水色になりました(わーい)
そこで水色になるまでにやったことを振り返ろうと思います。
ついに目標にしていた水色コーダーになることができました😭 pic.twitter.com/6RxmM8mrMP
— Baplisca (@sooooouls) February 27, 2021
1、灰色暗黒期(灰色)
この期間は競技プログラミング(以下競プロ)のルールがよく分からず、とりあえず参加したらこうなりました。 レーティング?TLEって何?みたいな、そもそものスタートラインに立ててなかったような気がします。 この期間だけPythonでコードを書いてました。
2、精進・バチャ期(灰色〜緑色)
卒論が終わり、某ウイルスが蔓延した際に、競プロ復帰しました。 また惰性で参加するのはよくないと思い、競プロ界隈で使っているユーザー数が多い言語であるC++をAPG4bで atcoder.jp
勉強しました。
その後、当時くじかつという午後9時から毎日開催されていたバーチャルコンテストに参加し、過去のコンテストで出た問題を参加したユーザー内で競う形で精進していました。
今となってはとても懐かしい気がします。
3、虚無期(緑色)
夏のインターンシップに参加していて、AtCoderのコンテストに参加できていなかったです。
参加自体は可能ですが、わざわざ忙しくする必要もないため参加は見送ってました。
4、長期インターン・就職活動期(緑色〜水色)
ある企業で、長期インターンをする機会に恵まれたのと同時に就職活動を行っていました。
ピーク時は参加できなかったものの、そこまで忙しくなかったためコンテストに参加してました。
最後に
結果として、精進・バチャ期の知識で水色になれたと思っています。
忙しくて、コンテストに出れない期間もあると思いますが、自分なりの目標を掲げて頑張りましょう。
精進方法ですがAtCoder Problemsというサイトで、自分が目標にしている色の過去問題にチャレンジして、その都度必要な知識を補う形がいいかなと思います。
難しければ、低い難易度の問題で下限を引き上げ、簡単であれば、高い難易度の問題で上限を伸ばしていきましょう。
今後の目標はCodeforcesという海外の競プロコンテストに参加し、英語力や実装力を上げつつ、青色を目指します。
これまでの精進画像になります。大体1000問くらい解きました。
横浜旅行 in Winter
Baplisca(@sooooouls) です。
12月9日 - 12月10日に横浜に行ってきました。
なぜ横浜?
夏に行ったインターン先の懇親会があったため、行くことになりました。その会社が交通費と後泊の費用を支給してくれたため、観光もかねて行きました。
12月9日
その日は、2限に講義があり、9時前の新幹線に乗って、東京駅の地下カフェで講義を聞きました。
カフェのwi-fiが1時間で切れる仕組みだったので講義を最後まで視聴することができませんでした。。
その後、みなとみらいに移動し、企業の懇親会に参加しました。
懇親会が終わった後、駅前のホテルに移動してのんびり過ごしました。
ホテル最上階に泊まります!!! pic.twitter.com/da30Knlx7l
— Baplisca (@sooooouls) 2020年12月9日
綺麗すぎる pic.twitter.com/wVKugc8qON
— Baplisca (@sooooouls) 2020年12月9日
エアウィーヴくん、知らん土地でもすぐに眠りにつけた。でも高いので自分では買わない
— Baplisca (@sooooouls) 2020年12月10日
12月10日
ホテルの朝食を済ませて、部屋の中で1限の講義を聞きました。 その後チェックアウトして、電車で横浜中華街に移動し昼ご飯を食べました。 中華街を少し抜けると、山下公園があり、そこには船や実物大のガンダムが鎮座してました。 実物大ガンダムは、19日から一般公開される予定なので少しタイミングが悪かったですね。
その後水上バスに乗って、再びみなとみらいに着き、帰仙しました。
終わりに
最近はインターンがあって家に引きこもりがちだったため、いいリフレッシュになりました。
ボイストラベラー 音声認識や周波数周りの技術選定の話
Baplisca(@sooooouls) です。
先日、技育展で「ボイストラベラー」という音声認識と周波数取得を組合せた世界初のゲームを紹介しました。
内容や感想はこちらの記事で書きました。
ゲーム内では、音声認識をするパートと周波数取得するパートに別れています。
この2つの機能をどの様に実装したか書いていきます。
はじめに
ゲームを作ってから結構時間が経っており、あいまいなところがあると思うので注意してください。
よって適宜調べながら、補完するのを推奨します。
それと、Unityの基礎的な話はここでは書きません。
技術選定の話
ゲームという性質上、高速な相互作用が必要です。
そこで基本指針としては、ユーザー目線に立った操作性と安定性と低遅延性を心がけました。
音声区間検出
音声認識と周波数取得、両方に共通するのは音声区間検出(VAD)です。
音声区間検出は、実際に取り出したい信号区間のみを検出し、雑音のみの信号区間を除去します。
これにより、音声認識と周波数取得の精度が上がります。
実装では、パワースペクトルとゼロ交差数を用いました。
パワースペクトルで、ある閾値以上の音を有声と判断します。
ゼロ交差数で、ある閾値以上の値を雑音として判断します。
この2つの技術で、音声区間検出を実現しています。
もっと詳しい説明を見つけたので紹介します。
音声認識
使用技術の変遷は、UnityEngine.Windows.Speech → Julius(モジュールモード)→ Julius(ネイティブプラグイン)です。
UnityEngine.Windows.Speechは、Unityの音声認識APIなので手軽に実装できたので採用しました。しかし、実装してみると認識遅延が発生して、ゲームとしては使えませんでした。
Julius(モジュールモード)は、Juliusを裏で実行し、ソケット通信を行うのですが、頻繁にソケットエラーが起き、安定しませんでした。
Julius(ネイティブプラグイン)は、メインスレッドであるC#側から、C++で書かれたJuliusの処理を呼び出し、音声認識を実現しています。両者の欠点(遅延と安定性)をうまく補えたので採用しました。
周波数取得
初めは、AMDF(Average Magnitude Difference Function)で、自己相関関数を利用して周波数を取得してました。ほぼリアルタイムで周波数は取得できるのですが、精度があまり良くなかったです。例えば音階A4(440Hz)の信号を流し込むと、倍音のA5(880Hz)で判定されるケースがありました。
試行錯誤の末、最終的には、高速フーリエ変換(FFT)を用いました。リアルタイムで精度もかなり高いです。
終わりに
「ボイストラベラー」は、現在Windows(exe版)のみを作成してます。UnityはMacやAndroid、ブラウザ(WebGL)などのマルチプラットフォームに対応しているので、他プラットフォームでの公開も検討してます。
NSSOL (日鉄ソリューションズ)インターンに参加しました
Baplisca (@sooooouls) です。
先月NSSOLの研究開発職のインターンシップに参加したので、感想などを書きます。
きっかけ
参加した経緯ですが、LabBaseからスカウトいただき、選考を受け、参加しました。
当日まで
私が配属されたのは研究開発職の主に組合せ最適化を行っているチーム (IMGroup) で、配属者は私の他にもうひとりいました。その方は私と同じ大学でかつ、研究科も同じだったので偶然にしては凄いなと思いました。
事前にZoomで3週間実施する2テーマの紹介を、配属先のメンターの方がしてくださいました。なんとメンターの方も大学のOBだったため親近感わきまくりでした。研究室で組合せ最適化の研究を行っているので、難しいテーマでもイケるやろと、難しい方を選択してしまったのですが、これが悪夢の始まりでした…
前日
初日と最終日は現地インターンだったため、移動しました。
インターン先が横浜みなとみらいなので、仙台から東北新幹線で東京駅、そのまま京浜東北線に乗り換えて、手配されたホテルにチェックインしました。
到着後お腹が空いたので、夜ご飯を探しました。
日給支払われるためちょっと贅沢してもいいよね!ということで、秀吉という回らないお寿司屋に行きました。おいしかったです。
当日
みなとみらいのシステム研究開発センターに行きました。 ちょっとした会社内見学と論文の概要説明をされた後、解散しました。 お昼ご飯は、近くのラーメン屋に行き「すごい煮干しラーメン」を食べました。
1週目
指定された論文を読みました。
論文は「Computing the Initial Temperature of Simulated Annealing」です。
詳しい内容を書くと長くなってしまうので、元論文読んでください。
概要としてはシミュレーテッドアニーリング (SA)を実行する際のパラメータの一つである初期温度を初期解の近傍エネルギーから求めることです。
組合せ最適化問題の問題構造によって、適切な初期温度は変わるので、それを求めようという話です。
大学の研究では、SAの初期温度をとりあえず高く設定してましたが、高くすることで逆によくない最終解になる場合があるみたいです。初期温度を高くするとアニーリング時間が長くなったり、冷却を早くする必要があるので、時間効率の良い初期温度の推定は大事です。
1週目の最後にIMGroupの皆さんに論文紹介をしました。
発表後の質問で、クリティカルな質問が飛んできて泣きそうになりました。
(論文読んでないのになんでわかるのこの方たち…)
その質問もあったおかげで理解も深まりました。
2週目
今回の論文のロジックのプログラムを書きました。
その後、論文の結果には記されてなかった追加検証を行いました。
言語はJavaで指定されてたので、心配でしたが、普通に書けました。
書き方はほぼC#なので助かりました。
Javaもいいぞ…!
元論文が難しくて、理解が出来ない部分やプログラムの成果が出ないこともありましたが、メンターの力を借りて(借りすぎた)なんとかやり遂げました。
3週目
運悪く秋の長期連休が挟まったので、水曜日スタートでした。
水・木の二日と金曜日の午前を使ってスライドを作成し、金曜の午後にシステム研究開発センター全体に向けて成果を発表しました。
最後に
長期インターンだったため、成果や進捗が出ない時もありましたが、諦めずに頑張れてよかったなと思いました。
大抵のことは粘れば何とかなりますが、どうしようもない時は頼るのもありだと思ってます。
迎えてくださった人事の方、3週間相談に乗ってくださったメンターの方、IMGroupのみなさま、ありがとうございました。
※ この記事はNSSOL社員さんの許可 (検閲) のもと、公開しています
サポーターズ1on1に参加しました
Baplisca (@sooooouls) です。
先日サポーターズさんのエンジニア1on1に参加しました。
きっかけ
サポーターズさんから、
「1on1参加しませんか?こちらのイベントは本来であればご参加いただいた皆様に10,000円の支援金をプレゼントさせていただいているのですが…Bapliscaさんのプロフィールと以前ご回答いただいたアンケートを拝見し、プログラミング経験が豊富で非常に優秀な方だと感じました。そのため、 もしBapliscaさんに下記イベントにご参加いただけましたら、特別に追加で5,000円の支援金をプレゼントさせていただきたく思っております。」
のようなメールをいただきました。
初めは詐欺メールかな?と思いましたが、しっかりとしたイベントでした。(疑ってすみませんでした)
申し込みは先着順ではなく、今までの経歴やアウトプット、どのようなエンジニアになりたいかをアンケートに書いて応募しました。
倍率は、100人応募して、40人合格くらいなので2.5倍です。
正直そこまでアウトプットをしてないので受かるか心配でしたが、2週間くらい待って、合格の通知が来たので参加することになりました。
サポーターズさんには先週の技育展に続いての参加でお世話になりっぱなしです。
当日まで
スライドを作りました。
一応自己紹介は5分くらいと言われてたのですが、15枚くらいスライド作成しまいました。
まぁ早口で話せばなんとか…?
当日
午前
10時スタートだったのですが、直前まで寝ていました。
午前の部は、ZOOMの音声・映像チェック、企業の5分プレゼン×20企業、学生の自己紹介1分×40人です。
企業の5分プレゼン中に感想や面談志望度を提出する必要があるので、結構キツかったです。
学生は、高専から大学院生までいろいろな方が参加してました。
沖縄や北海道の方もいて、オンラインのいいとこなのかなと思いました。
移動がないことや直前まで寝れるのはいいぞ!
午前の最後に最終的な面接志望度を提出してお昼休みになりました。
お昼休み中にサポーターズさんが、企業と学生の志望マッチングしていました。
30分くらいでマッチング完了させてたので、凄いなと思いました。
午後
面談する企業が決まりました。
8ターン全て埋まってたが嬉しかったです(こなみ)
面談したのは、サイボウズさん、楽天さん、メルカリさん、DeNAさん、グリーさん、ピクシブさん、オープンワークさん、マネーフォワードさんです。
オンラインで自分の意見や気持ちを伝えられるか不安でしたが、概ね上手くいきました。
エンジニア面談ということあって、スライドのインターン歴や何を考えてアウトプットしたのか、これからエンジニアとしてどうなりたいかについての質問を多くされました。
面接ではなくて、面談だったので、発表中に相槌を打ってもらえて話しやすかったです。
アウトプットの「海洋生物たちの復讐」で、自機がシャリを飛ばして、敵がお寿司に変わるんですよ〜の話は受けが良かったです。
面談後にフィードバックをもらえて、「最も良かった点」では、「技術力」が6社で、「思考力」が1社、「コミュニケーション力」が1社でした。技術力は多分技育展で登壇した「ボイストラベラー 」が大きかったのかなと思ってます。UIやUXのこだわりやプログラム内部で高速化していたので…
あとは、自己紹介スライドを毎回発表するので、口が疲れます。(オンラインなので、録音して再生すれば…?)
まとめ
スライドをあらかじめ作って、企業に対するイメージやこれからどうなりたいかを意識して話せばなんとかなります。 少なくとも、私が面談した企業は優しかったので…