Masteries

技術的なことや仕事に関することを書いていきます.

「YAPC::Hiroshima 2024」お疲れ様でした!!!

前回はこちら.

papix.hatenablog.com

...というわけで, 「YAPC::Hiroshima 2024」お疲れ様でした. YAPC::Kyoto 2023でちょっと頑張った(つもり)ので, 今回は少し労力を低めにさせてもらって, id:toya さんと id:kobakazu0429 さんと一緒に, 広報班リーダーということでやらせてもらいました( id:kobakazu0429 さんには, 他にも学生支援のオペレーションなどを担っていただきましたが...). まあそういう訳で, 今回は id:kfly8 さんと id:chanyou0311 さんにはカンファレンス運営をするにあたっての面倒な部分を押し付けて担っていただきましたね. 本当にお疲れ様でした.

広報班の役割としては, 本職が編集の id:toya さんにはとにかくその専門スキルを活かしたことをやっていただいて, id:kobakazu0429 さんには(学生なので, 学業の忙しさも当然あるので)リマインド番長として, YAPC::Hiroshima 2024をやっていく上で必要な各種告知のスケジュール管理をしてもらいました. そしてそれ以外は全部俺がやる. なるほど完璧な作戦っスねーっ id:papix が社会人だという点に目をつぶればよぉ〜〜!!!

...でもまあ, 個人的にはYAPC::Japanをやっていく上で必要な仕事は率先してJPAの理事が担っていくべき, と思っているので, 今回は淡々とやっていきました. というか, 「広報については責任持ってやれることをやる」という感じで責任範囲? がしっかり定まっていたので, そういう意味ではむしろやりやすさすらありました(YAPC::Kyoto 2023の時は, 漏れたボールは可能な範囲で俺が拾う or 他の理事に押し付ける, みたいな感じになっちゃっていたので...). そういう意味では, id:kobakazu0429 さんのリマインドにはだいぶ助けていただきました. 記事を書く人とスケジュール管理をする人が同一だと, どうしても妥協というか... ズルズルと後ろにズレていくものですからね.........

あとはまあ, id:toya さんがまあ〜〜〜すごかった. まあとにかく文字のプロなので, とりあえず1を投げたら10で返ってくるし, 文章の推敲やレビューなどをお願いしても過去の経験に基づいてすごく適切なものが返ってきて, むしろ常に原型より良い形になっていて, 大変やりやすかったです. 今回, 割と広報については過去に比べてやっていけた気がしていますが, そのへんは id:toya さんの尽力が大きいです. 座談会とかもほとんど丸投げさせてもらいましたし.

blog.yapcjapan.org

blog.yapcjapan.org

...そういう感じで, とにかく今回の準備はたいへん楽をさせて頂いたので, その分観光情報や交通情報のエントリについて, 結構力を入れて書かせていただきました.

個人的には, カンファレンスに参加するなら, カンファレンスそのもの(トークや参加者とのコミュニケーション)を楽しんでほしいですが, それと同じくらい, その土地土地の観光名所やグルメ, 歴史, 文化も楽しんで欲しい, と思うんですよね(特に学生の参加者の方には!!!). そういう経験や思い出が, 人生に彩りを与えてくれたり, 仕事の意外なところで役立ったりする, こともある... と思っているので. ちょっとでも, そういう経験や体験につながったのなら幸いです.

一方でカンファレンスの当日は, 基本的には広報担当ということで id:toya さんとスタッフ休憩室に詰めていました. 各種定例ポスト(オンラインで視聴している方向けの, トーク開始の周知ポスト)は id:toya さんにお任せして, それ以外の突発的なポストは概ね id:papix が巻き取る, みたいな体制. 後はスタッフ間のコミュニケーションをDiscordでやっていたのですが, 定期的にウォッチして適切に指示を出したり, 情報を横展開したり... という役割も担っていました(いわば, YAPC::Japanの後方司令部の司令官的な役割?). 実際にそういう役割が役立ったかどうかは初めての試みだったので未知ですが, 個人的には「現場にいないのに, 現場の様子がめっちゃわかる」感があって, すごく楽しかったです.


YAPC::Hiroshima 2024を準備するにあたって, 或いは開催中において, 万事がうまくいった, とは思っていません. 広報担当であると同時にJPAの理事でもあるので, いろいろな判断, 決定をする場面がたくさんありました. その選択や行動の結果によって, ご迷惑をおかけしたり, 不快な気持ちにさせてしまった参加者, 関係者の方がいらっしゃると思います. あと, 懇親会で完全に泥酔してしまいまして, 自分の態度や行動で, 不快な気持ちにさせた方がいらっしゃるのではないかと心配しています. 本当にごめんなさい.

一方で, 感想ブログやXのポストを見ている限り, 多くの方がYAPC::Hiroshima 2024を楽しんでくださったように思っていて, ひとまず一安心しています. 今私達は「YAPC::Japanが継続している」世界線にいますが, 新型コロナウイルス禍の中で「YAPC::Japanが終わる」世界線もあったはずで, そういう意味では京都から広島にバトンがつながって, とりあえず当面の危機は脱した... と言えるかもしれません. とはいえ今後が安心できる, という訳ではないのですが...

ところで, PerlやYAPC::Japanを取り巻く環境は新型コロナウイルス禍の間もだんだんと変わっています. そういう状況下で, JPAやYAPC::Japanが現状のままでいいのか? という話はあると思います. YAPC::Hiroshima 2024を開催することで「次」が見えてきた今こそ, その辺の話もしっかりしていく必要があるでしょう(但し, その結果が反映されるのは, 「次の次」のYAPC::Japanになる, と思いますが).

...これからのことはまだ何も見えていませんが, とにもかくにも「次」のYAPC::Japanが開催され, そこで皆様とお会いできることを祈っています. そのために, JPAの理事として, そして1人のPerl Mongerとして, これからもやれることをやっていきたいと思っています.

私とYAPC::Japanと【「YAPC::Hiroshima 2024 非公式予習会」宣伝記事】

この記事は, 「はてなエンジニア Advent Calendar 2023」の1月14日の記事です*1.

qiita.com

昨日は id:kk__777 さんの「Notionのメモをもとに記事を作らせて投稿してみる」でした.

qiita.com


唐突に宣伝なのですが, 1月23日に「YAPC::Hiroshima 2024 非公式予習会」を開催することになりました.

smartbank.connpass.com

YAPC::Hiroshima 2024 非公式予習会とは、初めてYAPC初参加や久しぶりに参加する人がYAPC の歩き方、空気感を知ることができ、本編参加前に参加予定の方々が交流できるイベントです!

ということなので, YAPC::Hiroshima 2024に参加するぞ! という方で, 過去のYAPC::AsiaやYAPC::Japanシリーズに参加したことがなくて, 空気感が分からなくて少し緊張感が... という方は, 是非お越しいただけると嬉しいです. 参加者はYAPC::Hiroshima 2024に参加する人ばかりなので, ここで先んじて知り合いを作っておけば, 当日一緒にYAPC::Hiroshima 2024を楽しめるかもしれません.

ちなみにYAPC::Hiroshima 2024のチケットについては, 1月14日現在Tシャツのサイズが選べない(Lサイズ限定)のチケットがまだ販売されています(学生なら, 「学生チケット」が無料で申し込めます). まだ間に合いますので, 是非参加を検討していただけると幸いです.

passmarket.yahoo.co.jp

...で, ここからが本題なのです. 「YAPC::Hiroshima 2024 非公式予習会」の中で, 「YAPC運営が語るこれまでのYAPCと今回のYAPC(仮)」というタイトルでJapan Perl Association代表理事であるところの id:karupanerura さんと漫談をすることになっています. ぶっつけ本番で行くと何も喋れずに終わりそうなので, このエントリでこれまでの自分とYAPC::Japanシリーズとの関わりを中心に, 簡単にまとめておこうと思いました.

注意

  • 以下, すべて自分語りです. 技術要素はありません
  • 昔の話もあるので, うろ覚えで書いています. 事実と異なる記載があるかもしれません(誤りがありましたらご指摘ください. 修正いたします)

YAPC::Hokkaido 2016

yapcjapan.org

YAPC::Asia 2011に「遠方からの参加者支援制度」で参加して以降, 最後のYAPC::AsiaであるところのYAPC::Asia 2015まで毎年参加していましたが, ずっと一般参加で, スタッフの経験として関わった経験は一切ありませんでした. ただ, YAPC::Japanとしてリブートするにあたり, どなたかに声をかけて頂いてスタッフとして関わるようになりました. 当時スタッフとして何をしていたのかは一切覚えていないのですが, 資料を漁ったところ会場の部屋リーダーをしていたようです.

YAPC::Hokkaido 2016の思い出としては, やはり雪ですかね... 12月上旬の開催とはいえ, 札幌在住者でも「この時期でこれだけ降るのは珍しい」という大雪が降っていて, 会場の最寄り駅から会場までの数分間の移動で「遭難するのではないか...?」みたいな気持ちになったのを覚えています. まさに「試される大地」でした. あとカンファレンス翌日にすすきのを歩いていると野生のPerl Mongerとどんどんエンカウントしたのも楽しかったですね. 雪の影響で日曜日に帰るのを諦めた(月曜日を有給にした)ので, みんなでジンギスカン食べに行ったり海鮮を楽しんだり, とにかく札幌で遊びまくっていた思い出があります.

YAPC::Kansai 2017

yapcjapan.org

実家がある, 地元の関西での開催. ということでこの時もスタッフをやっていたみたいです. ただ当日は, 自分のトークがあったり, 座談会に出たりしていて, 余りスタッフっぽい動きはできていなかったみたいです. YAPC::Kansai 2017は公式サイトのデザインがすごい好きでした(いかにも「大阪ッ!!!!」という感じの雰囲気が出ていて). 後はスタッフパーカーも「黒字に金色のライン」で, なんか関西の兄ちゃんが着ていそうな感じ(?)があったり... どんどん, 「この場所でやるなら, こういう催しをしたいよね!」みたいなアイデアを盛り込める余裕が出てきたのかな, と思います.

YAPC::Fukuoka 2017

yapcjapan.org

YAPC::Japanは, 実は(?)JPAの年度(4月〜翌3月)にあわせて年度内に1回は開催するように設定されています. YAPC::Fukuoka 2017はYAPC::Kansai 2017と同じ年ですが, YAPC::Kansai 2017が3月, YAPC::Fukuokaが7月の開催なので, 翌年度分の開催ということになります. ...しかし今にして思うと4ヶ月後に開催するのは気合が入りまくっていますね!!! 今だと絶対できない気がします. この時, 初めて実行副委員長の役割を担うことになりました. どこからその体制だったのかは記憶が定かではないのですが, YAPC::Japanはだいたい, 開催地の代表の方が実行委員長, JPA側のスタッフが実行副委員長を担当して, 協力しながら準備を進める感じになっているので, この辺りから(理事ではないですが)JPAの運営にも関わっていたはずです.

自分は福岡という街が好きで, Fukuoka.pmが開催される度になるべく足を運んでいたので, 福岡在住の方々と一緒に準備する実行副委員長の役割は適任だったのかな, と勝手に思っています. YAPC::Fukuoka 2017はロゴに「二○加煎餅」のモチーフが取り入れられているのが印象的で, これはちゃんとにわかせんぺい本舗東雲堂さんに許可をもらってやらせていただきました. 実行副委員長という役割はとにかく忙しくて, カンファレンス当日は昼過ぎまで弁当を食べる余裕がなく, 僅かな時間を見つけて弁当を流し込んでまた運営業務に戻る... みたいな感じで右往左往していた思い出があります. とはいえ最後まで大きな問題なく走り切る事ができて, かなりの達成感がありましたね.

YAPC::Okinawa 2018

yapcjapan.org

北海道, 関西(大阪), 福岡と南下してきて, YAPC::Japanは遂に沖縄へ. この時もスタッフとして運営に関わっていたはずです(やっぱり何をしていたかは覚えていない). 会場が, 那覇空港などがある那覇市からかなり外れた沖縄科学技術大学院大学(OIST)で, 会場まで参加者をどう運ぼう...? と検討した結果, バスを用意して運ぶぞ!!! となったのがかなり印象的でした(そういえば, 当日はバスの案内スタッフを担当していた記憶があります). スタッフTシャツか個人スポンサーノベルティでかりゆしが配られていたのも沖縄らしさが出ていてよかったですね.

YAPC::Tokyo 2019

yapcjapan.org

久々の東京, ということでこれまでから少し規模を拡大しての開催となったYAPC::Tokyo 2019. 「規模の拡大」に対応するために, イベント会社の活用を狙ったりなど新しい取り組みがありました. この時何をしていたかは結構覚えていて, 会場の部屋リーダーをしていたはずです. なぜ覚えているかというと自分がトークをする部屋で, スタッフとして部屋リーダーに任じられており, 司会進行をしていたので, 「自分のトークを司会の自分が紹介してそのまま登壇する」という謎ムーブメントをした記憶があるからです(?).

大きい会場で, 懇親会も大人数で開催できて, 久々にたくさんの人が集まって「大同窓会」みたいな雰囲気があって楽しかったですね. ベストトーク賞を受賞したsongmuさんを胴上げしたのもいい思い出でした. そしてそこで, 「次のYAPCは京都だ!!!」ということが決まり, 「京都で開催するならば, 京都に本社のあるはてなの人間が実行副委員長をするのがスジ(?)であろう」, という謎の理論で, YAPC::Japanシリーズになってから2回目の実行副委員長職を拝命した, のですが...

そういえばこの頃から, Japan Perl Associationの理事になったみたいです.

blog.perlassociation.org

YAPC::Nagoya::Tiny (2019年)

yapcjapan.connpass.com

「少し小さめのイベントもやってみよう」という施策でやったのかな...? このへんもほとんど記憶がないですね... ただこのイベントは, 前々から友達と計画していた台湾旅行と重なっていたので, YAPC::Asia 2011以来皆勤賞だったのに, 初めて欠席することになりました.

YAPC::Kyoto 2020 (2020年, 延期)

これはマジで辛かったですねえ〜〜〜〜〜〜〜... ちょうど新型コロナウイルス禍が始まった直後の開催で, 先の見通しが一切見えない状況で, 開催する? 延期する? の判断をする必要がありました. 最終的にはJPAの理事とも議論を重ねて, 一旦延期するという判断を下すことになりました. 不幸中の幸いだったのは, 会場費などの支払い前に判断を下せたので, キャンセル料などはほとんど発生せず, 金銭面のダメージをかなり抑えることができた点でした. この時ちょっとでも判断をミスっていたら, YAPC::Japanはここで終わっていた可能性も十分にある... と個人的には思っていて, なんというかうまく乗り越えることができてよかった... と思います.

これについては, とにかく「延期だ延期!!!」と言い続けていたのが記憶に残っています. とにかく「中止」と言ってしまうと, ここでYAPC::Japanが終わってしまう可能性があると思っていて, 「中止, 残念でしたね」と言われる度に「延期ですっ!」と言うようにしていました. そしてそれを後押しするように, 新型コロナウイルス禍だからこそ(?)できるYAPC::Japanを, という施策を数年続けることになります. なんとかまたみんなで集まれる日を祈りながら...

Japan.pm (2021年)

yapcjapan.connpass.com

YAPC::Japanシリーズとしては初めての完全オンラインイベントでした. 「YAPC::Japanの体験をオンラインで作る」のを目標にしていましたが, 最初からそれを実現するのは難しいので, まずは「Japan.pm」という名前でやってみよう! となったのが名前の由来です. 「Japan.pm」でググると, Googleは「Japan Prime Minister」と解釈するようで, 当時だと検索する度に菅義偉さんが登場(?)されていたのが記憶に残っています.

この時は司会進行を担当していたのかな...? オンラインだからこそできる施策をいろいろ試して, オフライン開催のYAPC::Japanには及ばないまでも, それに近い体験をオンラインでも作れそうだ, となって, 翌年のYAPC::Japan::Onlineに繋がります.

YAPC::Japan::Online (2022年)

yapcjapan.org

Japan.pmで得た知見をつぎ込んで作り上げた, YAPC::Japanの体験をオンラインで作る集大成. この時も司会進行をしていた気がします. この時はとにかく料理が豪華でした. 軽食としてピザハットさんからピザが届いたり, 懇親会の料理でチキンが届いたり. カンファレンス本編はもちろん, それ以外(企画, 懇親会, あるいはカンファレンス前後の時間)でもワクワク楽しめる要素があるのがYAPC::Japanのいいところ... だと自分は思っているので, それがオンラインの形でも再現できたのが良かったです.

とはいえやっぱり, オンラインの難しさというのはあって, そろそろオフラインでもやりたいよねえ... という気持ちはみんな持っていたと思います. ワクチンの普及, 緊急事態宣言の終了, 全国旅行支援といった施策の実施を受けて, そろそろYAPC::Kyotoをリブートしよう... ということになりました.

YAPC::Kyoto 2023

yapcjapan.org

実行副委員長としてあれこれしていました. とにかく, 延期することになったYAPC::Kyoto 2020をそのままリブートして, 更に盛り上げてやっていくぞ!!! という気持ちでした. 2019年以来, と考えると4年のブランクがあるので, とにかく全部思い出しながら準備することになりましたし, 京都らしさが出る施策(Perl神社とお賽銭の寄付, 護符ステッカーなど...)をどんどん盛り込んでいった結果, どんどんやることが増えて最終的には毎日がお祭り騒ぎでしたね.

なんとかここまでYAPC::Japanを続けてきたけど, ここでコケるとまたYAPC::Japanが終わり得るのでは? というプレッシャーもあったのですが, 最終的にはこちらも大きな問題なく終わることができたかと思います. YAPC::Japanというイベントも, いつか必ず終わる時が来るとは思っているのですが, 自分としてはなるべくそれを後ろに遅延させたいと思っていて, YAPC::Kyoto 2023の開催でそれを実現できたのはものすごく嬉しかったですし, 内心自画自賛しています(?). 本当に, YAPC::Kyoto 2023に関わって下さった皆様全員を今でも誇りに思っています.

YAPC::Hiroshima 2024

yapcjapan.org

YAPC::Kyoto 2023で燃え尽きたので, 今回は広報担当としてふわふわとスタッフ業をしています. やっぱり実行副委員長といった役割を一度担うと, 一時的に燃え尽きる部分はあるのでクールダウンは必要ですね...(それにしても少し動けていなさすぎるので, 申し訳無さがMAXではあります). 持続可能なYAPC::Japanを考えると, その辺りちゃんと仕組み化して, みんなが(同時に/長期間)燃え尽きないようにする, いわば燃え尽きる期間をコントロールできるようになる必要がありそうです.

「YAPC::Japanらしさ」とは?

多分, YAPC::Japanに参加したことがなくて, 「YAPC::Hiroshima 2024 非公式予習会」に参加される皆様は, 「結局のところ, YAPC::Japanってどういうカンファレンスなんだろう?」というところを思われていると思うので, 最後に自分が思う(あくまで自分 = papixが思う)「YAPC::Japanらしさ」について言及しておこうかと思います.

YAPC::Hiroshima 2024の公式サイトには「YAPCはYet Another Perl Conferenceの略で、Perlを軸としたITに関わる全ての人のためのカンファレンスです。」と書かれていますが, この「Perlを軸とした」がYAPC::Japanらしさの1つ, だと思っていて, Perlネタはもちろんアリ, それ以外のネタも(たとえPerl以外の言語であっても)大歓迎, とにかく何でもアリ!!! というのは結構珍しい雰囲気, いろいろとカンファレンスが開催されている中でも, 独特の立ち位置なのではないかと思います. @pyama86さんは「異種格闘技戦」と仰っていましたが, これもYAPC::Japanを表す良い表現だなと思っています.

Perlが好きな人, 今現在Perlを書いている人はもちろんのこと, かつてPerlを書いていた人, そして今はGoやRubyやScalaなど, 他の言語を書いている人, あるいはスクラムマスターやマネージャーなどのロールを担うようになった人, いろいろな方が集まる場になっています. もしかすると最近YAPC::Japanに参加するようになった方の中には, 「Perlなんて書いたことないや...」という人もたくさんいらっしゃるのではないでしょうか. なので, カンファレンスで披露される全部のトークが刺さる! ということはないでしょうが, Webの技術に関わりがあるエンジニアであれば, 何かしら刺さるトークが1つは見つかる, みたいなカンファレンスだと思っています(papixはYAPC::Japanはそういうカンファレンスでありたい! と思っています). つまり, YAPC::JapanはPerlだけにとどまらない様々な領域の知識, 技術, 知見に触れられる場になっています.

だからこそ, YAPC::Japanには学生の方に参加して頂きたい!!! と思っていて, 自分もYAPC::Asia 2011でお世話になった「遠方からの参加者支援制度」から生まれた「学生旅費支援制度」は可能な限り継続したいな... と思っています. 学生の知り合いがいらっしゃったら是非YAPC::Japanを紹介して頂きたいですし, 学生にも刺さるトークを応募して頂けると個人的には嬉しいですね. この辺りの「学生への姿勢(?)」も, YAPC::Japanの特色かもしれません(もっと良くする余地はあるとは思っていますが...).

さいごに

始まりがあれば終りがある, ということで, YAPC::Japanというカンファレンスもいつか終わりが来るのでしょう. 自分としては, YAPC::Japanとその前身であるYAPC::Asia, そしてPerlコミュニティには返しきれない恩があるので, その象徴の1つであり, その名のもとにみんなが集まれる「YAPC::Japan」というカンファレンスをなるべく続けられるよう, Japan Perl Associationの理事としても可能な限り尽力していきたいと思っています.

...うーん, なんというか, 勢いよく雑に書いてしまったので, 最初から最後まで乱文というか, とりとめのない文章になってしまって反省しています. ただこの文章を通して, ちょっとでも, YAPC::Japanというカンファレンスに興味を持っていただければ幸いです. 皆様と「YAPC::Hiroshima 2024 非公式予習会」と「YAPC::Hiroshima 2024」でお会いできることを楽しみにしています!!!


「はてなエンジニア Advent Calendar 2023」, 1月15日の担当は id:fxwx23 さんです. 宜しくお願いします.

*1:投稿日が1月15日に見えるかもしれませんが気にしないでください, 少し遅れました...

Perlの「後置if」について

この記事は, 「はてなエンジニア Advent Calendar 2023」の10日目の記事です.

qiita.com

9日目の記事は, id:cockscomb さんの「SwiftにおけるTyped throwsの現在」でした.

cockscomb.hatenablog.com

そして「Perl Advent Calendar 2023」の10日目の記事でもあります.

qiita.com

9日目の記事は, @bayashi_net さんの「Module::Setupをgo moduleのセットアップにも使っている話」でした.

bayashi.net


先日, Hatena Tech Book Vol.2に「Perlの未定義動作110連発」という記事を書きました.

techbookfest.org

この記事は, 以前このブログに書いた「Perlの未定義動作100連発」の加筆修正版です.

papix.hatenablog.com

「Perlの未定義動作100連発」や「Perlの未定義動作110連発」で紹介した未定義動作は, そのほとんどが「まあ, そんな書き方はしないだろう...?」というものですが, その中で比較的よく見かけるのが「my + 後置if」です.

注意: (my $x if ... のような) 条件構造やループ構造で修飾された my state,our 文の振る舞いは 未定義 です。 my 変数の値は undef かも知れませんし、以前に代入された値かも 知れませんし、その他の如何なる値の可能性もあります。 この値に依存してはいけません。 perl の将来のバージョンでは現在のバージョンとは何か違うかも知れません。 ここには厄介なものがいます。

use strict;
use warnings;
use DDP;

my $num1 = 123 if 1;
my $num2 = 345 if 0;

p $num1;
p $num2;

こういう実装は, レビューで指摘してもらう前に気付きたいものです. 何か良い手はあるかな? と思ったらPerl::CriticにPerl::Critic::Policy::Variables::ProhibitConditionalDeclarationsというポリシーがあるので, これで検知することができます. 先のコードであれば, 次のように警告してくれます:

Variable declared in conditional statement at line 5, column 1.  Declare variables outside of the condition.  (Severity: 5)
Variable declared in conditional statement at line 6, column 1.  Declare variables outside of the condition.  (Severity: 5)

ちなみに, Perl::LintにもPerl::Lint::Policy::Variables::ProhibitConditionalDeclarationsというポリシーがあるので, 同様に検知することができます.

余談

ところで, ここまで何気なく「後置if」と呼んでいました. 実は, Perlのドキュメントの日本語訳であるところのperldoc.jpを確認してみると, 「後置if」というワードは存在しません. この書き方は, perlsynの「文修飾子」で紹介されているので, むしろ「if文修飾子」と呼ぶべきなのかもしれません.

perldoc.jp

...となると, 「後置if」という呼び方の由来(?)はどこにあるんだろう, ということが気になってきますね. これについては, 機会があれば調べてみたいと思います.


「はてなエンジニア Advent Calendar 2023」の明日の担当は id:ne-sachirou さん*1です. よろしくお願いします.

*1:12/11が誕生日とのこと, おめでとうございます!!!

MySQLのDATETIMEをとにかく素早くPerlのDateTimeオブジェクトにしたい

この記事は, Perl Advent Calendar 2023の6日目の記事です. 12月6日の26時くらいに公開されているかもしれませんが気にしないでください.

qiita.com

5日目の記事は, @shogo82148 さんの「Amazon Linux 2023ベースのAWS Lambda Perl Runtimeを公開しました」でした.

shogo82148.github.io


タイトルにある通りで, MySQLのDATETIME(例えば2023-12-07 12:34:56)を, PerlのDateTimeオブジェクトにしたい訳です. まあ, 素早さ最優先ならTime::Momentを使いましょう, で完結するわけですが...

metacpan.org

...ただまあ, 様々な事情でどうしてもDateTimeを使いたい, という場合もあるでしょう. そういう時にどういう選択肢が取りうるか? というのを考えたのでご紹介します. もし, もっと良い作戦があったら教えてください.

王道

まず王道? の選択肢は, DateTime::Format::MySQLを使うことでしょう. MySQLのDATE, DATETIME, TIME, TIMESTAMPをパースして, DateTimeのオブジェクトを返してくれる君です.

metacpan.org

別解

Time::StrptimeのDESCRIPTIONを見ると, 日時のパースで一番速いのはやはりTime::Momentのようです.

metacpan.org

そこで, 「DATETIMEのparseだけTime::Momentを使って, その結果をDateTimeにする」という選択肢を思いつきました. 但し, Time::Momentのfrom_stringは, そのままMySQLのDATETIMEをパースできないので,

my $str = '2023-12-07 12:34:56';

$str .= 'Z' if substr($str, -1, 1) ne 'Z';
substr($str, 10, 1, 'T') if substr($str, 10, 1) eq ' ';

my $tm = Time::Moment->from_string($str);

...みたいな手当が必要になりますが. 後は, Time::Momentのオブジェクト(にある日時の情報)を使ってDateTimeのオブジェクトをnewしてあげれば良いわけです.

推測するな計測せよ

具体的にどれくらい素早くなるのでしょうか? 計測してみましょう. 以下の4つをBenchmarkを使って比較しました:

  • DateTime::Format::MySQL
  • Time::Moment + DateTime#new
  • Time::Moment + DateTime#from_epoch
  • Time::Moment (比較用)

DateTime::Format::MySQLが一番遅くて, Time::Momentが一番速いのはまあ確定として, Time::Momentでパースした結果からはDateTime#newを使う選択肢と, DateTime#from_epochを使う選択肢があります. なんとなくですが, 後者の方がepochからyearやhourなどを求める処理が必要なので, 誤差レベルで遅そうなイメージがありますが... 果たして.

use strict;
use warnings;

use Benchmark qw(timethese);
use DDP;

use DateTime::Format::MySQL;
use DateTime;
use Time::Moment;

my $str = '2023-12-07 12:34:56';

sub datetime {
    my ($str) = @_;
    return DateTime::Format::MySQL->parse_datetime($str);
}

sub time_moment_and_from_epoch {
    my ($str) = @_;
    $str .= 'Z' if substr($str, -1, 1) ne 'Z';
    substr($str, 10, 1, 'T') if substr($str, 10, 1) eq ' ';

    my $tm = Time::Moment->from_string($str);
    return DateTime->from_epoch($tm->epoch);
}

sub time_moment_and_new {
    my ($str) = @_;
    $str .= 'Z' if substr($str, -1, 1) ne 'Z';
    substr($str, 10, 1, 'T') if substr($str, 10, 1) eq ' ';

    my $tm = Time::Moment->from_string($str);
    return DateTime->new(
        year       => $tm->year,
        month      => $tm->month,
        day        => $tm->day_of_month,
        hour       => $tm->hour,
        minute     => $tm->minute,
        second     => $tm->second,
    );
}

sub time_moment {
    my ($str) = @_;
    $str .= 'Z' if substr($str, -1, 1) ne 'Z';
    substr($str, 10, 1, 'T') if substr($str, 10, 1) eq ' ';

    return Time::Moment->from_string($str);
}

# パースした結果, 同じ epoch を指していることを確認している
p datetime($str)->epoch;
p time_moment_and_from_epoch($str)->epoch;
p time_moment_and_new($str)->epoch;
p time_moment($str)->epoch;

timethese(2_000_000, {
    'datetime'                   => sub { my $obj = datetime($str) },
    'time_moment_and_from_epoch' => sub { my $obj = time_moment_and_from_epoch($str) },
    'time_moment_and_new'        => sub { my $obj = time_moment_and_new($str) },
    'time_moment'                => sub { my $obj = time_moment($str) },
});

以下は実行結果です:

$ perl datetime.pl
1701952496
1701952496
1701952496
1701952496
Benchmark: timing 2000000 iterations of datetime, time_moment, time_moment_and_from_epoch, time_moment_and_new...
  datetime: 35 wallclock secs (35.27 usr +  0.23 sys = 35.50 CPU) @ 56338.03/s (n=2000000)
time_moment:  1 wallclock secs ( 0.62 usr +  0.00 sys =  0.62 CPU) @ 3225806.45/s (n=2000000)
time_moment_and_from_epoch: 18 wallclock secs (17.86 usr +  0.12 sys = 17.98 CPU) @ 111234.71/s (n=2000000)
time_moment_and_new: 25 wallclock secs (24.52 usr +  0.07 sys = 24.59 CPU) @ 81333.88/s (n=2000000)

というわけで, 結果は速い順に Time::Moment > Time::Moment + DateTime#from_epoch > Time::Moment + DateTime#new > DateTime::Format::MySQL, でした. DateTime#newよりDateTime#from_epochの方が素早いんですね. というかこうやって見るとTime::Momentが早すぎる...

高速化という意味では, やはりTime::Moment化するのが理想です. とはいえそうもいかない場合はTime::MomentでパースしてDateTime#from_epochする... という手でも, ベンチマークの結果を見る限り50%くらい高速化できるので, やってみる価値はありそうですね.

忘備録: List::Util#anyかhashか

Perlを書いている時, 「いずれかと一致するなら...」みたいな条件を書く時に, List::Utilのanyを使うことがある.

metacpan.org

例えば, @ids という変数に何かしらのIDの一覧があって, あるIDが$idとして渡ってきた時に, $id@idsに含まれているかどうか, みたいなのは, anyを使って次のように書ける:

if (any { $_ eq $id ) @ids) {
    ...
}

但し, このコードは@idsに含まれる要素が増えれば増えるほど処理時間が伸びるはず. なので, こういう場合はhashを使って判定する方が早そうに思える:

my $hash = { $_ => 1 } @ids;
if ($hash{$id}) {
    ...
}

...というのをBenchmarkで確認してみたので, 忘備録としてメモっておきます.

use strict;
use warnings;

use List::Util qw(any);
use Benchmark qw(:all);

my $data = [1..10];
my $first = $data->[0];
my $last = $data->[-1];

my %prepared_hash = (map { $_ => 1 } $data->@*);

timethese(100_000_000, {
    prepared_hash => sub {
        $prepared_hash{$last};
    },
    hash => sub {
        my %hash = (map { $_ => 1 } $data->@*);
        $hash{$last};
    },
    any_first => sub {
        any { $_ eq $first } $data->@*;
    },
    any_last => sub {
        any { $_ eq $last } $data->@*;
    },
});

prepared_hashはhashを事前に準備するパターン. hashは都度hashを生成するパターンで, any_firstany_lastは先頭/末尾との一致をanyで判定するパターン. anyを使うパターンでも, any_lastよりもany_firstの方が先に処理が終わる(1回目でanyの条件部が真になるので, そこで処理が打ち切られる)はず. 果たして結果は...

Benchmark: timing 100000000 iterations of any_first, any_last, hash, prepared_hash...
 any_first: 24 wallclock secs (24.48 usr +  0.14 sys = 24.62 CPU) @ 4061738.42/s (n=100000000)
  any_last: 44 wallclock secs (43.14 usr +  0.22 sys = 43.36 CPU) @ 2306273.06/s (n=100000000)
      hash: 112 wallclock secs (110.83 usr +  0.50 sys = 111.33 CPU) @ 898230.49/s (n=100000000)
prepared_hash:  3 wallclock secs ( 2.40 usr +  0.00 sys =  2.40 CPU) @ 41666666.67/s (n=100000000)

結果としては, hashを事前に準備するパターン > anyを使うパターン > hashを都度準備するパターン, となりました.

なので, @idsに該当する部分が不変で, 判定が何度も呼び出される場合は, anyを使わずに事前にhashを用意してあげた方が素早く処理できそうですね.

最近のPerlなら, こういう感じでstateを使ってあげる手もありそうです:

state %hash = map { $_ => 1 } @ids;
if ($hash{$id}) {
    ...
}