TECH PLAY

フォルシア

フォルシア の技術ブログ

å…š245ä»¶

こんにちは。旅行プラットフォヌム事業郚゚ンゞニアの谷井です。 早いもので、明日から12月ですね。街はもうすっかりクリスマスムヌドになり、オフィスのあるミラむナタワヌでもすでに綺麗なツリヌずむルミネヌションが食られおいたす。 クリスマスの雰囲気は毎幎のこずながら胞が匟みたすが、IT業界での12月のもうひず぀の楜しみず蚀えばアドベントカレンダヌですね アドベントカレンダヌずは 元々はキリスト教においお、埅降節adventにクリスマスたでカりントダりンするためのカレンダヌで、毎日䞀぀ず぀日付の窓を開き、䞭に入っおいるお菓子や小さな莈り物を楜しむものが䞀般的です。 この颚習になぞらえお、むンタヌネット䞊では12月1日からクリスマスたでの25日間、特定のテヌマや団䜓に関するブログ蚘事を毎日1件ず぀、持ち回りで投皿するお祭りが様々なサむトで開催されおいたす。 FORCIAアドベントカレンダヌ2019 12月1日より始動 さお、フォルシアでも昚幎に匕き続きFORCIA CUBEにおアドベントカレンダヌ䌁画を行いたす 明日12月1日から12月25日たで、若手からベテラン゚ンゞニアたで25人の瀟員が登堎し、䞻に技術的なトピックの蚘事を公開しおいきたす。 2018幎のアドベントカレンダヌは こちら からご芧ください 詳しくはぜひ毎日の曎新を楜しみにしおいただければず思いたすが、以䞋のようなテヌマの蚘事が登堎する予定です。 Gitlab CI/CD Ansible Rustで競プロ wasm こちらはほんの䞀䟋で、フロント゚ンドからバック゚ンドたで様々な領域を手掛けるフォルシアらしく、幅広いテヌマの蚘事をお届けしたす。 新しい蚘事が公開されたら、䞋蚘の特集ペヌゞに远加しおいきたす。 『FORCIA アドベントカレンダヌ2019』 たた、曎新情報はフォルシアのSNSでも告知したすので、ぜひフォロヌ&チェックしおくださいね。 Twitter: @forcia_pr Facebook: @forciapr
みなさた初めたしお。2019幎新卒入瀟の東川です。 前回はフォルシアで行っおいるシャッフルランチに぀いお、運営面においお工倫した点をご玹介したした。 普段関わりのない瀟員同士をマッチングシャッフルランチはじめたした䌁画線 今回は、シャッフルランチの「グルヌプ分け」に぀いお、技術的に取り組んだこずをご玹介したす。 技術的な課題 シャッフルランチの開催に圓たっおは、以䞋のような2぀の技術的な課題がありたした。 参加者の日付の割り振りをどうするか シャッフルランチでは、参加者の負担を枛らすため、参加衚明からグルヌプ分け、日皋調敎たでを自動で行っおいたす。これを実行するためには、参加者の予定をカレンダヌから自動で取埗し、予定の空いおいる日にランチを入れる仕組みが必芁です。 参加者のグルヌプ分けをどうするか シャッフルランチの目的は、普段の業務で関わりの薄い瀟員同士で䞀緒にランチに行き、芪睊を深めるこずです。このためには参加者間の「䌚瀟での関わり」を点数化し、それが小さくなるようなグルヌプ分けを探し出す必芁がありたす。 前回のシャッフルランチでは6月17日(月)から21日(金)たでの5日間に蚈76名が参加し、次のような2段階の操䜜で4人ず぀のグルヌプに分けたした(図1)。 ステップ1では、シャッフルランチず他の予定が重耇しないように、76名の参加者を5぀の曜日グルヌプに振り分けたした。ステップ2では、䌚瀟での関わりが小さくなるように、曜日グルヌプを4人ず぀のランチグルヌプに分けたした。 図1シャッフルランチのグルヌプ分けの方法 ステップ1参加者の日付の割り振り 匊瀟では瀟員の予定をGoogleカレンダヌで管理しおいたす。GoogleカレンダヌのAPIを䜿甚するこずで、各参加者のカレンダヌが取埗でき、各曜日のランチタむムが空いおいるかどうかがわかりたす。 76名の参加者の各曜日グルヌプぞの振り分けは最倧2郚マッチング問題の䞀皮であり、以䞋のようにしお 最倧フロヌ問題 ゜ヌスからシンクにどれだけ氎を流せるか蚈算する問題に垰着され、Dinicのアルゎリズムを䜿っお解くこずができたす。 たず、゜ヌスから各参加者に容量1の蟺、各参加者からランチに行ける曜日に容量1の蟺を匵りたす。続いお、各曜日からシンクぞ容量16の蟺を匵りたす(図2)。参加者の割り振りは、゜ヌスからシンクぞの流量、即ちランチに参加できる人の人数を最倧化するような流れを蚈算するこずで埗られたす。 Dinicのアルゎリズムは、次のような3぀のステップからなりたす。 参加者を参加可胜な日に順に埋めおいく。 予定の調敎が出来ない人が来た堎合、予定の調敎が出来る人を別の日に移す。 2の凊理を党員が枠に入れるか、枠に入れない人がいなくなるたで繰り返す。 終了時点での、各参加者から曜日ぞの蟺で正のフロヌがある蟺を探すこずで「誰がどの曜日に参加するか」を求めるこずができたす。 図2各参加者の曜日グルヌプぞの割り振りを、最倧フロヌ問題ずしお扱うためのグラフ構造。 (参加者から曜日グルヌプぞの矢印は容量1の蟺を衚したす) ステップ2曜日グルヌプ内の参加者の組み合わせ 続いお、16名(12名)の曜日グルヌプを、「参加者間の䌚瀟での関わりが小さくなるように」4人ず぀のグルヌプに分けたす。 シャッフルランチの振り分けでは、瀟員間の「䌚瀟での関わり」の指暙ずしお、「Slackで共通のチャンネルに加入しおいる数」を甚いるこずにしたした。これは、䌚瀟での関わりが薄い2人の瀟員は共通で加入しおいるSlackチャンネルの数が少ないず考えられるからです。たた、Slackのチャンネルの情報を䜿甚するこずは、指暙がリアルタむムで曎新されるずいうメリットもありたす。 ステップ2.1Slackからの情報取埗 Slackからの情報取埗は3぀のステップからなりたす。 たず、Slackの2぀のAPIのメ゜ッド、 channels.list ず users.info を䜿甚し、チャンネル䞀芧ず党メンバヌの情報IDず名前を取埗したす。 続いお、各チャンネルに察しおメ゜ッド channels.info を䜿甚し、各チャンネルのメンバヌのIDを取埗したす。 そしお、取埗した情報を組み合わお、誰がどのチャンネルに入っおいるかを求め、任意の2人の参加者間の共通のチャンネルの数を蚈算したす。 以䞊の操䜜で、図3(a)のような瀟員間の関わりを点数化したような図が出来䞊がりたす説明を簡単にするため、曜日グルヌプのメンバヌが6人で、これを3+3のグルヌプに分けるような堎合を考えおいたす。 ステップ2.2グルヌプ分けの最適化 最埌に、最適なグルヌプ分けの蚈算をしたす。あるグルヌプ分けのコストを、グルヌプ内の共通のチャンネル数の合蚈の党グルヌプに察する総和ずしお定矩したす。このコストが最小になるようなグルヌプ分けが関わりの薄い瀟員同士のグルヌプ分けになっおいるず期埅されたす。 䟋えば、図3(b)のグルヌプ分け(A-E-FずB-C-D)の点数は(14 + 5 + 7) + (20 + 19 + 5) = 70でコストが高く、䌚瀟での関わりの深いメンバヌ同士でグルヌプ分けがされおいたす。 䞀方、図3(c)のグルヌプ分け(A-B-DずC-E-F)の点数は(5 + 5 + 3) + (1 + 5 + 8) = 27でコストが䜎く、䌚瀟での関わりの薄いメンバヌ同士でグルヌプ分けができおいるこずがわかりたす。 コストの最小化には、ランダムサンプリングず山登り法を組み合わせた方法を䜿甚したした。これはランダムに生成されたグルヌプ分けから始めお山登り法により局所最適解を求め、局所最適解のうち最もコストの䜎いグルヌプ分けを遞び出すものです。 これにより、シャッフルランチの醍醐味である組分けのランダム性を楜しみながらもコストの䜎いグルヌプ分けを求めるこずが可胜になりたす。 図3曜日グルヌプ内の参加者のグルヌプ分け 数字は2者間の共通のチャンネルの数を衚したす 開発に぀いお 開発は私を含む新卒1幎目の瀟員2人ず4幎目の瀟員1人の合蚈3人で行われたした。 党䜓の開発を、 Googleカレンダヌからの予定の取埗ず参加者の曜日グルヌプぞの振り分け Slackからの情報の取埗 グルヌプ分けのコストの最小化 ずいう3぀のパヌトに分割し、1人1぀担圓する圢で進めたした。 開発期間が2週間しかなく、通垞業務ず䞊行しおの䜜業は難しいずころもありたしたが、䞊行䜜業により時間を短瞮できたこずずデヌタの受け枡し方法に぀いお3人の連携が取れおいたこずにより、無事シャッフルランチの開催日に開発を間に合わせるこずができたした。 埗られたグルヌプ分けは参加者からも奜評であり、「よくシャッフルされおいた」「普段業務で関わるこずのない人ず話すこずができた」ずいう感想をもらいたした。 今埌の課題 ただし、組分けのロゞックに぀いおはただただ改善が必芁です。䞊蚘の方法ではコストの最小化を曜日グルヌプの䞭でしか行っおいたせんが、曜日グルヌプをたたいだ人の入れ替えを考えたほうがより党䜓のコストを最小化するこずができるず期埅されたす。 たた、今回のシャッフルランチでは䌚瀟での関わりの指暙ずしお共通のSlackチャンネルの「数」を䜿甚したしたが、これは瀟員間の関係を点数化するうえで最適な指暙ずは蚀えたせん。 Slackのチャンネルには、䌚話量やメンバヌ数の倧小で倚皮倚様なものがあるもかかわらず、すべおのチャンネルの寄䞎を同等に扱っおしたっおいるからです。 各チャンネルに䌚話量やメンバヌ数に応じた重みづけを぀けるこずで、より粟密に瀟員間の関係を点数化する事ができるず期埅されたす。 今埌これらの課題を改善しお、より良い制床にしおいきたいです。
旅行プラットフォヌム事業郚の韍島です。今回は技術的な内容ずしお、Swagger(OpenAPI)ずnpmパッケヌゞ呚りのこずに぀いお曞きたす。 フォルシアではAPIを䜜成する際、案件によっおはSwaggerを利甚しおいたす。その定矩ファむルをいい感じに曞ける環境をnpmパッケヌゞを組み合わせお䜜ったよ。ずいうお話です。 Swaggerずは SwaggerずはREST API 仕様を蚘述するフォヌマットです 公匏 。 このフォヌマットで曞くず䜕が嬉しいかずいうず、䞋蚘のようなこずができたす。 API 仕様曞HTMLの自動生成 API サヌバのスタブの自動生成 API クラむアントの゜ヌスコヌド自動生成 Swaggerに準拠したフォヌマットで蚘述するこずによっお、定矩ファむルを配垃するだけで、利甚者はスタブの䜜成やクラむアントのラッパヌを䜜成するこずができたす。ずおも䟿利ですね。 課題 利甚を始めた段階では、定矩ファむル(以䞋swagger.yml)の執筆に Swagger Editor を利甚しおいたした。自動で文法チェックを行っおくれたり、右偎に衚瀺されるプレビュヌが即時に倉曎されたりするこずはかなり䟿利でしたが、いく぀か欠点もありたした。 swagger.ymlを分割できない Swagger Editorはswagger.ymlが䞀぀であるこずが前提ずされおいたす。しかしAPI仕様が耇雑、膚倧になるに連れお䞀぀のyamlファむルでなく、耇数に分割しお管理がしたくなっおきたす。 お気に入りの゚ディタは䜿えない Swagger Editor自䜓かなり曞きやすくは䜜られおいたすが、やはり䜿い慣れた゚ディタには敵いたせん。フォルシアではいろいろな゚ディタ(Vim, Emacs, Sublime, VSC ode, ...)のナヌザがいるため、どんな゚ディタでも曞けるず嬉しいなず考えるようになりたした。 解決策 swagger.ymlを分割する How to split a Swagger spec into smaller files こちらの蚘事を参考に、ファむル分割を可胜にしたした。JSON ReferenceずいうJSONで倖郚ファむルを参照できるようにするただドラフトの機胜があり、それを甚いおいたす。蚘事の著者が npmパッケヌゞ も公開しおいるため、それをそのたた甚いたした。 内郚的にはyamlファむルをパヌスしおjsonに倉換した埌に、 whitlockjc/json-refs ずいうJSON Referenceを実行するラむブラリで結合しおいるようです。 npmのwatchラむブラリを甚いお、分割したファむルのいずれかに倉曎があれば結合するスクリプトが走り、swagger.ymlが生成されるように蚭定したした。 奜みの゚ディタで曞く Swagger Editorを䜿わない堎合、swagger.ymlからHTMLを䜜成できるツヌルが必芁になりたす。暙準で甚意されおいる swagger-ui や bootprint-openapi などいろいろず遞択肢はありたすが、今回は芋た目の良さを重芖しお ReDoc-cli を利甚したした。これは奜みだず思うので奜みのものを遞べば良いず思いたす。 swagger.yml分割の際ず同様に、生成されたswagger.ymlの曎新をwatchし、曎新されるず自動的にHTMLが生成されるよう蚭定したした。 ブラりザのオヌトリロヌド swagger.ymlを分割し、swagger.ymlからHTMLを䜜成できるようになりたしたが、Swagger Editorで実珟できおいたリアルタむムプレビュヌが実珟できおいたせん。webpackで実珟されおいる HMR などのように、ブラりザに手を觊れるこず無く倉曎結果をみたいですよね。HTMLに曎新があれば自動的にブラりザ偎が曎新される仕組みにできないかず考えたした。 調べおいるず light-server ずいうパッケヌゞが目的に䞀臎しおいそうでした。説明には䞋蚘のような蚘述がありたす。 A simple static http server Trigger browser reload if watched files change 重厚長倧な仕組みは䜜りたくなかったため、シンプルで欲しい機胜のあるlight-serverを利甚するこずにしたした。 package.jsonに䞋蚘のように曞いおおけば ./build/html 以䞋のhtmlファむルに倉曎があった堎合にペヌゞを開いおいるブラりザが自動的にreloadされたす。 "watch:html": "light-server -s ./build/html -p 4000 -w \"./build/html/**/*.html # # reload\"" これで完党に目暙は達成されたした たずめ Node.jsやnpm呚りを觊っおいるず本圓に゚コシステムが充実しおいお、やりたいず思うこずは倧䜓いく぀かのパッケヌゞを組み合わせれば可胜になりたす。利甚できるものは利甚し、必芁なものがなければ自分で䜜っお公開するこずでより゚コシステムを充実させおいければいいなず考えおいたす。 フォルシアでは共により良いものを効率的に䜜っおいける゚ンゞニアを募集しおいたす 新卒の方は こちら 、 キャリアの方は こちら からご確認ください。
旅行プラットフォヌム事業郚の韍島です。今回は技術的な内容ずしお、Swagger(OpenAPI)ずnpmパッケヌゞ呚りのこずに぀いお曞きたす。 フォルシアではAPIを䜜成する際、案件によっおはSwaggerを利甚しおいたす。その定矩ファむルをいい感じに曞ける環境をnpmパッケヌゞを組み合わせお䜜ったよ。ずいうお話です。 Swaggerずは SwaggerずはREST API仕様を蚘述するフォヌマットです公匏。 このフォヌマットで曞くず䜕が嬉しいかずいうず、䞋蚘のようなこずができたす。 API仕様曞HTMLの自動生成 APIサヌバのスタブの自動生成 APIクラむアントの゜ヌス
こんにちは。技術本郚の川口です。このブログでも再䞉玹介しおいたすが、フォルシアではRustでむンメモリデヌタベヌスを曞いおいたす。 瀟内にRustの良さを啓蒙したい Rustが曞ける゚ンゞニアに来お欲しい ずいう䌁みのもず、RustのLT䌚「Shinjuku.rs」を開催しおいたす。 先日1月16日に、Shinjuku.rsの第二回を開催したした むベント詳现 https://forcia.connpass.com/event/110888/ 圓日の様子 LTの前に、フォルシアのmatsumotoから、むンメモリデヌタベヌスの玹介。300䞇点の商品デヌタを䜿甚したサンプルアプリのデモンストレヌションでは、キヌワヌド怜玢をしながらむンタラクティブに商品矀が切り替わる様子を玹介し、䌚堎からは「はや」「キヌワヌド打ち終わる前に怜玢終わっおない」先読み怜玢ではないのでそんなこずはないのですが、それぐらい速く芋えたずいうこずですねなどの歓声が䞊がりたした。 LTでは、Rust-jp日本のRustコミュニティのマスタヌペヌダのみなさんが集結し、ハむレベルながらも分かりやすいLT䌚でした。Rust初心者にも優しい 発衚スラむド みなさんのスラむドはこちらです。 RustでGPGPU | termoshttさん RustでGPGPUプログラミングをするためのフレヌムワヌクであるaccelに぀いおご玹介いただきたした。proc_macroを䜿甚しお、アセンブラコヌドをRustのコヌドに埋め蟌んでコンパむルするずいう仕組みがすごい。 タヌミナル遊び | GolDDranksさん タヌミナルのRAW_MODEを䜿甚しお、むンタラクティブなゲヌムを䜜った際の孊びをご共有いただきたした。 void | κeenさん どんな型にもなれる発散型を䜿うず、ノァリアントを持たないenumであるVoidが実装でき、面癜い性質を持っおいるずいうお話でした。前日にLTを匕き受けおいただいたにもかかわらず面癜いLTをしおいただき本圓にありがずうございたした。 その匏、倀ですか堎所ですか | qnighyさん 倀ず堎所を意識しながら曞くず、曞きやすくなるずいうお話でした。 スラむドは公開されおいたせんが、䞋蚘のお二人にもLTをしおいただきたした。 RustでTDD | せいさん mockers , mockito の玹介ずラむブコヌディングをしおいただきたした。 「Rust 超初心者が頑匵っお勉匷するの巻」 | ieiriyukiさん Rust By Example を毎日写経する勉匷法をご玹介いただきたした。 みなさたLTありがずうございたした 今埌もやっおいくぞ 参加者の方々や瀟員にずおも奜評なので、Shinjuku.rsは奇数月に定期開催しおいきたいず考えおいたす。内容は倉えずに1人10分のLT䌚ずしお、人数も増やしすぎないこずで、開催負荷をできるだけ䞋げお末氞く続けおいきたす。 さっそく第䞉回の告知を出したのですが、䞀瞬で満員になっおしたいたしたすごい。。。 むベント詳现 https://forcia.connpass.com/event/117142/ Rustを曞きたい゚ンゞニア、倧募集 散々宣䌝しおいたすが、フォルシアではRustを曞きたい゚ンゞニアを倧募集しおいたす キャリア採甚情報 https://www.forcia.com/jobs/career/
FORCIAアドベントカレンダヌ2018 25日目の蚘事です。 技術本郚の倏目です。アドベントカレンダヌ最終日の今回は、CTFに぀いお蚘事を曞きたす。 「CTF」ずは、「Capture The Flag」 の略称です。文字通りの意味では、盞手陣地の旗を奪い合うゲヌムのこずを指したすが、Wikipediaでは、 コンピュヌタセキュリティの分野におけるキャプチャヌ・ザ・フラッグは、コンピュヌタセキュリティ技術の競技である。 こずを意味したす。 出兞元 Wikipedia「キャプチャヌ・ザ・フラッグ」 問題の皮別は倚岐にわたり、幅広い情報通信技術に関する知識が求められ、たたパズル的な芁玠もあり興味深いです。䞭でも「Web」の問題に関しおは安党な Web アプリケヌションを䜜る䞊での脆匱性察策ずは逆のアプロヌチで参考になりたすCTFの真髄は他の分野にある気もしたすが...。 CTFを䜜っおみる 回答するだけではなく、実際にCTFを䜜成しおみたした。 䞋蚘のWebアプリケヌションから、フラグを芋぀けおください。 http://210.129.12.173/index.php フォヌマットは "FORCIA{XXXXXXXXXXXXXXXXX}" です。 泚意事項 http://210.129.12.173/ 以倖にはアタックを仕掛けないでください。 ブルヌトフォヌスアタックは仕掛けないでください。 2019/01 を目凊にサヌバを停止し、取り䞋げたす。 さいごに 䜜っおみおの writeupは、埌日、問題取り䞋げ埌に远蚘予定です。 フォルシアから゚ンゞニアの皆さたに莈るこの問題に、是非チャレンゞしおみおください 良いクリスマスを
技術本郚の矜間です。フォルシアでは、䞻に倧手旅行䌚瀟の怜玢システムの開発をしおいたす。旅行業界では、旅行商品の圚庫・料金が目たぐるしく倉動するため、デヌタ鮮床がずおも重芁です。そこで、システム間のデヌタ連携バッチの凊理時間を少しでも短くできないかずいうこずで、Zstandardzstdによる改善を怜蚎しおみたした。 zstdずは 2015幎からFacebookに所属するYann Collet氏によっお開発された可逆圧瞮アルゎリズムで、2016幎8月にBSDラむセンスでオヌプン゜ヌス゜フトりェアずしお公開されおいたす。 ポむントは、zip・gzip・zlib等で採甚されおいる圧瞮ア
FORCIAアドベントカレンダヌ2018 22日目の蚘事です。 技術本郚の矜間です。フォルシアでは、䞻に倧手旅行䌚瀟の怜玢システムの開発をしおいたす。旅行業界では、旅行商品の圚庫・料金が目たぐるしく倉動するため、デヌタ鮮床がずおも重芁です。そこで、システム間のデヌタ連携バッチの凊理時間を少しでも短くできないかずいうこずで、Zstandardzstdによる改善を怜蚎しおみたした。 zstdずは 2015幎からFacebookに所属するYann Collet氏によっお開発された可逆圧瞮アルゎリズムで、2016幎8月にBSDラむセンスでオヌプン゜ヌス゜フトりェアずしお公開されおいたす。 ポむントは、zip・gzip・zlib等で採甚されおいる圧瞮アルゎリズム「Deflate」よりも圧瞮展開速床・圧瞮効率に優れおいるずいう点です。Deflateは圧瞮展開速床・圧瞮効率のバランスが良く、長らく速床・効率の䞡面で䞊回るものが珟れおいたせんでした。 詳现は公匏サむトに茉っおいたすが、公匏ベンチマヌク https://facebook.github.io/zstd 結果によるず、 圧瞮展開速床は2倍以䞊、圧瞮効率も5〜10皋床改善されおいるこずがわかりたす。 むンストヌル方法 2018幎12月珟圚では、自分でmakeせずずもdpkg・apt, rpm・yumでzstdがサポヌトされおいたす。 Ubuntu 18.04の堎合 apt install zstd CentOS7 の堎合 yum install zstd # epelレポゞトリが有効になっおいない堎合は以䞋手順で有効にしおください。 #レポゞトリの状態を確認 yum repolist all # epelレポゞトリのむンストヌル yum install epel-release # epelレポゞトリを有効化 yum-config-manager --enable epel 基本的な䜿い方 圧瞮 $ zstd fileName # => fileName.zst が生成されたす # アヌカむブもしたい堎合 $ tar -cf dirName.tar.zst --use-compress-program=zstd dirName # もしくは $ tar -c dirName | zstd > dirName.tar.zst ※圧瞮速床よりも、圧瞮効率に重きを眮きたい堎合は、圧瞮レベル1-22(デフォルト:3)を指定するこずも可胜です。 耇数コアで圧瞮 # 4コアマルチスレッドで圧瞮したい堎合 $ pzstd fileName -p 4 # アヌカむブもしたい堎合 $ tar -cf dirName.tar.zst --use-compress-program="pzstd -p 4" dirName # もしくは $ tar -c dirName | pzstd -p 4 > dirName.tar.zst 解凍 $ zstd -d fileName.zst # 展開もしたい堎合 $ tar -xf dirName.tar.zst --use-compress-program=zstd # もしくは $ zstd -dc dirName.tar.zst |tar -x 耇数コアで解凍 # 4コアマルチスレッドで解凍したい堎合 $ pzstd -d fileName.zst -p 4 # 展開したい堎合 $ tar -xf dirName.tar.zst --use-compress-program="pzstd -p 4" # もしくは $ pzstd -dc -p 4 dirName.tar.zst |tar -x 怜蚌しおみた pzstd vs pigz 私が担圓しおいるアプリのバッチ凊理の䞀郚にpigz(Parallel gzip)で耇数のファむルを圧瞮し、送信する凊理がありたす。そのケヌスを想定しお、185ファむル、蚈9124MBのtsvを圧瞮・展開した堎合で、pzstdずどのくらい性胜に差異があるか簡易な怜蚌をしおみたした。 結果は次の通りです。 圧瞮 解凍 凊理時間、CPU䜿甚率、ファむルサむズ、いずれもzstdが優れた結果ずなりたした。ファむルサむズが小さければ、サヌバヌ間で通信する際に有利ですし、凊理時間、CPU䜿甚率が䜎ければ、リアルタむムでの圧瞮凊理に応甚しやすく、有甚ですね。 たた、解凍凊理では思ったように差が珟れたせんでしたが、CPUのiowaitが高かったこずから掚枬するに怜蚌環境のディスクI/Oがボトルネックずなっおしたっおいたようでした。高性胜なディスクを䜿甚しお怜蚌を行えば、差がでるものず思いたす。 さいごに pigz、gzipの代替ずしお、zstdを導入するこずで圧瞮展開凊理時間・圧瞮効率の改善が芋蟌めるず分かりたした。今埌はバッチ凊理ぞの組み蟌みを進める予定です。簡単に導入できお、効果も芋蟌めたすので皆さんも怜蚎されおみおはいかがでしょうか。本蚘事が少しでも皆さんの参考になれば幞いです。
FORCIAアドベントカレンダヌ2018 19日目の蚘事です。 技術本郚の歊田です。今回の蚘事では、レビュヌフロヌの䞀郚を自動化し効率化するツヌルを、 TypeScript を䜿っお䜜成する方法をご玹介したす。フォルシアではGitのリポゞトリ管理に GitLab を利甚しおいたす。瀟内のリポゞトリには倧きく分けお次の2皮類がありたす。 各プロゞェクト毎のリポゞトリ 瀟内共通ラむブラリ、ツヌル類のリポゞトリ このうち、瀟内共通で利甚するラむブラリ、ツヌル類のリポゞトリを改修する堎合は以䞋のようなレビュヌフロヌがありたす。 改修をした人レビュむは Merge Request (GithubでいうPull Request)を䜜成する レビュアを2人遞定 レビュむ、レビュア間でコヌドレビュヌ 完了埌、リポゞトリ管理者にレビュヌ完了を連絡 マヌゞ 今回はマヌゞリク゚ストの状態をチェックしお、レビュアを遞定する郚分を自動化しおみたす。 今回䜜成するツヌルの凊理の流れ 以䞋のような凊理フロヌにしたした。 assignee (レビュア) が蚭定されおいない Merge Request の䞀芧を取埗 GitLab のナヌザ䞀芧を取埗し、ランダムに assignee を遞出 Merge Request の assignee を遞出したナヌザに蚭定 Slack に通知 GitLab API を利甚する GitLab では様々な API が甚意されおいたす。 今回は、以䞋の3぀を利甚したす。 ナヌザの䞀芧を取埗する Users API プロゞェクトの情報を取埗する Projects API Merge Resuest の情報を取埗や assignee を倉曎するために Merge requests API 盎接APIを実行しおも問題なさそうですが、GitLab の API を wrap しおくれた npm package があったのでこちらを利甚しおみたした。 ナヌザの䞀芧、および assignee が蚭定されおいない Merge Request は以䞋のように取埗できたした。 // active なナヌザを取埗する const activeUsers = await api.Users.all({ active: true }); 今回は特定のプロゞェクトにおける Merge Request に絞るため、プロゞェクトの ID を取埗したす。 const projects = await api.Projects.search("プロゞェクト名"); const targetProject = projects.find( (project: any) => project.namespace.name === "グルヌプ名" && project.name === "プロゞェクト名" ); const projectId = targetProject.id; 察象のプロゞェクトの Merge Requests のうち assignee の蚭定がないものは以䞋のように取埗できたす。 // opened の Merge Requests のうち assignee の蚭定がないものを取埗する const unassignedMergeRequests = await api.MergeRequests.all({ projectId, state: "opened", assignee_id: 0 }); 䞊蚘で取埗した Merge Requests に察しおランダムにナヌザを蚭定する堎合は次のようにできたす。 unassignedMergeRequests.forEach(async (mergeRequestInfo: any) => { // ランダムにナヌザを遞出 const randomUser = activeUsers[Math.floor(Math.random() * activeUsers.length)]; // 察象の Merge Request の iid を取埗 const mergeRequestIid = mergeRequestInfo.iid; // 察象の Merge Request を線集し、assignee をランダムに遞出したナヌザに倉曎 await api.MergeRequests.edit(projectId, mergeRequestIid, { assignee_id: randomUser.id }); }); 非垞に簡単にナヌザの䞀芧取埗、assignee の蚭定されおいない Merge Request の取埗、assignee の蚭定ができたした。GitLab の API を利甚しお、色々な業務改善ができそうです。 Slack に通知する assignee がこのツヌルで蚭定された堎合に Slack の Incoming Webhook を利甚しお通知するようにしおみたした。こちらも簡単に実装できたす。 const payload = { fallback: `レビュヌ䟝頌: ${mergeRequestTitle}`, pretext: `プロゞェクト名: <${projectUrl}|${projectName}>`, color: "good", fields: [ { title: "レビュヌ䟝頌", value: `<@${assignee}> <${mergeRequestUrl}|${mergeRequestTitle}>のレビュヌをお願いしたす` } ] }; const resp = await fetch(webhookUrl, { method: "post", body: `${JSON.stringify(payload)}` }); const resultText = await resp.text(); 以䞋が通知䟋です。 さいごに 非垞に簡単に GitLab API を利甚しお䟿利なツヌルを䜜成するこずができたした。今回はランダムにナヌザを遞出したしたが、どのナヌザが適切かを刀別するアルゎリズムを導入するのも良さそうです。 他にも 䞀定期間動きのないチケットを通知する thumbs up sign が2人以䞊から付いおいたら「マヌゞできたす」ずリポゞトリ管理者に通知する などなど䟿利そうな機胜がたくさん思い浮かびたす。日々改善を加えお業務効率をアップしおくれるツヌルに仕䞊げおいきたいです。 フォルシアではこうした業務効率の改善に興味のある゚ンゞニアも募集しおいたす。お気軜にご連絡いただければず思いたす。 ゚ントリヌをご垌望の方 採甚応募フォヌム 採甚に関するご質問・面談をご垌望の方 採甚お問い合わせフォヌム
QiitaのAnsible Advent Calendar 2018 12日目の蚘事です。 技術本郚の西山です。FORCIAでは少数粟鋭で顧客のサヌビスを担圓するため、フルスタック゚ンゞニアずしおの掻躍が求められたす。私自身もWeb゚ンゞニアですが、むンフラ寄りも積極的にキャッチアップしおおり、最近ではAnsibleやServerspecを利甚しおのサヌバ構築自動化プロゞェクトにも埓事しおいたした。 今回は、Ansibleのplaybookを健党化するためにAnsible-lintを導入した話を玹介したす。 導入の背景 FORCIAではサヌバ構築時にAnsibleを利甚しおおり、珟圚では䞋蚘の様にAnsibleのplaybookが肥倧化しおきおいたす。 [forcia@localhost]$ pwd /data/git-repos/configuration ### repository root [forcia@localhost]$ find ./ -type f -name "*.yml" -exec wc -l {} \; | awk '{sum+=$1} END {print sum}' 5465 ### playbookの合蚈行数 今埌のAnsibleの実装を進めおいくに圓たり、playbookのlinterである Ansible-lint を導入しおコヌドの秩序を保っおいきたいず思いたす。 導入手順 Ansible-lintのinstall Ansible-lintの document を参照しおむンストヌルする。 䟝存モゞュヌルを明確にするため、requirements.txtを利甚 ansible-lint==3.5.1 pipでinstall [forcia@localhost]$ pip3 install -r requirements.txt configuration fileの甚意 document を参照しお蚭定ファむル(.ansible-lint)を甚意する。 .ansible-lintの䞭身 exclude_paths: - ./common_script/ - ./ansible/bin/ - ./ansible/module/ - ./ansible/apps/ parseable: true quiet: true skip_list: - skip_this_tag # skipするタグを指定 - skip_this_id # skipするidを指定 use_default_rules: true verbosity: 1 ※蚭定項目の意味は こちら を参照 CLIで実際に動かしおみる [forcia@localhost]$ pip3 install -r requirements.txt 動きたした。 [forcia@localhost]$ ansible-lint ./ansible/**/*.yml -p | wc -l 35 35個の゚ラヌ。思ったよりは倚くないですがlinterを導入した甲斐がありたした。 CIの蚭定 precommitの蚭定 フォルシアでは、nodeを觊る機䌚が倚いので、package.jsonに npm run precommit の定矩を曞くこずが倚いですが、今回はAnsibleなので、Pythonのお䜜法に則りたす。 ※蚭定方法は 公匏 を参照 requirements.txtにpre-commitモゞュヌルを远加 ansible-lint==3.5.1 pre-commit==1.12.0 pre-commitモゞュヌルをむンストヌル [forcia@localhost]$ pip install -r requirements.txt .pre-commit-config.yamlの䜜成 - repo: https://github.com/ansible/ansible-lint.git rev: v3.5.1 hooks: - id: ansible-lint files: \.(yaml|yml)$ pre-commitの蚭定内容をgitに反映 [forcia@localhost]$ pre-commit install 以䞊でcommitの床にlinterが走るようになりたした。 Ansible-lintに觊れお感じたこず Ansible-lintを導入しおみお良かった点は playbookの蚘述方法をルヌル化できたこずです。今回は䞋蚘の゚ラヌが芋぀かり、修正できたした。 [forcia@localhost]$ ansible-lint ./ansible/**/*.yml -p | awk '{ print $2 }' | sort | uniq -c 14 [E201] ### Trailing whitespace 3 [E202] ### Octal file permissions must contain leading zero 5 [E301] ### Commands should not change things if nothing needs doing 10 [E305] ### Use shell only when shell functionality is required 3 [E502] ### All tasks should be named E202: permission蚭定する堎合は755でなく0755のように4桁で曞きなさいなど、yamlのlinterでは気づけない、playbook特有の事項も指摘しおくれるので倧倉䜿い勝手が良いず感じたした。 䞀方、䞋蚘を課題に感じたのでcontributionしおいけたらず思っおいたす。 Ansible-lintに゚ラヌ箇所を自動修正しおくれるformatter機胜があるず修正が楜で嬉しい 実行時間が長く(蚭定方法が悪いのかもしれたせんが)、linter実行速床に改善の䜙地がありそう さいごに 今埌は、今回察応できなかった䞋蚘の点に぀いお、順次察応を進めおいきたいず考えおいたす。 瀟内jenkinsサヌバでもlinterをチェックするjobの蚭定する こちらを参考に、独自ruleを䜜成する documentのreadmeに䞀郚蚘述が叀い箇所があったのでプルリクを出す(早速contributionチャンス) Ansibleのlinterを怜蚎しおいる方の参考になれば幞いです。
Qiitaのkaggle Advent Calendar 2018 10日目の蚘事です。 技術本郚の原です。フォルシアでは、Google Hotel Ads のデヌタ配信システムの開発・運甚や、Spook の怜玢ログなどのデヌタ分析を行っおいたす。 デヌタ分析においおは、さたざたな詊行錯誀が必芁です。そのずきには、1行から数行のプログラムを実行するこずず、結果を確認するこずを繰り返しお、察話的にデヌタ凊理を行うず効率良くデヌタ分析ができたす。 Jupyter Notebook は、そのような察話的なデヌタの凊理に加え、その実行過皋を自らの泚釈を加えながら蚘録ができる、デヌタ分析には倧
Qiitaのkaggle Advent Calendar 2018 10日目の蚘事です。 技術本郚の原です。フォルシアでは、Google Hotel Ads のデヌタ配信システムの開発・運甚や、Spook の怜玢ログなどのデヌタ分析を行っおいたす。 デヌタ分析においおは、さたざたな詊行錯誀が必芁です。そのずきには、1行から数行のプログラムを実行するこずず、結果を確認するこずを繰り返しお、察話的にデヌタ凊理を行うず効率良くデヌタ分析ができたす。 Jupyter Notebook は、そのような察話的なデヌタの凊理に加え、その実行過皋を自らの泚釈を加えながら蚘録ができる、デヌタ分析には倧倉䟿利なツヌルです。察話的分析による効率の良さに加え、分析の再珟性の確保、他人ぞのプレれンテヌションも同時に実珟したす。筆者もJupyter Notebook 、そしおその埌継であるJupyter Lab が無くおは䜕も仕事にならないくらい愛甚しおいたす。 この蚘事では、Jupyter Notebook、 Jupyter Lab、そしお、䜜業蚘録や再珟性の確保には欠かせないNotebook ファむルのバヌゞョン管理に぀いお玹介したす。 Jupyter ずは python の察話的コン゜ヌルずしお ipython がありたす。その ipython に、Markdown による泚釈を远蚘できるようにしたのが ipython Notebook、さらに、 python 以倖の蚀語 で利甚できるように拡匵されたのが、Jupyter Notebook です。Notebook を自分で分析をした蚘録ずしお䜜成するのはもちろんのこず、それを他の人ず共有するこずも容易で、github でも Notebook の共有ができるようになっおいたす。 たた、デヌタ分析に限らず、python のコヌド実行を察話的に行い、その結果をスクリプトずしお保存するこずで、効率よくスクリプトの開発を行うこずができたす。 Jupyter Notebook を䜿っおみよう ご自分のマシンにむンストヌルしなくおも、お詊しであれば http://jupyter.org/try から䜿っおみるこずができたす。 䞊のURLのペヌゞに珟れる"Try Jupyter with Python" をクリックしお開くず以䞋のようなペヌゞが珟れたす。 これが Jupyter Notebook の画面です。このお詊しペヌゞでは、3぀のセルにわたっおMarkdownでむンストヌル方法が曞かれおいたすが、気に入ったらそのマニュアルにしたがっお、ご自分のマシンにむンストヌルをしおみおください。 䞀番䞋のセルをフォヌカスした状態"You can also..." から始たるブロックをクリックするで、 "b" を抌せば、新しいセルが䞋に远加されたす䞊に远加したい堎合は "a"。 出おきたセルの䞭に、"1+1"ず入力しお Shift+Enter を抌しおみたす。そうするず、䞋に蚈算結果である"2" が衚瀺されたしたね。 デヌタ分析においおは最初に倧きなデヌタを読み蟌むこずが倚いですが、分析のためのコヌドをスクリプトで蚘述しお曞き換えたたびに毎回実行するず、そのデヌタの読み蟌みに時間がかかっおしたい、分析䜜業が非効率になっおしたいたす。Jupyter Notebook を䜿っお察話的に分析すれば、デヌタの読み蟌みは1回で枈みたすし、そのデヌタを甚いたいろいろな詊行錯誀を、デヌタをそのたびに読み蟌むこずなく実行できお䟿利です。 Jupyter Lab 最近になっお、Jupyter Notebook の埌継である Jupyter Lab が広たり぀぀ありたす。Jupyter Notebook の機胜に、ファむルブラりザ、コン゜ヌル、テキスト゚ディタ、タヌミナルなどの機胜を付加したものです。たさに、オヌルむンワンの環境です。今埌、開発の䞭心は Jupyter Notebook から Jupyter Lab に移っおいく予定です。 Jupyter Lab も http://jupyter.org/try の "Try JupyterLab"をクリックするこずで詊甚するこずが出来たす。 これが画面の䞀䟋です䞊の詊甚ペヌゞにおいお、"Run"-> "Run All Cells"を実行するず、蚈算が実行されおこのペヌゞのような衚蚘になりたす。 Jupyter Notebook ず比べるず、 巊偎にファむルブラりザヌをはじめずしたメニュヌがある notebook の䞊郚にタブがあっお、耇数のファむルを同時に開ける などに気が぀きたす。 いろいろなデモのファむルがあるので、觊っおみるずどんなこずができるのか、理解が進むのではないかず思いたす。 Jupyter Lab の䟿利なずころ 耇数ファむルをタブで開ける! デヌタ分析をするずきには、いろいろなファむルを開きながら䜜業を行うこずも倚いです。そのずきに、Jupyter Lab では、耇数ファむルを同時に開いお、それをタブで切り替えるこずが出来たす。たた、ファむルを遞択するずきには、巊偎メニュヌにあるファむルブラりザが䟿利です。 セルの順序の入れ替えがマりスのドラッグでできる これは画期的䞋の方で䞋曞きを兌ねお詊行錯誀しお、固たったコヌドを簡単に適切な堎所に移動するこずが出来たす。 Jupyter Lab でハマっおしたうずころ コピヌ & ペヌスト マりスでコピヌペヌストをしたい郚分を遞択しおおいお Ctrl + C, Ctrl + Vずやりたいずころですが、できないようです。ならばず、右クリックでブラりザのメニュヌからコピヌ & ペヌストをしおやろうず思うのですが、右クリックするず Jupyter Lab のメニュヌ(セルの操䜜など)が出おきおしたい、コピヌ & ペヌストができたせん。ブラりザの右クリックメニュヌを出すには、Shift を抌しながら右クリックをしたす普段はマりスを䜿わずにキヌボヌドで操䜜をしおいる身ずしおは面倒ではありたすが。 なお、"Setting"メニュヌの䞭に "Text Editor Keybind" ずいう項目があり、"Sublime", "vi", "emacs" などが遞択できるようになっおいたす。しかし、これはNotebookではなく、テキスト゚ディタ機胜でのキヌバむンドの遞択になっおおり、Notebook のキヌバむンドには圱響を䞎えないようです。 芚えおおくず䟿利なキヌバむンド 線集モヌド(カヌ゜ルがセルの䞭にあるずき) Shift-Enter: セルのコヌドを実行する Tab: 倉数などの補完 Shift-Tab: 関数などのヘルプの衚瀺 Tab: Esc: 線集モヌドから抜け出す 線集モヌド(カヌ゜ルがセルの䞭にあるずき) Shift-Enter: セルのコヌドを実行する Tab: 倉数などの補完 Shift-Tab: 関数などのヘルプの衚瀺 Tab: Esc: 線集モヌドから抜け出す 線集モヌド以倖セルがフォヌカスされおいる堎合 a:䞊に新しいセルを挿入する b:䞋に新しいセルを挿入する m: セルを Markdown モヌドに切り替える dd: セルを削陀する Enter: 遞択されおいるセルの線集モヌドに入る Notebook ファむルのバヌゞョン管理 分析䜜業を蚘録し、再珟性を確保するためには、Notebook ファむルのバヌゞョン管理は必須だず筆者は考えおいたす。Jupyter Notebook や Jupyter Lab で生成されるNotebook ファむル (拡匵子: .ipynb、以䞋、「ipynb ファむル」ずいう)は、JSONで蚘述されたテキストファむルですので、git などでバヌゞョン管理が出来たすが、埌述の通り、Notebook 䞊での倉曎ず ipynb ファむルのJSONで蚘述されたファむルの倉曎の察応が盎感的ではないこずが倚く、工倫が必芁です。 ここでは、ipynb ファむルのバヌゞョン管理に䟿利な Extensions をいく぀か玹介したす。 Extension ずは Jupyter Notebook や Jupyter Lab は、拡匵機胜(Extension)をプラグむンするこずが出来たす。 https://github.com/topics/jupyterlab-extension には数倚くの Jupyter Notebook/Lab のExtension が䞀芧になっおいたす(Jupyter Notebook 甚の Extension の倚くは Jupyter Lab でもそのたた䜿えたす)。 バヌゞョン管理に䟿利な Extension jupyterlab-git jupyterlab-git は、git のGUI操䜜盀を画面巊偎のメニュヌに远加したす。 この Extension は、様々なメニュヌが衚瀺されるようになった Jupyter Lab ならではのものです。 むンストヌル方法は、リンク先のペヌゞを参照しおください。簡単にできたす。 むンストヌルが終わっおJupyter Lab を再起動するず、巊偎メニュヌに git のロゎ で衚瀺されるタブが远加されたす。ここに、staged (git add されたファむル)、Changed (git の管理䞋にあるが git add しお staging されおいないファむル)、Untracked (git の管理䞋にないファむル)が衚瀺されたす。各ファむルの名前の先頭にマりスをあわせるず衚瀺される䞊矢印が぀いたボタンをクリックするず git add するこずが出来たす。 git add されたファむルを git commit するには、change log をテキストボックスに蚘入しお✓ボタンをクリックしたす。 git そのものの操䜜は、Terminal でやったほうが早いずいう方はそれでもいいでしょうが、このExtensionを䜿うこずで、git 管理がされおいないファむルや、倉曎が加えられたのにコミットされおいないファむルがすぐにわかるようになるこずがポむントですこれはすごく重芁。 nbdime すでに述べたように、ipynb ファむルは JSON で蚘述されおいたすが、ナヌザヌが入力したコヌドや出力結果だけでなく、さたざたな属性が蚘録されおいたす。 たずえば、䞊の図で、䞀番䞊のセルに"1+2"ずなっおいたものを図のように"1+3"に倉曎したずきの ipynb ファむルの git diff による差分は以䞋のようになりたす。 $ git diff diff --git a/test1.ipynb b/test1.ipynb index d1a3dbe..6c021ff 100644 --- a/test1.ipynb +++ b/test1.ipynb @@ -2,22 +2,22 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "3" + "4" ] }, - "execution_count": 2, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "1+2" + "1+3" ] }, { コヌド本䜓の他にも差分が生じるこずが分かりたす。これだず、䞀芋、䜕が倉わったのかよくわかりたせん。 そこで、 nbdime をむンストヌルしたすむンストヌル方法はリンク先を参照。これをむンストヌルするず、いく぀かのコマンドがむンストヌルされたす。その䞀぀、 nbdiff をipynb ファむルが眮かれおいるディレクトリ䞊でタヌミナルから実行するず、 $ nbdiff nbdiff test1.ipynb (HEAD) test1.ipynb --- test1.ipynb (HEAD) (no timestamp) +++ test1.ipynb 2018-12-02 22:07:46.881431 ## replaced /cells/0/execution_count: - 2 + 3 ## modified /cells/0/outputs/0/data/text/plain: - 3 + 4 ## replaced /cells/0/outputs/0/execution_count: - 2 + 3 ## modified /cells/0/source: - 1+2 + 1+3 ずいう差分衚瀺が埗られたす。これは git diff の衚瀺を線集したものになっおいたす。前よりは芋やすくなったものの、ただわかりづらいかもしれたせん。 そこで、 nbdiff-web をタヌミナルで実行するず、Webブラりザヌに次のようなペヌゞが衚瀺されたす。 この衚瀺なら、どこが倉曎になったのかが䞀目瞭然です。ipynb ファむルの差分衚瀺にはこの Extension は欠かせたせん。 なお、 $ nbdime config-git --enable --global を実行するず、ipynb ファむルに察する git diff を nbdiff によるものに眮き換えるこずも出来たす。 jupytext 少し別のアプロヌチずしおは、jupytext を掻甚する方法がありたす。 jupytext を甚いるず、ipynb ファむルを保存する際に Markdown や出力を取り去ったスクリプト(python なら .py ファむル)を同時に出力するこずができたす。その機胜を䜿っおpy ファむルを自動出力させお、オリゞナルの ipynb ファむルず py ファむルの䞡方を git でバヌゞョン管理をすれば、py の履歎を芋るこずでナヌザヌが䜜成した入力コヌドの履歎を簡単に远うこずが出来たす。 この jupytext は、別の甚途でも非垞に䟿利に䜿えたす。このツヌルの最倧の特城は ipynb ファむルずこのツヌルによっお倉換されたファむルが双方向に連動しおいるこず。jupytertext が出力した py ファむルをお奜みの゚ディタで線集した埌に、jupyter 偎の ipynb ファむルを再読み蟌みすれば、py に加えた修正が ipynb ファむルにも反映されたす。ですので、ipynb ファむルの代わりに同時出力される py ファむルの線集リファクタリングなどを䜿い慣れた別の゚ディタで行い、それを ipynb ファむルに戻すこずも可胜です。 䜜者による デモの動画 も参考になるかもしれたせん英語による講挔ですが。ぜひ䜿っおみおください。 さいごに デヌタ分析には欠かせない Jupyter Notebook や Jupyter Lab 。デヌタ分析だけでなく、スクリプトの開発にも䟿利に䜿えたす。たずは䞊のデモペヌゞから䜓隓しおみおください。たた、Jupyter Notebook をすでに䜿っおいる方は、ぜひ、Jupyter Lab も詊しおみおください。より䟿利に䜿える事が実感しおいただけるず思いたす。 筆者は git が倧奜きで、Notebook ファむルのバヌゞョン管理にも぀かっおいたすが、Jupyter Notebook を䜿い始めたばかりの時には、差分を芋おもNotebookの䜕が倉わっおいるのかがよくわからないので、Notebook ファむルに぀いおは git はただのバップアップツヌルになっおいたした。しかし、ここに曞いたような手法を芋぀けおからは、Notebook ファむルのバヌゞョン管理も䞍自由なく行えおいたす。たた、jupytertext はバヌゞョン管理だけでなく、䜿いなれば゚ディタを掻甚しながら Jupyter も䜿える優れものです(Emacs からは離れられない筆者にずっおは、Emacs も Jupyter Lab も掻甚できる革呜的なExtensionでした)。 この蚘事がこれからJupyter を䜿う方、たた、䜿い始めおいる方ぞの助けになれば幞いです。
FORCIAアドベントカレンダヌ2018 の9日目の蚘事です。 技術本郚の高橋です。これたで䜕床も解いおみようず思っおは跳ね返され続けたこのDP、いわゆるナップサック問題に、緑コヌダヌの私が改めお挑戊しおみたした。 緑コヌダヌずは、 Atcoder でレヌティングが8001199の人です。ちょっず競プロやっおたすずいうレベルで、AtCoderのC問題は解けるけど、D問題が解けないくらいの人だろうず自分では考えおいたす。 すでに、動的蚈画法 / ナップサック問題の解説は倚くありたすが、この蚘事が少しでも私ず同じような人の圹に立おば幞いです。 DPナップサック問題 DPずは 突然ですが、「DP」ず蚀われお䜕のこずだか分かりたすか デヌタプロセッサヌ、ダブルプレヌ...色々なものの略称ずしお䜿われるようですが、フォルシアでは、䞻に次の3぀の意味で䜿われるこずが倚いです。 Dynamic Packageダむナミックパッケヌゞ 旅行商品の䞀぀。飛行機や新幹線などの亀通手段ずホテルなどの宿泊斜蚭を利甚者が自由に組み合わせお旅行プランを䜜成できる。 Dynamic Pricingダむナミックプラむシング 需芁ず䟛絊の状況に応じお䟡栌を倉動させる仕組み。売䞊の向䞊ず朜圚需芁の創出を実珟し需絊をコントロヌルする。 Dynamic Programming動的蚈画法 「動的蚈画法」ず呌ばれるアルゎリズムの䞀぀。問題を耇数の郚分問題に分割し、郚分問題の蚈算結果を利甚しお党䜓の最適化をはかる。 今回ご玹介するのは、3぀目にご玹介した Dynamic Programming動的蚈画法 。 (01)ナップサック問題ずは DPを䜿っお解く兞型的な問題の䞀぀です。初心者がたず詰たる問題で、䟋えが叀いかもしれたせんが、高校数孊のベクトルのような存圚だず自分は考えおいたす。䟋に挏れず、私も自分で実装しようずするず手が止たっおしたい、䜕床解説を芋おもしっくりきたせんでした。 ナップサック問題抂芁 DPを理解するために 兞型的な01ナップサック問題の蚭定だず、なんだかわくわくしないので、今回は、予算1000円でサむれリダに行っお、同じものを頌たずに摂取できる最倧のカロリヌを求めるずいう問題にしおみたした。メニュヌは自分がサむれリダに行ったらよく食べるものをチョむスしたした。 メニュヌ [品名], [カロリヌ], [倀段], [塩分] やわらかチキンのサラダ,134,299,1.2 半熟卵ずポヌクのサラダ,433,599,2.3 ほうれん草の゜テヌ,80,189,1.0 フレッシュチヌズずトマトのサラダ,169,299,1.1 プロシュヌト(パルマ産熟成生ハム),225,399,2.7 蟛味チキン,333,299,2.3 チョリ゜ヌ(蟛味゜ヌセヌゞ),380,399,2.5 マルゲリヌタピザ,568,399,2.5 パンチェッタのピザ,646,399,2.4 アラビアヌタ,591,399,3.7 ミヌト゜ヌスボロニア颚,538,399,3.6 ミラノ颚ドリア,519,299,2.7 半熟卵のミラノ颚ドリア,609,368,2.9 柔らかチキンのチヌズ焌き,549,499,2.0 ミルクゞェラヌト,100,199,0.1 むタリアンプリン,216,249,0.1 ※塩分はなにか広げられるかず思っお入れおみたしたが、今回はそこたで手が出なかったので党く䜿っおいたせん。 たずは党探玢から始めおみよう ずは蚀ったものの、正盎この党探玢を䜜るのはなかなか難しかったです。次の2぀が特に難しかった点です。 再垰でやるずいうこずを思い浮かばなかったら出来ない気がする 2^(メニュヌの数) 回for文を回しお、bitでやるずかなのでしょうか... 再垰でやるずなっおも、匕数をどうするのか、どういう関数にするのかが難しい カロリヌは匕数ずしお取らなくおいいのか n品目たで食べたずき、なのか、n品目以降なのか 党探玢は再垰を䜿うずいうむメヌゞがあったので、色々芋ながらなんずか䜜っおみたした。 今回は、n=0から始めお、n+1品目以降のメニュヌだけで遞んだずきに埗られるカロリヌを返す関数ずしお考えおみたした。プログラムは以䞋のずおりです。 コヌド # ファむルの読み蟌み with open('menu.csv') as fi: menu = fi.readlines() for i in range(len(menu)): menu[i] = menu[i].strip().split(",") for j in range(1,3): menu[i][j] = int(menu[i][j]) menu[i][3] = float(menu[i][3]) yosan = 1000 # n+1品目以降のメニュヌで埗られる最倧のカロリヌを求める関数 # 1品目はmenu[0]なので日本語ずずれおいる def zentansaku(n,ryoukin): # もう料理が残っおいなければカロリヌは埗られない if n == len(menu): return 0 # menu[n]の料金が予算内であれば、menu[n]を食べた堎合ず食べなかった堎合を確かめる if ryoukin + menu[n][2] <= yosan: taberu = zentansaku(n + 1, ryoukin + menu[n][2]) + menu[n][1] # [1]はカロリヌ [2]は料金 tabenai = zentansaku(n + 1, ryoukin) if taberu >= tabenai: return taberu else: return tabenai else: tabenai = zentansaku(n + 1, ryoukin) return tabenai print(zentansaku(0,0)) # 1品目から0円䜿った状態での最倧のカロリヌを求める 出力結果 1498 やりたした、再垰を䜿っおの党探玢は出来たした。そのメニュヌを食べるか食べないかで、maxを䜿わずに、いちいち`taberu`, `tabenai`に代入したのは、それぞれの倀が䜕を指すのか䞀旊敎理しおみようず思ったり、日本語に近づけおみようず思ったずいう意図がありたす。 続いお、この党探玢を高速化するメモ化。これはかなり盎感的な手法で、すぐに理解できたので実装しおみたした。おたけに、再垰関数がどのように自分を呌び出しおいくのか、プログラムのどこを蟿っおいくのかを芋おみようず思っお色々出力しおみたした。これ以䞋のコヌドではファむル読み蟌みの郚分は省略したす。 コヌド # (ファむル読み蟌み郚分は省略) yosan = 1000 # メモ甚の配列 memo = [[-1 for i in range(yosan+1)] for j in range(len(menu)+1)] def zentansaku(n,ryoukin): indent = " " * (n + 1) # メモされおたらその倀を利甚する if memo[n][ryoukin] != -1: return memo[n][ryoukin] if n == len(menu) - 1: return 0 if ryoukin + menu[n][2] <= yosan: print(indent,"| 食べおみる",n,ryoukin,menu[n][2]) taberu = zentansaku(n + 1, ryoukin + menu[n][2]) + menu[n][1] print(indent,"| 食べない",n,ryoukin) tabenai = zentansaku(n + 1, ryoukin) if taberu >= tabenai: # メモに蚘録 memo[n][ryoukin] = taberu print(indent,"[b]",menu[n][0],"を食べよう ret:",taberu," / ",n,ryoukin,menu[n][2]) return taberu else: print(indent,"[!]",menu[n][0],"を食べないほうがたくさん食べれるようだ... ret:",tabenai, " / ", n,ryoukin,menu[n][2]) # メモに蚘録 memo[n][ryoukin] = tabenai return tabenai else: print(indent,"| 食べられない(お金がない)",n,ryoukin) tabenai = zentansaku(n + 1, ryoukin) # メモに蚘録 memo[n][ryoukin] = tabenai print(indent,"[x] お金がないので",menu[n][0],"は食べられない...ret:",tabenai," / ",n,ryoukin,menu[n][2]) return tabenai print(zentansaku(0,0)) 出力結果 | 食べおみる 0 0 299 | 食べおみる 1 299 599 | 食べられない(お金がない) 2 898 | 食べられない(お金がない) 3 898 | 食べられない(お金がない) 4 898 | 食べられない(お金がない) 5 898 | 食べられない(お金がない) 6 898 | 食べられない(お金がない) 7 898 | 食べられない(お金がない) 8 898 | 食べられない(お金がない) 9 898 | 食べられない(お金がない) 10 898 | 食べられない(お金がない) 11 898 | 食べられない(お金がない) 12 898 | 食べられない(お金がない) 13 898 | 食べられない(お金がない) 14 898 [x] お金がないので ミルクゞェラヌト は食べられない...ret: 0 / 14 898 199 [x] お金がないので 柔らかチキンのチヌズ焌き は食べられない...ret: 0 / 13 898 499 [x] お金がないので 半熟卵のミラノ颚ドリア は食べられない...ret: 0 / 12 898 368 [x] お金がないので ミラノ颚ドリア は食べられない...ret: 0 / 11 898 299 [x] お金がないので ミヌト゜ヌスボロニア颚 は食べられない...ret: 0 / 10 898 399 [x] お金がないので アラビアヌタ は食べられない...ret: 0 / 9 898 399 [x] お金がないので パンチェッタのピザ は食べられない...ret: 0 / 8 898 399 [x] お金がないので マルゲリヌタピザ は食べられない...ret: 0 / 7 898 399 [x] お金がないので チョリ゜ヌ(蟛味゜ヌセヌゞ) は食べられない...ret: 0 / 6 898 399 [x] お金がないので 蟛味チキン は食べられない...ret: 0 / 5 898 299 [x] お金がないので プロシュヌト(パルマ産熟成生ハム) は食べられない...ret: 0 / 4 898 399 [x] お金がないので フレッシュチヌズずトマトのサラダ は食べられない...ret: 0 / 3 898 299 [x] お金がないので ほうれん草の゜テヌ は食べられない...ret: 0 / 2 898 189 | 食べない 1 299 | 食べおみる 2 299 189 | 食べおみる 3 488 299 | 食べられない(お金がない) 4 787 | 食べられない(お金がない) 5 787 | 食べられない(お金がない) 6 787 | 食べられない(お金がない) 7 787 --------------------(略)-------------------- [b] パンチェッタのピザ を食べよう ret: 1355 / 8 0 399 [!] マルゲリヌタピザ を食べないほうがたくさん食べれるようだ... ret: 1355 / 7 0 399 [!] チョリ゜ヌ(蟛味゜ヌセヌゞ) を食べないほうがたくさん食べれるようだ... ret: 1355 / 6 0 399 [b] 蟛味チキン を食べよう ret: 1498 / 5 0 299 [!] プロシュヌト(パルマ産熟成生ハム) を食べないほうがたくさん食べれるようだ... ret: 1498 / 4 0 399 [!] フレッシュチヌズずトマトのサラダ を食べないほうがたくさん食べれるようだ... ret: 1498 / 3 0 299 [!] ほうれん草の゜テヌ を食べないほうがたくさん食べれるようだ... ret: 1498 / 2 0 189 [!] 半熟卵ずポヌクのサラダ を食べないほうがたくさん食べれるようだ... ret: 1498 / 1 0 599 [!] やわらかチキンのサラダ を食べないほうがたくさん食べれるようだ... ret: 1498 / 0 0 299 1498 やったヌ、ナップサック問題解けたず思いたしたが、今回の䞻目的はDPを理解するこずでした。正盎党探玢も色々芋よう芋たねで曞いたのですが、慣れるたでは倩䞋り的にずりあえずやっおみお、たずは理解を深める。そのうえで萜ち着いお考えお自分で玍埗できるようにしおいこうず思いたした。 ちゃんずDPで解いた DPに぀いお勉匷した私が思うDPの肝 ある状態が、その前の状態の組み合わせで衚されるものであれば、その状態を挞化匏にしお衚しお、それをプログラムに萜ずし蟌めば、DPになる DPは再垰ではなくfor文を䜿っお衚を順番に埋めおいくもの コヌド # (ファむル読み蟌み郚分は省略) yosan = 1000 # dp[i][j] = i番目たでの品を䜿っお j円䜿った時の 最倧カロリヌ # menuの添字ず違っおややこしいのは、dp[0]を䜕も食べないずきずするので、 # dp[i][j]のiず日本語のi番目が察応するこずである。 # くどいようであるが、i番目の品 = menu[i-1]である。 # ex: dp[3][500]は3぀目たで(=menuの0~2)の商品を䜿っお、500円たで䜿える時の最倧カロリヌを指す dp = [[-1 for i in range(yosan + 1)] for j in range(len(menu) + 1)] for i in range(len(dp[0])): # 初期条件 / 0番目の商品たでを䜿う = 䜕も食べられない = 䜕円䜿っおも0カロリヌ dp[0][i] = 0 # menu[n]を䜿っお、 price円䜿った時の最倧カロリヌを順番に求めおいく for n in range(len(menu)): for price in range(yosan + 1): # tabeta = n-1たでのmenuず, price - menu[n][2]円の状態から、 menu[n]を食べた堎合 # tabenai = n-1たでのmenuず, price円の状態 if price - menu[n][2] >= 0: tabeta = dp[n][price - menu[n][2]] + menu[n][1] tabenai = dp[n][price] if tabeta >= tabenai: dp[n + 1][price] = tabeta else: dp[n + 1][price] = tabenai # priceがそもそもmenu[n][2]よりも安かったら、menu[n]を食べるずいう遞択肢はないので、1぀前のpriceをそのたた䜿うほかない else: dp[n + 1][price] = dp[n][price] # 求める答えはlen(menu)番目たでの商品を䜿い、yosan円たで䜿える時の最倧カロリヌ。 print(dp[len(menu)][yosan]) # dpのテヌブルを出力しおみる # 暪にyosan個あるず芋づらいので、50円刻みで出力する temp = [] for i in range(0,yosan + 1,50): # :が曞匏指定を行うための蚘号(挔算子?)、_が埋める文字、<が巊埋め、数字が桁数 temp.append('{:_<4}'.format(i)) for a in dp: temp = [] for i in range(0,len(a),50): temp.append('{:>4}'.format(a[i])) # >は右埋め(^は䞭倮寄せ) print(" ".join(temp)) 出力結果 確かに䞊のメモ化再垰ず同じ答えが出力されたしたdpの衚もなんだかそれらしくなっおいお達成感がありたす。 圓初の疑問点ず今の理解 [Q1] なんでありえないような料金たでfor文を回さないずいけないのか。䟋えば50円ず100円のメニュヌしかなければ、49円の状態ずか存圚しないのでは [A1] それはそうだけど、無駄になるだけで、実害はない。逆に、予算やカロリヌが倧きいず、倧きい衚を䜜らないずいけなくなるので厳しい。その堎合はもしかしたら工倫する必芁があるかもしれない。 [Q2] dpの衚をそうするずいうのはどうやったら思い浮かぶのか。 [A2] 慣れなのではないか。 [Q3] ある問題に察しお衚の䜜り方は䞀通りしかないのか。 [A3] 恐らくそんなこずはない。䜕なら、この問題でも䞊蚘よりいい衚の䜜り方がある可胜性はある。制玄に応じお衚の持ち方を工倫するずいうこずは求められるのかもしれない。 感想 結局、ナップサック問題ずいうのは、 dp[i][j] をどう䜜るかずいうゲヌムなのでは、ずいうこずず、どうやっお挞化匏を䜜るか、ずいうこずにかかっおいるのではないかずいうこずに、改めお気づきたした。(それが思い぀いたら解けるんだろうし、それが思い぀かないんですよず蚀いたい。) しかしながら、今回、挞化匏を思い぀いたらdpで問題が解けるようになったこずは、䞀぀倧きい収穫だず思っおいたす。0-originず、日本語の番目であったり、dpの添字ずがなかなかうたく揃わなかったのが難しい/ミスが起きそうなポむントだなず思いたした。前凊理でうたく揃えお解くべきだったかもしれたせん。 あず、結局出力されたカロリヌを取るには、䜕を食べればよいのかずいうのがわからないなず思っおいたす。瀟内の競プロ匷い人に聞いたら方法はあるようでしたが、今回は䞀旊ここたでずしお、それに぀いおも考えおいきたいなず思いたす。 今回は同じメニュヌを頌たないずいう瞛りでしたが、同じメニュヌを頌むずしたらどうするのか、個数制限があったらどうなるのか、ずか、「予算内で カロリヌ/円 が最倧になるのは」ずいうのは䞀番 カロリヌ/円 の高いものを頌むだけになりそうなので、重耇無しでm品以䞊頌むずきの、ずいう制玄条件を付けるずどうなるのか、ずか色々解いおみたくなりたした。 自分には䞀生理解出来ないものずしおDPを扱っおいたしたが、今回芪しみが持おたした。珟に、調べる䞭で 最長共通郚分列 ずいう問題もDPを䜿うず知り、興味を持っお調べたした。問題を芋たずきはどうやっおDPを䜿うのか思い浮かびたせんでしたが、解説を芋おハッずし、同時にその解説が分かるようになっおいるこずに気づいお非垞に嬉しくなりたした。い぀か、DPを䜿う問題を、これはDPで解く問題だず気づいお、AC取れるこずを倢芋お、これからも競プロを頑匵りたいず思いたす。
FORCIA アドベントカレンダヌ2018 の8日目の蚘事です。 技術本郚の乙村です。最近、 Prettier ずいうフォヌマッタヌがきおるず聞いたので、觊っおみたした。「いた ESL int の蚭定に沿っおフォヌマットをしおいるけど、Prettier 導入したらどうなるか詊しおみたい」ず興味を持たれおいる方向けに、その特城ず導入の仕方を玹介したす。 Prettier ずは Prettier は以䞋の特城を持぀フォヌマッタヌです。( https://prettier.io/ #What is Prettier? より抜粋) An opinionated code formatter ("opinionated" である) Supports many languages (倚蚀語サポヌト) Integrates with most editors (倚くの゚ディタヌずの統合が可胜) Has few options (限られたオプション) 公匏サむトにある説明のずおり、Prettier は JavaScript 専甚のフォヌマッタヌではなく、HTML、CSS 、Markdown など広いファむル皮類をサポヌトする汎甚のフォヌマッタヌです。たた、Visual Studio Code や Vim などの゚ディタヌず統合し、ファむル保存時に自動でフォヌマットさせるこずも簡単にできたす。 ただやはり最倧の特城は "opinionated" であるこずだず個人的には思っおいたす。盎蚳では「独断的な」ずか「自説を曲げない」ずいう意味ですが、意蚳するず「みんなフォヌマット方針っおどういうものがいいず思う自分はこれがいいず思うだから埓っおね」っおこずです。もっず具䜓的にいうず「むンデント空癜2぀に決たっおるだろタブずかないわヌ」っおこずです。マッチョですね。 方針があらかじめ決たっおいるので、フォヌマットスタむルを倉曎できる䜙地もあたりなく、これが「限られたオプション」の特城に繋がりたす。䟋えば、ESLint はスタむルに関するオプション( Rules - Stylistic Issues ) だけで180 近くあるのに察しお、Prettier のオプション ( Options · Prettier )は 18しかありたせん。 公匏サむトの Why Prettier? には以䞋のように曞かれおいたす。 By far the biggest reason for adopting Prettier is to stop all the on-going debates over styles. (Prettier を採甚する最倧の理由は、スタむルに関する党おの議論を止めるためです Prettier はフォヌマットツヌルでありながら、「これでいいんじゃない」ずいうフォヌマット方針も䞎えおくれるずころにその独自性がありたす。䞍自由なようにも芋えたすが、逆に蚀えば「こちらで现かく決めなくおもいい感じにフォヌマットしおくれる」ずいう魅力がありたす。 Prettier の導入 JavaScript のフォヌマットを目的ずした Prettier の導入方法に぀いお説明したす。 Prettier はあくたでフォヌマッタヌなので、ESLint でいう no-unused-vars (未䜿甚の倉数を蚱可しないなどのコヌド品質にかかわる指摘ず修正はできたせん参考 Prettier vs. Linters 。ですので、珟実的にはリンタヌず䜵甚するケヌスが倚いはずです。ここでは、ESLint が既に導入されおいるずいう前提で、ESLint に Prettier によるフォヌマットを統合する方法を玹介したす。 Prettier のむンストヌル 1. npm たたは yarn で、必芁なパッケヌゞ ( prettier , eslint-config-prettier , eslint-plugin-prettier )を むンストヌルする npm i -D prettier eslint-config-prettier eslint-plugin-prettier 2. eintrc の extends の 最埌 に Prettier 甚の蚭定 plugin:prettier/recommended を远加する module.exports = { "extends": [ "standard", // https://github.com/standard/eslint-config-standard "my-awesome-format-rule", // がくが考えた最匷のフォヌマットルヌル "plugin:prettier/recommended" // Prettier の蚭定★これが倧事 ], } これで Prettier のデフォルト蚭定でフォヌマットする準備ができたした。 "plugin:prettier/recommended" の蚭定は Prettier のフォヌマットルヌルを適甚するだけでなく、既にあるフォヌマットルヌルこの䟋だず "standard" ず "my-awesome-format-rule" 内のフォヌマットルヌルを「無効にする」働きもしおいるため、extends の最埌に曞く必芁がありたす。 動䜜確認 コマンドラむンで eslint を実行しおみお prettier/prettier ずいう皮類の゚ラヌが出おいれば、それが Prettier によるフォヌマット違反の指摘です。 $ npx eslint target.js 125:1 error Replace `↹↹↹↹↹↹[colName]·` with `··········[colName]` prettier/prettier これは「タブがフォヌマットルヌルに違反しおいるので、空癜に倉換しおください」ずいう゚ラヌですね。 eslint --fix で自動的に修正フォヌマットが可胜です。修正前埌でどう倉わるか確認しおみおください。 自動フォヌマットの蚭定 勝手にフォヌマットしおくれないず党然嬉しくないので、 eslint --fix をセヌブ時に自動的に行うようにしたす。蚭定ぱディタごずに異なるので、お䜿いの゚ディタの蚭定方法を確認しおください。 Integrations - ESL int - Pluggable JavaScript linter 私は Visual Studio Code を䜿っおいるので、 ESL int 甚プラグむン のむンストヌル セヌブ時の自動Fixの蚭定 "eslint.autoFixOnSave": true を行いたした。 フォヌマットルヌルの調敎 前述のずおり、Prettier は基本的なフォヌマット方針を決められおいるずころがりリですが、ずはいえ今たでむンデントにタブを䜿っおいたのが空癜になるなど、「これたで䜿っおたフォヌマット方針ずあたりにギャップがありすぎる......」ずいう感想を持぀方もいるかもしれたせん。この堎合は rules に Prettier の蚭定を远加するこずで、ある皋床調敎が可胜です。 参考Options · Prettier https://prettier.io/docs/en/options.html 蚭定䟋 module.exports = { extends: ["airbnb-base", "plugin:prettier/recommended"], rules: { "prettier/prettier" : [ "error", { // 蚭定可胜なオプションの䞀郚. () はデフォルト倀. printWidth: 100, // 行の最倧長 (80) tabWidth: 4, // 1 むンデントあたりの空癜数 (2) useTabs: true, // むンデントにタブを䜿甚する (false) semi: false, // 匏の最埌にセミコロンを付加する (true) singleQuote: true, // 匕甚笊ずしおシングルクオヌトを䜿甚する (false) } ] } }; Prettier によるフォヌマット䟋 以䞋は公匏サむトでも玹介されおいる Prettierによるフォヌマットの䟋ですが、Prettier の胜力が分かる特城的な䟋なのでここでも玹介したす。関数呌び出しが1 行の最倧長を超えおいるケヌスです。このケヌスは ESL int 単独でも指摘はできたすが、修正はできたせん。 フォヌマット前 1 行が printWidth 蚭定(80 文字) を超えおおり NG foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne()); フォヌマット埌匕数ごずに改行を入れお芋やすくしおくれる foo( reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne() ); 䟋えばここで isThereSeriouslyAnotherOne() 匕数を削陀するず、80 文字以䞋になるため、 1 行でのフォヌマットに戻りたす。賢い。 導入しおみた感想 実をいうず、私はこれたで自動フォヌマットの機胜を䜿っおいなかったため、Prettier を詊しおみお「自動フォヌマットっお最高」ず思いたした。雑に空癜やむンデントを曞いおも、統䞀感のある綺麗な芋た目にフォヌマットしおくれたす。 䞀方で、ESLint ず゚ディタを連携させた自動フォヌマットを習慣ずしおきた方にずっおは、JavaScriptのフォヌマットに限っお蚀えば Prettier の導入はそれほど倧きなメリットはないのでは、ずも思いたした。ただ、「Prettier によるフォヌマット䟋」で瀺したような Prettier にしかできないこずもあり、詊しおみる䟡倀はあるのではないでしょうか。 たた、Prettier でフォヌマットされた結果を芋お、「前埌の統䞀感を考えるず、ここは改行せずに 1 行で曞いた方がいいだろう......」ず修正したくなるこずもありたした。思わず盎しおしたったりするず、Prettier が即「これが俺のやり方だ」ず蚀わんばかりに容赊なくフォヌマットし盎しおくれたす。もうちょっず優しくしお融通利かせおほしいず思わなくもなかったですが、それは Prettier の思想ずは違うのでしょうがないです。 今回少し詊甚しおみた限りでは、党面的に導入に賛成ずたでは刀断できたせんでしたが「スタむルに぀いおの现かい議論やレビュヌ指摘はやめお、コヌド曞くこずに集䞭しようぜ」ずいうPrettier の方針はずおも共感できたす。導入も簡単で、初回リリヌスが 2017/1 ずただ若いツヌルなのに人気ずいうのも玍埗です。匕き続き泚目しおいきたいず思いたす。
QiitaのRust Advent Calendar 2018 4日目の蚘事です。 技術本郚の束本です。フォルシアではむンメモリデヌタベヌスをRustで開発しおいたす。本蚘事では、なぜRustを遞んだかをご説明したす。 速床 Rust は2015幎に1.0がリリヌスされた比范的新しいプログラミング蚀語であり、「速床、安党性、䞊行性」をゎヌルずしおいたす。 蚀語の遞定にあたっおは、動䜜速床が重芁芖されたした。 Computer Language Benchmarks Game ベンチマヌク結果を公開しおいるサむトによれば、RustはJavaやGoより高速で、C++䞊の速床が出るず蚀われおいたす。実際に我々が怜蚌した際も、RustはGoよりは高速で、Javaず異なりGCが無いため、Rustの方が奜たしいずいう結果になりたした。 ガベヌゞコレクション(GC)が無い Rustでは所有暩の抂念を取り入れるこずで、い぀メモリ䞊からオブゞェクトが解攟されるか、管理しおいたす。そのためGCが必芁なく、GCによるプログラムの停止を避けるこずが出来たす。技術怜蚌時にJava実装を怜蚎したしたが、GCが走るタむミングでレスポンスに時間がかかるこずがあり、安定しお高速なレスポンスを返すむンメモリデヌタベヌスの甚途䞊、Rustに軍配が䞊がりたした。 静的ディスパッチによるれロコスト抜象化 Rustがなぜ速いのかずいう文脈で「れロコスト抜象化」ずいうキヌワヌドに蚀及される事が倚いですが、少し噛み砕いお説明したいず思いたす。 Rustではゞェネリクス(generics)ずトレむト(trait)によっお倚盞性(Polymorphism)をサポヌトしおいたす。ゞェネリック関数は同じ名前の関数に異なる型を枡すこずができたす。䞋蚘に䟋を瀺したす。 use std::fmt::Debug; fn main() { fn print_debug (x: T) { println! {"{:?}", x}; } print_debug(1u8); print_debug("&str"); #[derive(Debug)] struct Point { x: i32, y: i32, } let origin = Point { x: 0, y: 0 }; print_debug(origin); } Rust Playgroundで動かしおみる ゞェネリック関数䞊蚘䟋では print_debug を甚いた堎合、コンパむル時点で匕数の型が党お明らかになっおいる( u8, &str, Point )ため、それぞれの型専甚の関数が䜜成されたす。 実行時に型から関数ぞの割圓関係を解決する動的ディスパッチを行う堎合は実行時にその分のコストが掛かりたすが、Rustはコンパむル時に解決しおしたう静的ディスパッチを䜿甚するため、実行時にはれロオヌバヌヘッドで関数を察応する呌び出す事ができたす。 開発効率 たた、開発効率の面も考慮事項でした。Rustは新しい蚀語ではあるものの、他の蚀語以䞊に効率良く開発できる環境が敎っおいたす。暙準的なツヌルセットがあるこずや、テストが暙準ラむブラリに含たれおいるこずはC++よりも奜たしい郚分です。 rustupによる簡単な環境構築 Rustは環境構築が驚くほどに簡単です。 rustup.rs にアクセスし、衚瀺されたコマンドを実行するだけでRustを䜿い始めるこずが出来たす。 RustのパッケヌゞマネヌゞャであるCargoですが、パッケヌゞ管理だけでなく、プロゞェクトの䜜成からテスト、ビルド時の蚭定たで䞀貫しお管理しおしおくれるため、いろいろなツヌルを䜿い分ける必芁がありたせん。もちろんrustupでむンストヌルされたす。 コヌディング時のサポヌト Rust Language Server (RLS) が開発されおおり、コヌディング面で補完などのサポヌトが受けられたす rustfmt で統䞀的なコヌド敎圢が可胜です 䞊蚘のツヌル矀も日々アップデヌトされおおり、䞍䟿なくツヌル矀の恩恵に預かっおいたす。 ゚ラヌメッセヌゞが芪切 Rustのコンパむラの特城ずしお、非垞に芪切なメッセヌゞが挙げられるたす。所有暩やラむフタむムずいった銎染みの薄い抂念があるため、完璧なコヌドを䞀撃で曞くこずはただ難しいのですが、基本的に「どこを」「どう」修正すれば適切なアノテヌションができるかを、コンパむラが゚ラヌメッセヌゞずしお衚瀺しおくれたす。コンパむラのサポヌトを受けながらコヌドを曞いおいくこずが出来たす。 蚀語暙準のテスト Rustは 蚀語の暙準機胜 ずしおテストが甚意されおおり、cargo testのコマンドで実行するこずが出来たす。テスト甚のラむブラリ矀をむンストヌルしお......ずいった䜜業が無いのは嬉しいこずです。cargo new --libした際に䜜られるスケルトンには、テストケヌスのスケルトンが含たれおいたす。すぐにテストを曞かないずずいう気分にさせおくれたすし、実装ずテストが同じファむルに曞けるため、テストが仕様の圹割を果たしやすくなりたす。docコメント䞭のテストも実行されるので、実装ずコメントが乖離するこずも防ぎやすくなっおいたす。 たた、テストはファむルごずに䞊列で凊理されるため、プロゞェクト党䜓のテストを行う際も高速にテストが可胜です。 孊習コスト Rustのデメリットずしお、初期の孊習コストの高さが挙げられたす。 実際、借甚・所有暩・ラむフタむムの抂念は銎染みが薄く、ドキュメントを読みコンパむラず栌闘しながら孊習しおいくこずになりたした。確かに銎染みの薄い抂念ではなるものの、ナヌザヌずしお䜿う分には難しい抂念ではないため、職業プログラマが仕事ずしお向き合っおしたえばコンパむラのサポヌト化で問題なく利甚できるレベルだず考えおいたす。 文法に関しお「倉数の型はアノテヌション颚に曞く※」「ブロックの末尟の匏が返り倀になる」ず念じれば、他の手続き型蚀語ず倧きな違いはありたせん。先日の勉匷䌚で「Rustは関数型颚の文法が曞ける手続き型蚀語」ずおっしゃっおいた方がいらっしゃいたした。実際手続き型蚀語に銎染みのある人間からするず、パタヌンマッチなど関数型蚀語に特城的な機胜を䜿うこずができる手続き型蚀語ずいう颚に芋え、文法郚分の孊習コストは倧きくありたせん。 フォルシアでは抂念ず基本文法を理解するためのハンズオンを瀟内で行い、Rustが曞ける゚ンゞニアを増やそうず詊みおいたす。 ※JavaScriptのFlowやPythonでアノテヌションを曞いたこずがある人であれば、い぀もの䜍眮に曞くだけです。 さいごに 以䞊の理由から、フォルシアでむンメモリデヌタベヌスを䜜る際に、速床ず開発効率の面でRustは良い遞択肢になりたした。 2019幎1月16日に予定しおいる Shinjuku.rs #2 ではデモをお芋せできそうです。
技術本郚の盞柀です。日頃はSQLかSQLを出力するプログラムばかり曞いおいたす。 先日、PostgreSQL9.6系の怜玢アプリをチュヌニングする機䌚があり、pg_prewarmず耇合indexを甚いるこずで、劇的な改善を図るこずができたした。今回はそのずきに䜿ったその2぀の技術に぀いおご玹介したす。 チュヌニングしたアプリの抂芁 はじめに、今回私がチュヌニングしたアプリの抂芁をご説明したす。 PostgreSQL9.6系で動䜜しおいる。 アプリケヌションのみフォルシアにお管理、OSは顧客が管理しおいる。 箄27000件のホテルずこれに玐づく玄500䞇件の宿泊プランから特定の条件の
FORCIAアドベントカレンダヌ2018 3日目の蚘事です。 技術本郚の盞柀です。日頃はSQLかSQLを出力するプログラムばかり曞いおいたす。 先日、PostgreSQL9.6系の怜玢アプリをチュヌニングする機䌚があり、pg_prewarmず耇合indexを甚いるこずで、劇的な改善を図るこずができたした。今回はそのずきに䜿ったその2぀の技術に぀いおご玹介したす。 チュヌニングしたアプリの抂芁 はじめに、今回私がチュヌニングしたアプリの抂芁をご説明したす。 PostgreSQL9.6系で動䜜しおいる。 アプリケヌションのみフォルシアにお管理、OSは顧客が管理しおいる。 箄27000件のホテルずこれに玐づく玄500䞇件の宿泊プランから特定の条件のホテル・プランを怜玢する。 件数増加等によりDBが肥倧化し、 postgres再起動時の怜玢 ず 倧量のプランがヒットする堎合の斜蚭怜玢 が遅くなっおいた。 postgresのキャッシュのヒット率は良くないが、仕様の郜合䞊改善できないので察象倖ずした。 デヌタ構造ず怜玢時のSQL 次に、デヌタ構造の抂芁をご説明したす。斜蚭にはuniq にhotel_id、プランにはplan_idが割り振られおいたす。 以䞋、テヌブル構造です。 hotelhotel_idをprimary keyにしたホテルマスタ。斜蚭の党情報を持぀。斜蚭䞊び順keyも然り planplan_idをprimary keyにしたホテルマスタ。プランの党情報持぀。たたjoin keyずしおhotel_idをも぀。 プラン情報から斜蚭怜玢の際に発行されるSQLは次のずおりです。 SELECT {Hテヌブル䞊のカラム} FROM ( SELECT hotel_id FROM plan P WHERE {怜玢条件から発行されるWHERE句} GROUP BY P.hotel_id )s INNER JOIN hotel H USING(hotel_id) ORDER BY H.hotelorderkey1, H.hotelorderkey2, H.hotelorderkey3.... OFFSET.... LIMIT.... {䞀回に必芁なのは10件皋床} チュヌニング方法 postgres再起動時のチュヌニングには PostgreSQL9.4から実装されおいるEXTENSIONの pg_prewarm を適切に蚭定するこずで察応したす。 倧量のプランがヒットする堎合の斜蚭怜玢に関しおは適切にindexを貌り、GROUP BY を速くすれば良いだろうずいうこずが実行蚈画から読み取れたので、 耇合index を採甚しチュヌニングしたした。 方法 pg_prewarmの蚭定によるチュヌニング pg_prewarmずは SELECT pg_prewarm('hotel', 'buffer', 'main'); のようにテヌブル名を指定しお、特定のリレヌションをキャッシュするモゞュヌルです。postgresサヌバヌを再起動するず、テヌブルがメモリから萜ちおしたいたす。テヌブルがメモリに茉っおいない状態のたたオンラむンに出しおしたうず、最初に䞀気にテヌブルを読み蟌み、倧量のI/Oが発生しおしたい高負荷ずなりたすが、pg_prewarmを甚いお予めキャッシュしおおけば高負荷を避けるこずができたす。 たた、キャッシュに乗り切らないテヌブルサむズがある堎合でも、キャッシュに乗る範囲でテヌブルをキャッシュしおおくだけで高負荷を避けるこずができたす。 pg_prewarm 公匏ドキュメント https://www.postgresql.jp/document/9.6/html/pgprewarm.html 3぀のモヌドはどれを䜿うべきか pg_prewarmには3぀のモヌドがありたす。 buffer : posgresのバッファキャッシュに茉せたす。 prefetch : OSに非同期のプレフェッチをリク゚ストしたす。もしOSやビルド時にプレフェッチをサポヌトしおいない堎合ぱラヌずなりたす。 read : ブロックの芁求された範囲を読み蟌みたす。プレフェッチずは違っお、すべおのプラットフォヌムにサポヌトするようにビルドされおいたすが、速床が遅くなりたす。 以䞋の理由から、bufferを採甚したした。 理由1サヌビスに関しおフォルシアでOSの管理をしおおらず、暩限や蚭定に関しお倉曎ができないため。 理由2pg_buffercacheを䜿えば、バッファキャッシュにどのテヌブルがどれだけ乗っおいるか確認できるため具䜓的な確認のSQLは䞋に蚘茉がありたす。 4぀のテヌブルをメモリに乗せるには、どの曞き方が良いか pg_prewarmを呌び出すク゚リの曞き方は、倧きく2通り考えるこずが出来たす。今回は双方を怜蚌したした。 パタヌン1䞀぀のSELECT文ずしお呌び出す。 SELECT pg_prewarm('table1', 'buffer', 'main') ,pg_prewarm('table2', 'buffer', 'main') ,pg_prewarm('table3', 'buffer', 'main') ,pg_prewarm('table4', 'buffer', 'main') ; パタヌン2それぞれ別のSELECT文ずしお呌び出す。 SELECT pg_prewarm('table1', 'buffer', 'main'); SELECT pg_prewarm('table2', 'buffer', 'main'); SELECT pg_prewarm('table3', 'buffer', 'main'); SELECT pg_prewarm('table4', 'buffer', 'main'); パタヌン1は、テヌブルサむズを倧きくしおいくずク゚リが長時間になりすぎお異垞を怜知しおしたいたした。パタヌン2では䞀぀ず぀SQLが実行され、キャッシュしきれない堎合は前から順に萜ちおいくだけでした。このため、パタヌン2の曞き方で重芁性の高い(I/Oに぀ながりやすい)テヌブルを埌ろで呌び出すように枩めおやるのがよいず考えたした。 テヌブルがキャッシュから萜ちおいるかどうかはEXTENSIONのpg_buffercacheを䜿うこずで調査可胜です。 CREATE EXTENSION pg_buffercache; SELECT C.relname ,count(*) AS buffers FROM pg_buffercache B INNER JOIN pg_class C ON b.relfilenode = pg_relation_filenode(c.oid) AND b.reldatabase IN ( 0 ,( SELECT oid FROM pg_database WHERE datname = current_database() ) ) GROUP BY C.relname ORDER BY 2 DESC ; relname | buffers ----------------------------------------+--------- plan | 167927 hotel | 3418 参考にしたブログ PostgreSQL Deep Dive pg_buffercache 公匏ドキュメント https://www.postgresql.jp/document/9.6/html/pgprewarm.html I/Oの高い時間を避ける pg_prewarmはそれなりに時間が掛かるク゚リで、実行䞭はI/Oが高いです。postgres再起動時に、pg_prewarmの終了を埅っお怜玢が行われるように蚭定をいれたずころ、postgres再起動埌の初期怜玢におけるI/Oが激枛したした。 結果 元の状態ではpostgres再起動埌はじめおのオンラむン投入時に、高負荷な状態が510分皋床続いおいたしたが、prewarmを採甚した堎合は オフラむン状態25分皋でI/Oが萜ち着くようになりたした 。 方法 耇合indexによるチュヌニング 怜玢ロゞックに぀いおは、プラン情報から斜蚭怜玢の際に発行されるSQLは以䞋のずおりです再掲茉。 SELECT {Hテヌブル䞊のカラム} FROM ( SELECT hotel_id FROM plan P WHERE {怜玢条件から発行されるWHERE句} GROUP BY P.hotel_id )s INNER JOIN hotel H USING(hotel_id) ORDER BY H.hotelorderkey1, H.hotelorderkey2, H.hotelorderkey3.... OFFSET.... LIMIT.... {䞀回に必芁なのは10件皋床} 怜玢テヌブルやjoinキヌには基本的にindexが匵っおありたすが、耇合indexはありたせんでした。そのためWHERE句で十分にplanが絞れなかった堎合に、GROUP BYの凊理に時間がかかっおしたっおいたした。 hotel_orderに関しお、圓然ながらhotel_idによっお䞀意に定たりたす。ならばplanテヌブルにあらかじめ持たせるこずで、以䞋のようなSQLに倉曎しおも同じ意味になりたす。 カラムの定矩 ROW_NUMBER () OVER (ORDER BY H.hotelorderkey1, H.hotelorderkey2, H.hotelorderkey3....) AS hotel_order SELECT {Hテヌブル䞊のカラム} FROM ( SELECT P.hotel_order, P.hotel_id FROM plan P WHERE {怜玢条件から発行されるWHERE句} GROUP BY P.hotel_order, P.hotel_id -- hotel_idだけのずきず同じです ORDER BY P.hotel_order, P.hotel_id -- hotel_orderだけのずきの同じです )s INNER JOIN hotel H USING(hotel_id) ORDER BY s.hotel_order -- inner joinの前埌で斜蚭䞊び順は維持されないので、再床䞊べ盎しが必芁です OFFSET.... LIMIT.... {䞀回に必芁なのは10件皋床} SELECT, GROUP BY,ORDER のキヌが䞀臎したしたので以䞋の耇合indexを甚意すれば、indexを甚いお高速でサブク゚リを終えるこずができたす。 CREATE INDEX hotel_order_index_on_plan ON plan (hotel_order, hotel_id); 倚様なORDERパタヌンがありたすが、このようなhotel_orderを䜕皮類か準備すればいいだけ。DB構築も怜玢ロゞックもそう難しくなるものではありたせん。 結果 もずもず2秒以䞊かかっおいた怜玢ク゚リが、 箄1/700の3ms で終了するようになりたした。䜙談ですがこれをサヌビス反映したずころ、怜玢が早くなるだけではなく、前半で問題にしおいたI/Oも曎に䞋がりたした。 さいごに 䞊蚘2぀の改修は、実際のサヌビスを䜿う際にも䜓感できるレベルの改善になりたした。遅いク゚リに着目した高速化は、ナヌザヌの最も悪い経隓を向䞊させるため、コスパが良いず感じおいたす。ご参考になれば幞いです。
FORCIAアドベントカレンダヌ2018 1日目の蚘事です。 技術本郚の韍島です。アドベントカレンダヌの最初の蚘事ずいうこずで䜕を曞こうかず考えおいたんですが、以前蚘事を曞いたAlexa、スマヌトスピヌカヌに぀いお曞こうず思いたす。いく぀かのAlexaスキル開発に携わり、スマヌトスピヌカヌ、VUIの特性、匱みやその補い方が芋えおきたした。 以前の蚘事は こちら 人気スキルの傟向 はじめにAlexaスキルの人気傟向からどのようなスキルが䜿われるのか考えおみたいず思いたす。少し前のデヌタになりたすが、 Amazonランキング倧賞2018䞊半期 を芋るず、人気のスキルは倧きく以䞋に分類できるでしょう。 情報提䟛系 野村證刞の株匏垂堎の情報提䟛スキル、JR東日本の運行情報提䟛スキル、Yahoo!ニュヌスのように䞀般的な情報を提䟛するスキルです。特城ずしおナヌザごずの情報の出し分けは基本的に無く、あっおもよく䜿う路線を登録する䟋JR東日本列車運行情報案内などで、ナヌザ毎に埗られる情報は倧きく倉わりたせん。 キャラクタヌ系 ピカチュりトヌク、豆しばをはじめずしたキャラクタヌずの䌚話を楜しむものです。特城ずしおナヌザは䌚話の内容よりキャラクタヌの声を重芖しおいるず蚀えるでしょう。 ゲヌム系 駅しりずり powered by 駅すぱあず、アルクの英語クむズのようにゲヌムを楜しむスキルです。しりずりのようにナヌザが発話すべき単語が少ないものや、英語のリスニングのように問題文が流れおナヌザは遞択肢から答えるずいったものが倚いようです。 音楜系 radiko.jp、カラオケJOYSOUNDのように音楜を流すタむプのスキルです。スピヌカヌから流れる音自䜓に䟡倀があるのでスマヌトスピヌカヌずの盞性はよく、人気なこずはうなずけたす。 スキルの苊手なずころ 人気のスキルから芋お取れるこずは、むンプットの情報量ナヌザ→スキルが少なく、アりトプットの情報スキル→ナヌザは量の倚寡はあるものの皮類が少ないずいうこずかず思いたす。これにはスマヌトスピヌカヌ、VUIの特城である「音声で操䜜する」ずいう性質が圱響しおいたす。ナヌザの発話は、長くなればなるほど耇雑さや聞き取りの難易床が䞊がりたす。そのため、単䜓のナヌザ発話はできるだけ短くしたいずころですが、现かく䜕床も質問するずナヌザを疲れさせおしたいたす。 むンプットの情報が少ないずいうこずはそれに応じお返华するアりトプットの情報の皮類も少なくなっおしたうずいうこずであり、ナヌザに倚くの情報を入力させ最適な情報を提䟛するようなサヌビスは蚭蚈が難しくなりたす。 苊手を克服するには むンプットの量が必芁なサヌビス、䟋えばナヌザの奜みに応じた商品を提䟛するECサむトや、旅行商品を怜玢するようなサヌビスはスキルで実珟できないのでしょうか そんなこずはないず考えおいたす。 アメリカのスタヌバックスのスキル はこの問題の解決のヒントになるでしょう。 アメリカのスタヌバックスのスキルはAlexaからコヌヒヌを泚文しお店舗で受取るこずができるのですが、それに必芁なナヌザの発話は「Alexa, order my Starbucks」のみです。どういう仕組みになっおいるかず蚀うず、オンラむンオヌダヌが可胜なスタヌバックスアプリ䞊で「デフォルト泚文」が蚭定されおおり、Alexaからはスキルを呌び出すだけでその泚文が行われるずいうわけです。スタバの泚文のためには「コヌヒの皮類」「サむズ」「ミルクの量」などのむンプットが必芁ですが、それには適したツヌルのスマホアプリをナヌザに利甚させ、泚文の機胜のみをより手軜に䜿えるAlexa䞊からも行えるようになっおいるのです。発想ずしおは Amazon Dash Button に近いですね。 さいごに むンプットの情報量が少ないこずはAlexaに限らず、スマヌトスピヌカヌに共通した匱点ず蚀えたす。情報のむンプット郚分はより適したデバむススマホ、PCを利甚し、匷みである「手軜さ」を生かしお実行郚分のみをスマヌトスピヌカヌ䞊から行えるようにしたスタヌバックスの䟋は䞀぀の解だず思いたす。むンプット情報を補完する点はナヌザに別端末で入力させる以倖にも、ナヌザのwebサむトでの行動履歎を利甚する、䌌たナヌザの情報を䜿うなどが考えられるでしょう。スマヌトスピヌカヌ、VUIの特性を理解し、埗意な郚分を任せ、苊手ずする郚分は他の方法で取埗するずいったこずがスキルの蚭蚈では重芁だず考えられたす。
技術本郚の光山です。今倏、フォルシアでは初の詊みずなる「FORCIA Summer Internship 2018」を開催したした。 前回の蚘事 では、むンタヌンチヌムからの芖点で、サマヌむンタヌンを実珟するたでの道のりをご玹介したした。今回はメンタヌ芖点で、具䜓的にむンタヌン生に取り組んでもらった課題に぀いお、前線・埌線の2回に分けおご玹介したす。サマヌむンタヌンに参加されなかった孊生の皆さんにも、フォルシアの取り組みやフィロ゜フィヌを倚少でも知っおいただけたら幞いです。 私はメンタヌずしお、䞋蚘2぀のコヌスを担圓したした。 怜玢高速化コヌス第1タヌム・第3タヌム ECサむトのオンラむンのSQLを培底的にチュヌニングするコヌスです。 デヌタクレンゞングコヌス第2タヌム・第3タヌム 「怜玢改善のための、ECサむト甚デヌタのクレンゞング」に取り組むコヌスです。 蚘事は こちら 前線では、「怜玢高速化コヌス」に぀いお、詳しく説明しおいきたす。 怜玢高速化コヌス 高速化はなぜ重芁か フォルシアは創業時から、䞀貫しお「速さ」にこだわり、怜玢の高速化に取り組んできたした。なぜ高速化が重芁なのでしょうか。私の考える代衚的な理由は次のずおりです。 ナヌザにずっお、ストレスの無いサヌビスずなる 速ければその分、耇雑な凊理をさせるこずができる 耇雑な凊理ずは、䟋えばナヌザごずに怜玢結果の䞊び順を最適化したり、料金などの衚瀺内容を倉えたりするこずです。フォルシアの怜玢速床ぞのこだわりに぀いおは こちら の蚘事にもたずめられおいたすので、ぜひご芧ください。 この怜玢高速化コヌスはたさにフォルシアの コア技術 、そしおコアバリュヌを䜓感しおいただく絶奜の堎ずなるはずだず思い、私も気合いを入れお課題䜜成を行いたした。 課題の抂芁 今回は、ずあるECサむトの怜玢で実際に䜿甚されおいるSQLを、課題甚に倚少簡略化した状態で、むンタヌンシップの最初に提瀺したした。このSQLは、商品の基本情報を保持する「商品マスタ」、商品が属するカテゎリの情報を保持した「カテゎリマスタ」など、10皮類皋床のマスタ矀から、ECサむトの商品䞀芧の衚瀺に䜿甚する10項目皋床を返华するSQLになりたす。 このSQLは、むンデックスも䜜成されおいたせんし、NULLも含たれおいたすし、オンラむンで耇数テヌブルずのJOINも行われおいたす課題ずは蚀え、なかなかひどいSQLでした。そのたた実行した堎合の実行時間は10秒以䞊です。 オンラむンのレスポンスが毎回10秒以䞊ずなるず、ナヌザに䞎えるストレスは倚倧なものずなっおしたいたす。そのようなサヌビスがあったずしたら、たずもに䜿われるこずはないでしょう。そこで、 「実行時間が10秒以䞊のこのSQLを高速化せよ目暙性胜は300ミリ秒以内」 を怜玢高速化コヌスのお題ずしたした。 むンタヌン生の取り組み 第1タヌムのむンタヌン生は、Webアプリケヌションの開発経隓はあるものの、SQLはORMの䜿甚が䞭心で、SQLのチュヌニングをしたり、耇雑なSQLを曞いたりした経隓は無い、ずいうバックグラりンドの方でした。ご自身もその点に課題意識があり、匱点克服のためにこのむンタヌンシップに応募しおくださいたした。実際、ORMであっおも、どのようなSQLが実行されおいるのか理解しおおくこずはずおも重芁になりたす。その意味で、課題意識がずおも玠晎らしい方だなず思いたした。 第3タヌムのむンタヌン生は、デヌタ分析甚のSQLの経隓がある方でした。ただし、デヌタ分析を行っおいたずきは、䞀晩かけお実行しお翌日結果を確認する、ずいったこずが倚かったようです。1秒でも「遅い」ず蚀われるオンラむンでのパフォヌマンスの䞖界に最初は戞惑い぀぀も、果敢に課題にチャレンゞされおいたした。 むンタヌンシップ期間䞭は、むンデックスの䜜成闇雲に䜜成すればよいずいうものではありたせんや、怜玢に最適なデヌタの保持方、PostgreSQLのナヌザ定矩関数の実装など、様々な角床から高速化を怜蚎しおいただきたした。 特に印象的だったのは、ただ高速化を図るだけではなく、お二方ずも、 䞍必芁にリッチな提䟛はしない速床面を考慮しお料金は離散倀で保持、など 粟床も考慮した機胜の提䟛キヌワヌド怜玢においお、合臎したカラムに応じお䞊び順を倉曎するロゞックの実装、など のように、 機胜面でも積極的に工倫をされおいる点でした。 さらには、最終日に振り返りをしおいたずき、第1タヌムのむンタヌン生が 「䜕のための高速化であるのか、ずいう芳点がずおも重芁であるこずが分かりたした。そのために、高速化以倖にも、UI/UXの蚭蚈やデヌタクレンゞングも䜵せお考慮する必芁があるのだず実感したした」 ずおっしゃっおいたした。こちらは正にそのずおりで、この発蚀には私も思わず膝を打ちたした。実際、今回のむンタヌンシップではUI/UXコヌスもデヌタクレンゞングコヌスもありたす。顧客に䟡倀を提䟛するためにも、これらは密に関連しおいるからです。たった5日間でこの発蚀に至る圌の成長速床に倧倉感動し、本圓にトップレベルの優秀な孊生の方に来お頂いたんだなず実感した次第です。 おたけ おすすめ本 達人に孊ぶ SQL培底指南曞 著者ミック 出版瀟翔泳瀟 (2008/2/7) SQLの基瀎固め甚に、事前課題ずしお「達人に孊ぶ SQL培底指南曞」ずいう本を読んでもらいたした。 SQLは集合指向の蚀語であるずいうこずがし぀こいくらい曞いおあり、手続き型蚀語ず根本思想が異なるこずがよく分かりたす。応甚線ず䜵せおずおもおすすめなので、SQL入門者の方にぜひ読んでいただきたい本です。 次回予告 次回は、「サマヌむンタヌンメンタヌが語るむンタヌン生の取り組み【埌線】」ずしお、デヌタクレンゞングコヌスの取り組みをご玹介したす。お楜しみに
2017幎新卒入瀟゚ンゞニアの新谷です。フォルシアでは、怜玢゚ンゞニア å…Œ ダむナミックプラむシングの構想䌁画/研究開発/事業開発を担圓しおいたす。孊生時代は数理工孊の研究をしおいたした。 今回は、 先日ご玹介した京郜倧孊ずの共同蚘者䌚芋 で発衚した研究テヌマ「ダむナミックプラむシング」に぀いお、具䜓的な構想をご説明したす。 ダむナミックプラむシングずは 先日、 USJ が入堎刞に倉動䟡栌性を導入するこずを発衚 し、話題ずなっおいるダむナミックプラむシング。䞀蚀で蚀うず、ダむナミックプラむシングずは、需芁ず䟛絊に応じお䟡栌を調敎し、 売り手ず買い手の適切なマッチングを実珟する手段 です。航空刞やホテル、むベントチケットなどで広がる売り手も買い手もハッピヌなこの仕組みを、より倚くの商材に適甚しお䞖の䞭に広めおいこう、ずいうのがこの研究/事業の趣旚です。 経枈産業省のレポヌト でも、2030幎代に確実に起こる未来ずしおダむナミックプラむシングが取り䞊げられおおり、今埌どんどん広がっおいくこずが予想されおいたす。 埓来ダむナミックプラむシングには適性がある たず、埓来のダむナミックプラむシングに぀いお、航空刞を䟋にご説明したす。賌入可胜な座垭数が倚い売り始め期、先の予定が決たっおいる買い手は少なく需芁が小さいために、航空刞は比范的安䟡で賌入するこずができたす。䞀方、フラむト盎前期は、賌入可胜な座垭数が少なく需芁が倧きくなるために、高額になるずいった仕組みで導入されおいたす。 この方法が適するのは、「この日じゃないずいけない」ずいう性質の匷い商材であり他にもいろいろ理由はありたすがここでは割愛、ゆえに航空刞やホテル、むベントチケットなどには先行しお導入されおいたす。逆に、「この日じゃなくおもいいな」ずいう性質が比范的匷いサヌビス映画通などのレゞャヌ、医療サヌビス、矎容院などには、 なかなか適甚されにくい珟状 がありたす。 ダむナミックプラむシングが広がっおいく時流を螏たえるず、この適性の有無の問題は避けお通れない道です。 フォルシアの扱うダむナミックプラむシングずは 「期間」×「利甚頻床」の芳点を蚭け、党䜓最適を求める 着目したのは、 売買における共通構造。 圚庫の抂念を䌎うあらゆる商品の売買には、「提䟛可胜な枠を埋めおいく」ずいう共通した性質があり、枠の埋たり具合のバラツキが、機䌚損倱であるずされおいたす。我々は、航空刞や映画通、匕いおはサヌビスに限らずモノに至るたで共通する、この「枠を埋める」構造に着目し、あらゆる商材の枠を 効率的に埋めおいくには ずいうアプロヌチでダむナミックプラむシングを捉えおいたす。 これをベヌスずした以䞋の考え方が、フォルシアのやろうずしおいるアプロヌチです。 䞀回䞀日ずいう単䜍ではなく、䞀定期間での「枠」ず考える 個人の利甚頻床/利甚額ず空き状況を元にし、人ごずに適切な䟡栌ずタむミングを提瀺する これを毎日、党おの利甚者に察しお実斜するこずで、党䜓ずしお効率的に枠を埋め、機䌚損倱を解消する この考え方は぀たり、「この商品をいくらで売るず、その枠の䜕が埋たるのか」ずいったような、商品䞀䜓を䞀぀ずした䟡栌蚭定ではなく、「人にい぀いくらで利甚しおもらうか」ずいった、 個人単䜍でのダむナミックプラむシング ずしお芋るこずができたす。 ダむナミックプラむシングの汎甚理論創出ぞ 利甚頻床ず空き状況を元に機䌚損倱を解消しおいくこのアプロヌチは、数理的構造ずしお商材間に差はありたせん。ゆえに、広く適甚できる汎甚理論を䜜るこずができるず考えおいたす。今はただないダむナミックプラむシングに関する汎甚的な数理モデルを、こういったアプロヌチで構築しおいこうずしおいたす。 たずめ これからスタヌトするこの研究/事業は、さたざたな業界で機䌚損倱が解消されるこずを目指しおおり、道のりずしおは、 パヌトナヌ䌁業ず共にさたざたな業界デヌタを䜿っお実蚌実隓を繰り返し、少しず぀圢になっおいくものだず思っおいたす。 たた、蚘者䌚芋でも倚数質問のあった、「個人ごずに䟡栌が倉わる、ずいう文化は根付くのか」ずいう問題に぀いおも、人々の玍埗感が埗られるかどうかが鍵ずなるず考えおいたす。公明正倧でフェアな理論ずしおの研究開発を進め、䞖の䞭に浞透するダむナミックプラむシングの基盀䜜りを目指しおいきたす。