Slide 1

Slide 1 text

ESP32 IoTを動かしながら メモリ使用量を観測してみた話 RubyKaigi 2026 アフターイベント〜初参加LT・スポンサー4社のパネル〜 株式会社ZOZO ブランドソリューション開発本部 WEAR開発部 バックエンドブロック 坂元 菜摘 Copyright © ZOZO, Inc. 1

Slide 2

Slide 2 text

© ZOZO, Inc. 株式会社ZOZO ブランドソリューション開発本部 WEAR開発部 バックエンドブロック 坂元 菜摘 (もっちゃん) ● 2025年 に新卒入社 ○ RubyKaigi 初参加! ● ファッションコーディネートアプリ 「WEAR」の バックエンド開発に従事 ● 趣味はラーメン巡り 🍜 2

Slide 3

Slide 3 text

© ZOZO, Inc. https://wear.jp/ 3 ● あなたの「似合う」が探せるファッションコーディネートアプリ ● 2,000万ダウンロード突破、コーディネート投稿総数は1,400万件 以上(2026年3月末時点) ● コーディネートや最新トレンド、メイクなど豊富なファッション情報を チェック ● AIを活用したファッションジャンル診断や、フルメイクをARで試せる 「WEARお試しメイク」を提供 ● コーディネート着用アイテムを公式サイトで購入可能 ● WEAR公認の人気ユーザーをWEARISTAと認定。モデル・タレント ・デザイナー・インフルエンサーといった各界著名人も参加

Slide 4

Slide 4 text

© ZOZO, Inc. 4 RubyKaigi2026 初参加! gifteeさんと movさんの Drinkupにおじゃましました! ご当地グルメも 満喫できて最高でした...

Slide 5

Slide 5 text

© ZOZO, Inc. ● PicoRuby for IoT: Connecting to the Cloud with MQTT 5 今回のピックアップセッション 他にも2日目の 「Extreme MQTT on PicoRuby」 など、MQTTがホットな RubyKaigiでしたね! 引用元: https://rubykaigi.org/2026/presentations/Y_uuu.html

Slide 6

Slide 6 text

© ZOZO, Inc. 6 このセッションの内容 ● モチベーション ○ 「PicoRuby」 を動かしている ESP32 マイコンから クラウド(AWS IoT Core)へセンサーデータを送信し、IoTシステムを構築したい! ○ ESP32とは ■ Wi-FiとBluetoothを搭載した低価格マイコン ● 手段 ○ Wi-Fi 接続、ソケット通信の移植、MQTT 実装まで、通信の土台をゼロから構築 ● 結果 ○ AWS への通信に成功し、ピタゴラ装置を動かすデモを実施 → ESP32 が IoT を作れる状態になった!! ※ MQTT とは? IoT 向けに開発された、軽量かつ双方向可能な通信プロトコル 引用元: https://speakerdeck.com/yuuu/picoruby-for-iot-connecting-to-the-cloud-with-mqtt

Slide 7

Slide 7 text

© ZOZO, Inc. 7 セッションを聴いた私 初めてRubyが マイコンで 動いているところを見た!! RubyでIoT実現できるんだ! 楽しそうすぎでは...?!

Slide 8

Slide 8 text

© ZOZO, Inc. 8 セッションを聴いた私 初めてRubyが マイコンで 動いているところを見た!! RubyでIoT実現できるんだ! 楽しそうすぎでは...?! ・・・

Slide 9

Slide 9 text

© ZOZO, Inc. 9 セッションを聴いた私 初めてRubyが マイコンで 動いているところを見た!! RubyでIoT実現できるんだ! 楽しそうすぎでは...?! そういえば家に ESP32あったな...

Slide 10

Slide 10 text

© ZOZO, Inc. 10 セッションを聴いた私 初めてRubyが マイコンで 動いているところを見た!! RubyでIoT実現できるんだ! 楽しそうすぎでは...?! そういえば家に ESP32あったな... ということで、実際に ESP32 を使って IoT システム作ってみた!

Slide 11

Slide 11 text

© ZOZO, Inc. 11 作成した構成 ESPr® Developer 32 Type-C (ESP32-WROOM-32) + フォトダイオード(光センサ) 光センサによる電圧の変化 + VMでのメモリ空き容量

Slide 12

Slide 12 text

© ZOZO, Inc. 12 そこで問題発生 Fatal error: Out of memory 少し欲張った実装をすると... ● error -> abort() -> 強制終了 -> reboot の無限ループに陥る ● 原因 ○ ESP32を始めとしたマイコンはヒープメモリが限られており、Rubyの実行などでメモリを大量 に確保したり、解放しないと枯渇する RubyVM が使用できるメモリ: 102.4KB

Slide 13

Slide 13 text

© ZOZO, Inc. 13 詳細な処理内容をみてみる # ライブラリ読み込み require 'picorubyvm' require 'machine' require 'adc' require 'json' require 'net/ntp' require 'net/mqtt' # 定数定義 AWS_ENDPOINT = "xxxxx-ats.iot.ap-northeast-1.amazonaws.com" DEVICE_ID = Machine.unique_id[0, 8] adc = ADC.new(34) # WiFi 接続待ち sleep 0.5 until ESP32::WiFi.link_connected? # NTP 時刻同期 ntp_base = Net::NTP.get boot_uptime_us = Machine.uptime_us # MQTT 接続(AWS IoT Core) client = Net::MQTT::Client.new( AWS_ENDPOINT, 8883, client_id: "r2p2-#{DEVICE_ID}", ssl: true, ca_file: "/etc/aws/AmazonRootCA1.pem", cert_file: "/etc/aws/device-cert.pem", key_file: "/etc/aws/device-private.key" ) client.connect # メインループ:1 秒ごとに光センサー値を publish while true ts = ntp_base + (Machine.uptime_us - boot_uptime_us) / 1_000_000 light = adc.read client.publish("r2p2/#{DEVICE_ID}/sensor/light", JSON.generate({device_id: DEVICE_ID, ts: ts, light_value: light})) sleep 1 end ① ライブラリ読み込み ② WiFi 接続 ③ NTPを使用した時刻同期 ④ MQTT 接続 ⑤ ループ   (1秒毎にセンサ情報をPublish) 以下がわかりづらい ● どの処理にどれぐらい メモリを使用しているのか ● どこを意識して節約すれば良いか メモリの割り当て状況を確認できる関数 mrbc_alloc_statistics() を使用し、可視化 app.rb

Slide 14

Slide 14 text

© ZOZO, Inc. 14 詳細な処理内容をみてみる # ライブラリ読み込み require 'picorubyvm' require 'machine' require 'adc' require 'json' require 'net/ntp' require 'net/mqtt' # 定数定義 AWS_ENDPOINT = "xxxxx-ats.iot.ap-northeast-1.amazonaws.com" DEVICE_ID = Machine.unique_id[0, 8] adc = ADC.new(34) # WiFi 接続待ち sleep 0.5 until ESP32::WiFi.link_connected? # NTP 時刻同期 ntp_base = Net::NTP.get boot_uptime_us = Machine.uptime_us # MQTT 接続(AWS IoT Core) client = Net::MQTT::Client.new( AWS_ENDPOINT, 8883, client_id: "r2p2-#{DEVICE_ID}", ssl: true, ca_file: "/etc/aws/AmazonRootCA1.pem", cert_file: "/etc/aws/device-cert.pem", key_file: "/etc/aws/device-private.key" ) client.connect # メインループ:1 秒ごとに光センサー値を publish while true ts = ntp_base + (Machine.uptime_us - boot_uptime_us) / 1_000_000 light = adc.read client.publish("r2p2/#{DEVICE_ID}/sensor/light", JSON.generate({device_id: DEVICE_ID, ts: ts, light_value: light})) sleep 1 end 以下がわかりづらい ● どの処理にどれぐらい メモリを使用しているのか ● どこを意識して節約すれば良いか メモリの割り当て状況を確認できる関数 mrbc_alloc_statistics() を使用し、可視化 app.rb puts puts puts puts

Slide 15

Slide 15 text

© ZOZO, Inc. 15 メモリ使用量の可視化 適宜メモリ使用量を確認したい位置に関数を追加し、 モニターにメモリ使用量を出力することで、 そのログを元に Claude がレポートを作成 MAX 102.4KB

Slide 16

Slide 16 text

© ZOZO, Inc. 16 メモリ使用量の可視化 すでに、起動前の処理によって80% のメモリが消費されている

Slide 17

Slide 17 text

© ZOZO, Inc. 17 メモリ使用量の可視化 さらに、 app.rb の require と TLS のコネクションによって かなりのメモリを消費している

Slide 18

Slide 18 text

© ZOZO, Inc. 18 メモリ消費量を確認して見えてきたこと ● 起動時点ですでに、多くのメモリが消費されている ● 特に require での読み込みが消費量多い ○ → 必要最低限の require にすることが有効 ● TLSのコネクションでも、他と比べた際に大きなメモリを消費している とはいえ、現状の実装でもかなり最低限 puts を削除する、送信データ数を少なくする、最低限の rescue にするなどの 小手先テクニックで改善した結果...!!

Slide 19

Slide 19 text

© ZOZO, Inc. 19 動いた!!

Slide 20

Slide 20 text

© ZOZO, Inc. 20 まとめ ● 実際に ESP32 と PicoRuby を使用して、簡単なIoTシステムを構築した ○ Out of memory の頻発から、実際に各メソッドや処理のメモリ使用量を 可視化することで、ボトルネックを把握しながら改善できた ○ → 結果、無事動作させることができた ● 普段使い慣れているRubyで直感的に実装できることのメリットを実感した ○ 一方で、メモリ制約が厳しい環境ではリソース管理が重要となるため 開発効率と実行効率のトレードオフを実体験として理解することができた ● RubyKaigi 2026 でRaspberry Pi pico もいただいたので、また触ってみたい!

Slide 21

Slide 21 text

No content