refinedでPosInt + PosInt を PosIntにしたい

結論

オーバーフローしたら条件満たさないから無理

結論以外

refinedScalaでrefinement typeを表現するためのライブラリです。

このライブラリの中に「1以上のInt」を表すPosIntという型があるのですが、refinedは PosInt + PosInt = PosIntといった推論を(通常は)行わないので、2つのPosIntを足す場合は自分で検査を行う必要があります。

val a = PosInt.unsafeFrom(1)
val b = PosInt.unsafeFrom(2)
val c: Either[String, PosInt] = PosInt.from(a.value + b.value) 

一方でrefinedでは catsのSemigroupインスタンス が提供されているので、 以下のようにPosIntが返ってくるPosInt同士の計算を行うことができます。

import eu.timepit.refined.cats._
import cats.syntax.semigroup._

val c: PosInt =  a.value |+| b.value

標準で上記のようなメソッドが用意されていないのはオーバーフローによりPosInt同士の加算が負になる = PosIntでなくなる可能性があるためです。 (see https://github.com/fthomas/refined/issues/217#issuecomment-258535569 )

実際、refinedで提供されているSemigroupのインスタンスでは オーバーフローしないような実装 が含まれています。

これが求めるものかどうかはユースケース次第かとは思います。筆者がよく使うシチュエーションではPosInt.fromを使って万が一オーバフローが発生したら例外が出てくれる方が嬉しいので上記インスタンスを積極的に利用することはしていません。

ということで用法用量を守って正しくお使いください。

なおこの記事は来週のアドベントカレンダー用の記事の端材を使って執筆されました。

MySQLでカラム追加などのalter table中にクエリがブロックされるかなどについてのメモ

これは何

MySQLのカラム追加などのDDL, alter table時にそれぞれの操作がどれくらい危険なのか、負荷は?といった情報の見方を毎回忘れるのでメモしたもの

まとめ

  • 表を見なくても ALTER TABLE の末尾に ALGORITHM=INPLACE,LOCK=NONE; をつけてしまえば、動作を決められる(不可能な場合はエラーになる)ので、それで実験してみるとよい
  • 公式document に詳細に記載があるのでそれを見ると良い。
    • ただし必ずしもその表通りになるわけではないため表の下に記載されている注意書きをよく読む必要がある。
  • 例えば varcharのサイズ変更 = Extending VARCHAR column size は表内では INPLACE=yes と記載されているが length を 255 から 256 に拡張する場合は ALGORITHM=COPY しか利用できないといった制限が記載されているので見落とさないようにすべき。(MySQL8.0 公式doc
  • 余談だが上記の事象については MySQLでのVARCHARサイズ変更を行うALTER TABLEについて - だいたいよくわからないブログ に理由を記載している。

Alter Tableの性能特性についての公式ドキュメントの見方

にある表からやりたい操作を探せば良い。

表にあるそれぞれの意味と解釈は

項目 説明
インプレース In Place yesだと既存データを新規ファイルにコピーせずに、既存ファイル内でalter tableを実行する。Noだと新規データファイルにデータをコピーするのでディスク容量を消費する。またsharedロックが取得され書き込みがブロックされる。(yesだとalgorithm=INPLACE, noだとalgorithm=COPYとなる)
テーブルの再構築 Rebuilds Table yesだと既存データの書き換えが走るのでテーブル行数に応じて時間がかかったりディスクIOが高まったりする
同時 DML の許可 Permits Concurrent DML yesだとinsert/update/deleteなどの更新が行える(lock=none)
メタデータの変更のみ Only Modifies Metadata yesだとメタデータ更新のみでalter tableがすぐ完了する

より詳細な解説は以下の記事を参照すると良い。

mita2db.hateblo.jp

まとめ欄にも記載したが、表だけではなく表の下の解説まで読むことをおすすめする。読み飛ばすとALGORITHM=INPLACEで実行されると思っていたのにALGORITHM=COPYが発動してしまう(ALGORITHMについては後述)といったことがありえる。

algorithmの違い

algorithm=COPY

  • 空テーブルを作成
  • 全データ変換しながらコピー
  • テーブルを新しいものに入れ替え という手順でのマイグレーション

基本的に古い時代の物だがいくつかのケースではCOPYが採用される。

使われるケースは例えば

  • 主キーの削除(削除&追加を1行で行うのは問題ないが、削除だけを行う操作を行うと)
  • データ型の変更

などになる。

  • データをコピーするためデータ件数によってはdisk IO負荷が高くなり、ディスク容量も必要で、実行時間も長くなることがあるので注意

algorithm=INPLACE

  • テーブルを作り直す
  • secondary indexを作り直す
  • テーブル作り直し中の更新操作をログに記録
  • テーブル作り直し中の更新操作を作り直したテーブルへapplyする

という手順でのマイグレーション

MySQL 5.xでALGORITHMを指定せずにADD COLUMNをした場合は大抵の場合は inplace になる。

誕生の経緯などは第30回 InnoDBオンラインDDLについて | gihyo.jpを参照

  • 裏でテーブルを作り直すのでデータ件数によってはdisk IO負荷が高くなり、実行時間も長くなることがあるので注意

algorithm=INSTANT

メタデータのみを書き換えて、テーブルデータを全く変更しないモード

対応する操作は以下

  • テーブル末尾へのカラム追加
  • MODIFY COLUMN
  • etc

基本的にはMySQL 8以降の機能。

MySQL 8.0.12からInstant ADD COLUMNという機能が追加されました。

MySQLのInstant ADD COLUMNをちゃんと調べてみる - y-asaba@hatenablog

auroraでは今までサポートされていなかったが 2021/11/18にMySQL 8.x系互換のaurora MySQL v3がリリースされた ので現在は利用可能のよう。

速度感の違いとしては

  • COPY 21.70 秒
  • INPLACE 6.54 秒
  • INSTANT 0.05秒

といった参考値が挙げられている。 (もちろん諸条件によって変化する) MySQL 8.0 の INSTANT DDL について – スマートスタイル技術ブログ

カラム追加をalgorithm=INSTANTで実行する際の条件については MySQL :: MySQL 8.0 Reference Manual :: 17.12.1 Online DDL Operationsから (Syntax and Usage Notes > Adding a column )を参照

aurora fast DDL

仕組みは不明だがテーブルコピーなしで瞬時にカラム追加できる。

条件は以下

  • NULL を許容する列 (デフォルト値を持たない) のテーブル末尾への追加
  • パーティション分割されてない
  • レコードサイズがページサイズの半分以下

公式 には

Currently, Aurora lab mode must be enabled to use fast DDL for Aurora MySQL. We don't recommend using fast DDL for production DB clusters. For information about enabling Aurora lab mode, see Amazon Aurora MySQL lab mode.

との記載があり、さらに aurora MySQL v3からはInstantで行くぞと書いてあるためこちらについて詳しくなる必要はあまりなさそう。

Alter Table時のlockモードとalgorithmの指定

意図されていないlockモードやalgorithmでの動作を防ぎたい場合は

ALTER TABLE test MODIFY text varchar(20), ALGORITHM=INPLACE,LOCK=NONE;

のように明示的に指定してやればよい。

もし想定と異なるモードで実行される状態であればエラーで停止するようになっている。

第30回 InnoDBオンラインDDLについて | gihyo.jp

LOCKについて

ページ上部に記載した表を見て意図したものを選ぶのがよい。

オプション 説明
NONE read ○, write○ (何もブロックしない)
SHARED read ○, write × (writeがブロックされる)
EXCLUSIVE read ×, write × (read/writeがブロックされる)
DEFAULT 使用可能なもっとも低いレベルのロックを使用
LOCK句省略 DEFAULTと同じ

algorithmについて

オプション 説明
COPY テーブルコピー方式
INPLACE インプレース方式
INSTANT インスタント方式
DEFAULT 一番負荷が少ない方式を採用
ALGORITHM句省略 DEFAULTと同じ

マイグレーションの速度感

インスタンスサイズや設定によるので概算でしかないが以下が参考になる。

https://www.percona.com/live/e18/sites/default/files/slides/Deep%20Dive%20on%20Amazon%20Aurora%20-%20FileId%20-%20160328.pdf の p.31より r3.large ~ r3.8xlarge

mysql テーブルサイズ 実行時間目安 sec 実行時間の大体オーダー感
5.6 10GB 900 ~ 3960 15 min ~ 70 min
5.6 50GB 4680 ~ 23400 1.3h ~ 6.5h
5.6 100GB 14400 ~ 53460 4h ~ 15h
5.7 10GB 1080 ~ 1600 15 min ~ 30 min
5.7 50GB 5040 1.4h
5.7 100GB 9720 2.7h

繰り返すがinstanceサイズやレコードサイズ、mysqlの設定などあらゆる要素で変動するので、この時間で終わると思ってはいけない。

テーブルサイズの調べ方

MySQLでDBとテーブルのサイズを確認するSQL #MySQL - Qiitaを参考にした。

SELECT  
    table_name, 
    table_rows,
    floor((data_length+index_length)/1024/1024)/1024 AS dataGB  #総容量(インデックス込み)
FROM 
    information_schema.tables  
WHERE
    table_schema=database()  
ORDER BY
    table_name;

Places: Adding Message-Passing Parallelism to Racket を読んだ

はじめに

ruby3で導入されるRactorという機構があり、そこの提案の中で

This model is similar to Racket's Place abstraction.

という記載があったのでRacketのPlaceを探してみると、Place自体はRacketの公式ドキュメント に記述を見つけることができました。

更に追ってみるとこれらの源流になっている気配がする2011年のDLS(Dynamic Languages Symposium)で Places: Adding Message-Passing Parallelism to Racket という論文が見つかったので、こちらについてかいつまんで紹介したいと思います。(RubyやRacketの話はせず、この論文の話のみを行います。RubyやRacketにある機能がこの論文と同じモデルなのか等は特に調査していません。)

自分が面白いなと思ったところだけを紹介するので、気になった人はぜひ論文を読んでみてください。

論文について

Racketにmesage passingベースの並列性サポートである Place を実装する提案です。
メッセージパッシングベースの並列性サポートというと色々あるわけですが、この提案ではsequentialな処理を前提とした巨大なランタイムシステムに、後入れで並列性を(無理なく)入れるところに工夫があるようです。*1

従来型の手法としてはUnixのforkをつかう物が上げられますが、この手法だとタスク間の通信がbyte streamに制限されてしまうため抽象化の難しさや通信効率の低下などの問題が生じることがあります。

PlaceではOSによるサポートではなくランタイムによるサポートを実現することで、上記のような問題を回避しようとしています。

Placeの概要

Racketのランタイムを起動すると、まず単一のinitial placeが作成されます。 そこから追加のplaceを作成したり、メッセージを送信したりすることで並列性を実現します。

Placeは基本的には独立したRacket virtual machineであり*2GCなどもPlaceごとに実行されます。*3

メッセージはplace channelを経由してやりとりされます。place channelにはlistやpairなどの構造化されたデータを送ることができます。またplace channel自体を送信することもできるので、直接の親子関係にないplace同士も直接やりとりさせることができます。

place channelで送れる値は基本的にimmutable(一部atomicなデータのvectorなど例外あり)です*4が、この制約があるとthunkなども送れなくなります。*5

Thread等の場合は開始用のコードをthunkで指定したりできるのですが、Placeではそれができないので、Placeを新しく作成する場合は module pathで指定し、そこでexportされたmain関数を実行することでPlaceの開始処理を行います。*6

(このあとAPIの話とマクロを利用した抽象化がありますがカットするので気になる方は論文を読んでください)

実装について

Placeがない状態のRacket virtual machineは単一のgarbage collectorとOS threadから成り立ちます。 Racketにはthreadのサポートがありますが、これは並行性のサポートであり並列性でのサポートではないそうです。(concurrentなタスクに分割することはできるが、マルチコアで同時に実行させてパフォーマンスを上げるものではない)

PlaceありのRacketではOSのスレッドを複数使い、Racket virtual machineを稼働させます。 並列実行でのパフォーマンスを向上させるために、Placeは可能な限り独立・疎結合になっており、メモリ領域も分離させることで局所参照性を最大化させています。この分離があることで、PlaceごとにGCが可能になるといった点もあります。*7 PlaceごとのGCに加えて、全Placeで共有されているmaster GCというのもあり、こちらはグローバルで共有されているオブジェクトを管理しているようです。

global変数とthread local変数

Racketは10年半開発されてきており、コードベースにはたくさんのグローバル変数があります。 これがスレッド導入の障壁であり、Place導入のためにはこれの解決が必須になります。

残念ながらすごく手軽に解決する方法はなさそうで、grep とCIL解析を使用して、Racket 実装内の 719 個のグローバル変数を監査しタグ付けし、以下のように分類していったようです。

  • READ_ONLY: 読み取り専用のシングルトン・オブジェクト(scheme_true, scheme_falseなど)
  • SHARED_OK: 共有が許可されているもの
  • THREAD_LOCAL_DECL: Placeごとに局所化が必要なもの

グローバル変数を局所化させるにあたって、大きく移動させるとランタイムシステムへの修正が大きくなりすぎる*8のでOSがサポートしているスレッドローカル変数を使用してplaceローカルな変数を作ったそうです。

thread local storageの操作には pthread_get_specific()より _threadlocal とか _declspec(thread) などのコンパイラが提供しているアノテーションを使ったほうが高速らしいのですが、OSによっては(macやwinなど)ではうまく動作しないようです。 windowsではコンパイラの提供するスレッドローカルのサポートがありますが、windows XPではDLL内では使えないようです*9 macはこの論文が書かれた時点では上記のようなコンパイラのサポートが提供されていないようです。 論文ではプリプロセッサを定義して、OSごとにスレッドローカル変数へのアクセス方法を切り替えるような工夫を行っています。

GC

racketの起動時にmaster GCはリードオンリーなグローバル変数やシンボルテーブル、解決済みのモジュールpathテーブルなどを割り当てます。 上記が終わったあと、initial placeはmaster GCから切り離され、自身専用のGCインスタンスを作成することになります。 このブートストラップフェーズのあとはmaster GCは通信チャンネルや共有される値の割当などごく少量のことしか行いません。

PlaceでのGCはplaceのローカルヒープを独立して回収するか、master GCと協力してglobalなオブジェクトを回収する(=グローバルコレクション)かに二分されます。 グローバルコレクションではすべてのPlaceが一時停止しますが、基本的にmaster GCからの割当はプログラムの初期化時にほぼ全てが終わるため、大体の状況ではプログラムの処理中で発生することはあまりないそうです。*10

グローバルコレクションを開始する際にはmaster GCがすべてのPlaceに対してmutationを停止し、収集を開始するようにシグナルを送ります。 すべてのPlaceがオブジェクトにマーク付けを行ったあと、master GCが不要なオブジェクトを回収します。 PlaceのローカルGCの場合はフラグメンテーションを防ぐためにオブジェクトを移動させますが、一方でmaster GCの場合は移動させません。*11

channel

前述のplaceローカルでのGCを成立させるためにチャンネルを介したメッセージングではデータをコピーして行います。 placeチャンネルはこのプロセスを新しいメモリをorphanアロケータに要求することで開始します。 orphanアロケータはすべての割当をどのGCによっても管理されていないメモリーブロックに対して行います。

次に、placeチャンネルはメッセージ全体をorphanアロケータに割り当てられたメモリーにコピーします。 コピーが完了したあと、メッセージにはオブジェクトの参照とmaster GCによって管理されている共有オブジェクトのみが含まれることになります。 その後、送信元のplaceはこの新しいメッセージとorphanアロケータによって割り当てられたメモリー送信先のplaceへ送信します。

メッセージを受信したplaceチャンネルは、孤立したメモリーページをnursery generationとして採用し、ユーザープログラムにメッセージを返します。 nursery generationを経ても生き残ったメッセージコンテンツはplaceローカルなメモリーに再配置されます。(長さが1024byte以下の場合はnursery generationをスキップして直接ローカルアロケータにコピーするという最適化が入っているそうです。) このプロセスにより、送信側・受信側でアロケーションの調整なく非同期メッセージングが可能になります。*12

lock

上記の工夫で爆速racketが完成!と行きたいところですが、racketのGCでは mprotect() *13 がたくさん呼ばれており、これがボトルネックになることがあるようでした。

mprotectはOSのページテーブルロックを取得するため、通常のsequentialなracketで問題にならなかったmprotect()呼び出しが、placeありのracketでは並列にGCが走りlock contentionが高まり、ロック待ちでボトルネックになるという構造のようです。 この構造を回避するために、racket allocatorで大きなブロックを確保するようにすることでブロック数を削減し、結果的にmprotectの呼び出し回数を劇的に減らすようにしたそうです。

まとめ

実装には2年位かかったそうです。が、不具合などはかなり少なく実装できたそうです。 著者らが以前にランタイムシステムにconcurrencyサポートを実装した際は、数ヶ月の追加テストを行い多数のレースコンディションを発見したそう*14なので、sequentialが前提になっている巨大なランタイムに後からこのようなサポートを追加する場合はplaceのような実装方法を取ると良さそうですね。

ところでErlangはメッセージに流れるオブジェクト用のアロケーションだけ静的解析で検出して(軽量)プロセス用ヒープじゃなくて共有用ヒープにメモリ確保する。*15って書いてあったんですが、これは初耳でした。おもしろいですね。

ということで以上です。

*1:巨大なランタイムにlockを適切に入れていく作業はかなり大変なのは想像に難くない・・

*2:初期段階ではリードオンリーなコードやJITによって生成されたコードなどをplace間で共有することはないらしいですが、長期的にはやりたいとのこと

*3:こういうのがあると、全VMが止まるstop the worldとかを回避できたりするのでよいですね

*4:shared memoryなのでmutableなデータだとdata raceが発生する可能性があるので、この辺は大事ですね。

*5:thunkについては https://www.fos.kuis.kyoto-u.ac.jp/~igarashi/class/isle4-05w/text/eopl014.html などを参照

*6:なかなか豪快な作り方っぽさを感じますね。racket virtual machineの起動オーバーヘッドがどのくらいかはあまりわからないんですが、後述するmaster GCなどでの仮定などからも、起動時にまとめてplaceを作っておいて順次処理させるといった使い方が想定されていそうです。そもそもこれってconcurrentをサポートしたいと言うよりは、マルチコアなハードウェアを活かしたparallelな機構を備えたいという動機(concurrentサポート自体はすでにある)らしいので、そう考えるとplaceをたくさん動的に立てたいというシチュエーションは無いのだと思います。Erlangのようにたくさん(軽量)プロセスを立てて、たくさんメッセージを送り合うのとは思想が違うはず。

*7:(軽量)Process/ActorごとにGCというのはErlangとかPonyとかもそういう感じですね。

*8:大きな修正を入れないというのがPlace導入の最大の肝なのでここは重要

*9:vista以降なら使えるけど32bit racketはwindows xpで動作する必要があるなど歴史を感じる部分がありますね

*10:逆に言うと、そういう仕組みであることを理解して使わないとすごいことになりそう

*11:master GCが稀なのとコンパクションが不要になる程度の荒い粒度で管理されているそうなので必要なさそうですね

*12:普通に自分のplaceのGCが管理してるメモリー領域のポインタ渡すとlocal placeでGCが起きたときに死んだり、それをlockで回避しようとすると泥沼なので、それとは別などこにも所属してない領域にメモリを確保してそこでやりとりするって感じですね。

*13: mprotect()は、同一プロセス内のメモリ保護機能で、一時的にheapの特定領域をread onlyなどにすることができます。GC中にいじられないように保護してるんですかね?

*14:バグの質も異なるらしく、lockベースの実装では競合状態による見つけにくいタイミングバグ、placeのような実装では壊れた参照によるバグ(GCのタイミングでだいたい見つかる)ですぐ治るものだったそうです。

*15:The Erlang implementation employs static analysis to try to determine which allocations will eventually flow to a message send and therefore should be allocated in the shared heap.

ぼんくらITエンジニアでもYouTubeとスタサプでTOEIC 900点突破できたので勉強法をまとめていく

2020/2にbefore 600点台(正確な値は紛失)から始めて2020/9に目標(900点以上)を達成しました₍₍ (ง´・_・`)ว ⁾⁾

英語学習は最初の入門のところが割と難しいなと思ったので、やったことをまとめておきます。(なお、この記事は頑張ったから自慢したい気持ちが90%、他の人に参考になったらなという気持ちが10%で提供されています。)

ちなみに英語指導経験があるとか、すごいペラペラになったとかそういう感じではないので、近くに英語に詳しい人がいる場合はそちらの人の言うことに従うのがおすすめです。(あくまで素人がやったことが書いてあるだけ)

基本的にリスニングについてのみ書きます。

はじめに

ある日突然英語やるかーと思い立ち、勢いでスタサプTOEIC https://eigosapuri.jp/toeic/ のパーソナルコーチプランに登録しました。 コーチングプランでなにやるかについては「スタディサプリ TOEIC コーチングプラン まとめ」あたりでググると出てきます。

あとはコーチの言うとおりにやっていけば自然と目標達成できる感じなんですが、その前にちょっとやっておいたほうが良いかなと思うことがあります。

英語の音について学習する

そもそも英語って日本語と音が違うんですよみたいなことは耳にタコができるレベルで聞いたことあったけど、実際どう違うのか?を体感する機会にはあまり恵まれてこなかったので、同じ境遇の人はまずそこから勉強するのがおすすめです。

スタサプTOEICは問題量・シャドーイングのやりやすさ・動画講義の質などの点でかなりよく出来ているんですが、音声変化や母音・子音についてのコンテンツは(筆者がやっていた時代は)豊富ではないので、そこを補ってあげるとディクテーション、シャドーイング*1の効率が段違いになります。

このあたりをまず意識すると、とりあえず音声をシャドーイングしてるけど「どこに注目していいのかわからなくてただ読んでるだけ」といった状態になり時間を浪費してしまうのを防げると思います。

音声変化・ストレス編

順番でいうと子音や母音のほうが先だとは思うんですが、とりあえず登る山を見るというところで「ニック式英会話」をおすすめします。

www.youtube.com

最初に言ってる英語については「一切わからん!」って感じだと思う*2んですが、一通り解説を聞くと「まあ・・わからんでもない!」くらいにはなると思います。このあたりで、そもそも「音が変化するという知識がないから聞き取れない」という問題をまず乗り越えておき、スタサプTOEICで「変化してる音を捉えきれるようにする」ような練習を積むのがおすすめです。

とはいえ、いきなり動画を全部みても脳に入ってこないと思うので、最初はニック式英会話の↑のシリーズを5回分見るくらいがいいんじゃないかと思います。

次にストレスについてです。

ストレスってなに??って状態だったんですが、僕は「サマー先生と英会話 ! 【プライムイングリッシュ】」の下記の動画を見てイメージを掴みました。

www.youtube.com

機能語・非機能語でストレスのかかりかたが違ったりとか、弱形発音があって短く言われるぞとか、知らないと聞き取りできないというか聞き取る練習をするぞ!という気持ちになることすら不可能なので、この辺の前提知識は身につけておくとよいと思います。

ストレスのかかり方から生まれる英語のリズムみたいな観点でいうと「英語発音専門ドクターDイングリッシュ」の下記動画もおすすめです。*3

www.youtube.com

弱形発音についての動画もあります。

www.youtube.com

いきなり動画をたくさん貼ってしまいましたが、この辺の知識を得るだけでリスニング能力を上げる下地はかなり出来てくるのではないかなと思います。

なお動画だけだと全体像があいまいになるかもしれないので「英語 音声変化」など適当なワードでググってみるといくつか解説サイトがあるので、動画をある程度みたぞ!と思ったら仕上げに見てみましょう。

子音・母音編

appleのaは”あ”じゃないぞみたいなのは聞いたことがあるとおもいますが、実際そこをちゃんと勉強したことがなかったのでそちらも勉強しました。 これに関しては英語耳が良いのでぜひ読んでみてください。*4

英語耳[改訂・新CD版] 発音ができるとリスニングができる | 松澤喜好 |本 | 通販 | Amazon

英語耳知らずにシャドーイングしてた時間返してってくらい良いです。

ちなみにyoutubeでも検索するとかなり色々あります。(本のほうが網羅的に出来るので本の補完として見るのがいいかなと思いました。)

例えば「あいうえおフォニックス」は解説が丁寧なのでおすすめです。

www.youtube.com

また、「がくちゃん GACKT official YouTube」の動画も勉強になりました。

www.youtube.com

ちなみに、この辺の基本は忘れがちだったりするので、それぞれチャンネル登録してアップされた動画を継続的に見ると良いです。

英語の学習方法について学習する

スタサプTOEICではディクテーションやシャドーイングなどを行うようになっているのですが、こいつが曲者で、最初のうちは「別に繰り返そうと思えばできるけど・・・で・・・?」みたいな気持ちになりがちです。(僕はなりました)

で、これの対策としてもyoutubeを漁ると色々出てきます。

特に僕の中でわかりやすかったのが「Yumi's English Boot Camp」のこちら

www.youtube.com

動画中で言っている「英語を聞く時間を増やすだけでは足りなくて、集中して聞く・聞き取れない部分を分析する」というのがポイントです。 シャドーイングでは、聞き取れない原因になっている課題を発見する => そこを聞き取れるようにする というループがポイントなので、ただ漫然と繰り返し聞いても課題を発見できず、上達までに時間がかかる(はず)です。*5*6

長々と書いてきましたが、英語学習が自転車のペダルをこぐってイメージなら、英語の音や学習方法について学ぶのは自転車のギアを上げる作業なので、ギアを上げずにこぎ続けたり、まったくこがずにギアだけ上げようとするといったことがないようにするのを心がけると良いと思います。(伝われ)

スタサプTOEICについて

さてここまではスタサプ以外の解説が95%なんですが、実際に費やした時間としてはスタサプが95%でその他5%という感じです。

基本的にはコンテンツ通り、動画講義をみる・問題をやる・ひたすらシャドーイング*7という流れになっています。 どのくらいのペースで何をやるか?については「スタサプ パーソナルコーチプラン スケジュール」あたりで検索すると他の人の体験記などが得られるので、それを参考にすると良いと思います。

その他の使い勝手や内容とかはググってもらうとして、僕が気をつけていたところを紹介します。

時間

コーチングプランであればコーチと相談で変わってくると思いますが、僕は一日3時間やりました。

初期は平日2時間,土日で5.5時間ずつやってたんですが、土日がきつすぎて集中力が0になっていたので、朝5:30に起きて毎日3時間やることにしました。(仕事の後だと集中力がなくなってるし、早起きしてやると頑張ってる感が出てモチベーションにつながるタイプだった。)*8

実際にやる時間は、いつまでに何点になっていたいか?をベースに決めると良いと思います。 諸説あると思いますがスタサプ的には毎日3時間を2ヶ月で100点アップペースとしていて、世の中的にも200時間で100点とか言われたりしているようです。 *9また、英語がある程度話せるようになるまで1000時間などの話もあります。なぜ1,000時間の英語学習が必要なのか|【公式】TORAIZ[トライズ] - コーチング英会話スクール

こう考えると、例えば

  • ある程度話せるようになりたいから1000時間が目標。そこまで時間かけたくないから一日30分 => 2000日 = 5.5年後
  • 来年までにTOEICを300点あげたいから600時間が目標。 => 一日2時間だと300日, 3時間だと200日なので一日2時間でよさそう

など当たりをつけられるようになると思います。 とはいえ集中してやるのが前提になるので、一日10時間とかはかなりモチベーションが高くないと難しいと思いますし、個々人の学習能力や年齢*10などにもかなり依存するので本当にざっくりです。ここでは時間が短すぎると効果でるのが10年後とかになってしまうかもといったところだけ抑えてもらうと良いのかなと思います。

スタサプの学習目標の選択肢には1日30分ってのは無い*11んですが、そのくらいの時間でも意味はある気がします(逆に集中できて効率良さそう)。 ただし、英語や英語学習の前提知識(音声変化やシャドーイングのやり方)などを抑えないまま時間を投資すると、ただ早口でカタカナ英語を話してる人状態になり、全然リスニング能力が上がらないということも考えられる*12ので、そこまでモチベ高くないんだけどちょろちょろはやりたいなって人でもこの辺は抑えるようにしたほうが良いと思います。

とはいえ大学受験のおつりで一ヶ月位で普通に高得点とれたよーみたいな報告も見かけるので、この辺は本当に人それぞれかもしれません。

深さが大事

シャドーイング・オーバーラッピングは 遅いスピード で深く分析するのがおすすめです。*13 僕の場合は最初の方は速いスピードで出来たぜやったーみたいな感じでやってたんですが、それだと「実際は聞き取れてないけど文脈で埋めてるところ」とか「弱形発音で短く言われてるんだけど、元から速いから気づけ無い」などの問題が出てくるのでゆっっっっっっくりやるのがよかったです。勢いで飛ばさないの大事。

分析はどのくらいやればいいんだってところですが、僕は1文30分(設問ではなくピリオド単位での1文)以上出来ると実り多い学習になったなと感じることが多かったです。とはいえ自分でそこまで深く分析するのはかなり集中力が必要で、そんなものは無いときのほうが多いので、動画でネタを仕入れて課題を見つけやすい状態に保つのを心がけていました。

パーソナルコーチプランにすべきかどうか

以下の理由でお金に余裕があればやってみても良いと個人的には思いました。*14

  • 毎日2時間とか3時間とか英語の時間とるのは慣れないと結構大変
  • 特に最初のうちは、成功体験が無いのでモチベーションが維持しづらい
  • 毎日、このくらい勉強しましたーとか、シャドーイングしてるけど全然うまくなった感じがしないんだけど・・・みたいな自慢(?)とか愚痴(?)とかを言える人がいるのが割とやる理由になった。多分日報を送るコーチがいなかったら途中でやめてたと思う。
  • 英語を将来的に活かす場合は、(職種にもよるが)投資対効果はかなり高い部類と思われるのでパーソナルコーチプランくらいはペイするはず(と自分に言い聞かせることが可能)

終わり

ということで以上です。

勢いで書いたけどこの記事意味あるのかな🙄 って正直思ってますが、おすすめの英語動画リンク集としては意味あるかなと思ったのでそのまま投下します。

素人が書いた勉強論はあんま信用ならないですが、動画あげてる人はだいたいプロなんで動画の方は積極的に見ていくと良いと思います🙏

TOEICの次は英検一級を受験予定ですが、過去問を解いたらリスニングで余裕で落ちたので先は長そうです(◞‸◟) *15

なおこの記事はFOLIO Advent Calendar 2020 6日目として書かれました。

*1:スタサプTOEICで出てくる勉強法

*2:聞き取れるぜって人はたぶんTOEICのリスニングは余裕だと思う

*3:ちなみに挙げてる動画に出てくる人はドクターDではないです。ドクターDの動画も参考になるものが多いです

*4:ただ、母音編はそこまでわかり易くない(と感じた)ので、ひとまず子音だけ抑えてもよいかもしれません

*5:センスの化身みたいな人は別

*6:ちなみにたくさん聞いて、よく使われるフレーズを覚えるといった目的では有効だと思うので、英語を垂れ流すのに意味がないわけではないと思います。ただリスニング能力を上げるのであれば集中と分析を重視したほうがよいだろうとは言えると思います(実体験ベースではある)

*7:ディクテーションはやってたけどシャドーイングの方が効果は感じた。いくつかブログ等を見る限りこのへんは人による感じがします。

*8:ちなみにこの意識の高さはTOEIC目標達成の翌日から消え去りました・・・

*9:500->600点と800->900点は違うでしょみたいな指摘もあるようですが、学習方法をちゃんと調整できているかなどに大きく依存するとは思うのでざっくりでいいと思います。

*10:やっぱ若い方がリスニング伸びやすいとかはあるらしい

*11:カスタム目標にはある

*12:全く上がらないってことは流石にないと思いますが

*13:出典は忘れたけど何かの動画で見た

*14:でもまあ人それぞれだよね

*15:英検一級といえば単語がゲキヤバなんですが、そっちについては血反吐を吐きつつなんとか8割くらいは取れるようになりました。

Inside Fintech Meetup ~ Finatext × Kyash × FOLIO ~で発表しました

speakerdeck.com

Inside Fintech Meetup ~ Finatext × Kyash × FOLIO ~ - connpass という勉強会で発表しました。

ここ1年弱くらいずっとやってたので話すネタはいくつかあったんですが、Scala的な部分は趣旨じゃなさそうだしロボアドの仕組みを説明してもいいけどリプレースの話もしたいし・・・と、割とトピック選びの時点で難産でした。 最終的にはイベントストーミングにしたんですが、弊社イベントストーミングの話するの3回目くらいな気がしますね・・・🙄

とはいえ理解が難しい部分、知識差がある部分をどうカバーしていくか?っていうのは重要なテーマだと思うし、イベントストーミングは要件定義ではなくチームビルディングにも使えるんだぜってのは個人的には結構面白いかなと思ってたので発表できてよかったかなーと思っています。

ところで2020/09/25(金)にFOLIOでcats-effect,fs2,doobie使って証券システム作ってみた (仮)っていう発表があるので、 Scala的なところが聞きたい人はこちらもぜひご参加ください(宣伝)

scala-tokyo.connpass.com