この世界はただのView層なのかも

量子力学は定期的に話題になるので、わりと認知度はあがっていそうです。


d.hatena.ne.jp


あらゆる物質の最小単位である素粒子は確率(波)として存在していて、人に観測された時にその存在が確定して粒子として振る舞う、という二重スリット実験とコペンハーゲン解釈はロマンしかないですし、実際に素粒子のあらゆる状態を確率として同時に持つことができる性質を利用した量子コンピューターの研究も盛んなようです。

素粒子は物質の最小単位ですが、その素粒子の存在が観測されるまで確定していないというのはなかなか受け入れ難い何とも不思議な話ですね。


それとは別に、今の理論物理学にはホログラフィック原理という理論があったりするようです。ホログラフィック原理というのは、「僕らがいつも生活しているこの3次元空間の実態は、実は全て宇宙の地平面に記述された二次元の情報だ」という感じのようなものです。

これもまた随分と突拍子のない話なのですが、

  • ある空間の内側の情報量は、空間の体積ではなく表面積で決まっていることが分かっている
  • ホログラフィック原理をベースにすると、重力などのいままで記述が難解だったこの世界の物理現象が簡潔に記述できるようになる

という感じでわりと信憑性が高まってきているようです。

そして個人的には、このホログラフィック原理を前提にすると、前述した素粒子は確率として存在していて観測された時に初めて粒子として確定するという性質がとてもしっくりきます。


この世界が何か別の情報の写像であるというのは、TVゲームの画面の中の空間にとてもよく似ています。TVゲームの画面に映る色鮮やかな世界は単なるViewにすぎず、そこに映し出される世界のもととなっているものは、メモリやディスクにひたすら0と1とだけで記述されている情報です。

このTVゲームの世界観はホログラフィック原理の世界観にとてもよく似ていますよね。

そんなTVゲームの世界では基本的にプレイヤーが観測した場所だけが画像として出力されます。プレイヤーが観測している外側の世界は画像としては確定しておらず、0と1との状態の情報としてのみ存在しています。ホログラフィック原理に従って、僕らのこの現実世界もまたただのViewであると考えるのであれば、僕らが観測していない場所にある物質の存在が確定しないというのもうなずける話ではないでしょうか。

観測範囲外にある物質をどんな状態でも取りうる確率という形で待機させておくというのは、Viewの実装としてはとても効率的に思えます。

そう考えると素粒子物理学の進歩により人類がたどり着こうとしているところは、ゲーム内のキャラクターが画面外の世界が存在していないことに気が付いてしまったという、そんな世界なのかもしれません。

帰ってきたウルトラマンの美的感覚

僕は著作権法などの知財関連の法律はまじで悪だと思って久しいのですが、そんな風に思い始めたのは創作を始めた頃で、ボカロの暴走Pさんもアンチザファンタスティックガーデンの歌詞で言っていますが「よくできた 着せ替え人形の 細部いじって 自分を主張する 歪んだカタチの器 偽者と知って コレしかないと 自分に嘘をつく」というのを肌感覚で覚えたところからでしょうか。


その後色々あってフランス現代思想にすこしふれる機会があって、「よくできた着せ替え人形説」が研究されて体系化されているのを知ってすごい感銘をうけたのですよね。特に間テクスト性(ハイパーテクスト性)とか作者の死とかはほんと面白いのですけど、そういうのに触れていくとオリジナリティという概念を再考する必要にせまられますし、著作権というのは本当いびつな形をしているし弊害が大きいなぁと思わないわけにはいかなくなってくるのですよね。
 

それはさておき、みんな著作権正しいオリジナリティあるやつがすごいっていいますが、しかし自分のことを思い返してみると、子供の頃ウルトラマン好きだったのですが一番好きだったのは「帰ってきたウルトラマン」だったのですよね。

帰ってきたウルトラマン - Google 検索


帰ってきたウルトラマンって、見た目がウルトラマンほぼそのままで、なんか胸のところのマークが2重になってるくらいの違いしかない感じなのですが、そのまさに「着せ替え人形の細部いじっただけ」な感じが子供の頃の僕にとってはすごくクールに見えたんですよ。だって他のやつらとか、やる気出しすぎてトサカ生えちゃったり角生えちゃったりでなんか大変そうじゃないですか。その点、帰ってきたウルトラマンはオリジナルの細部をすこし変えただけというシンプルさがクールなんですよ。和食もそうじゃないですか、いろいろごちゃごちゃするより素材をそのまま生かした薄い味付けの方が美味しいのです。そしてこれが重要なのですが、帰ってきたウルトラマンはオリジナルのウルトラマンよりもクールなのですよね。
 

まあつまり僕は物心つくくらいの頃からオリジナリティあふれるものよりも、優れたものに+αしてみたものをかっこいいと思っていたようだと最近気が付いたので、生まれながらこれじゃもう今更変わるのはあきらめるしかないですし、そういう着せ替え人形を上手に仕上げたものを好きでいくしかないようです。

でも大変困ったことに、著作権があると、帰ってきたウルトラマンってアウトなのが確定的に明らかじゃないですか。ウルトラセブンはもしかしたらセーフかもしれない。でも帰ってきたウルトラマンはどうみてもあかんのです。でもそれじゃ困ってしまうので著作権なくならんかな、みたいなことを思うのでした。

いじめがあった時に、いじめられっ子にも原因があるのかという

とうとつに、いじめがあった時に、いじめられっ子にも原因があるのかという話。
僕はいじめというのはイスとりゲームのようなものだと思うのです。
他の人と比べて反応が遅かったり要領が悪かったりして座れなかった人がいじめられるのです。

したがって、A君がいじめられっ子として選ばれた原因は他の人に比べてイスとりゲームが苦手だったA君にあります。
一方で、いじめが発生した原因はA君にはありません。
いじめがまず先に存在し、イスとりゲームが行われ、その結果としてA君はいじめっ子という役割に選ばれただけなのです。


いじめ問題などが起きるといじめられっ子にも原因があるだのないだのでなかなか白熱した議論になりますが、「A君がいじめられっ子として選ばれた原因」と「そこでいじめが発生した原因」とを一緒くたにしているのでカオスな感じになるので、分けて考えたほうがいいですし、前者は単に誰が選ばれるかというだけの問題ですので、本当の問題は後者なのです。

Elasticsearchのコードを読んでみる③ Bulk編

ほとんど更新と一緒だけど、運用する時はBulkのがよく使うと思うので簡単に。


curl -XPOST localhost:9200/_bulk -d '
{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_type" : "type1", "_id" : "2" } }
{ "create" : { "_index" : "test", "_type" : "type1", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1"} }
{ "doc" : {"field2" : "value2"} }
'
な感じのリクエスト。

Bulk処理

RestBulkAction : bulkリクエストを処理するクラス
- client#bulk()を実行。めぐりめぐってNodeClient#execute()が実行される。

NodeClient
- TransportBulkAction#execute()を実行。

TransportBulkAction
- Bulkリクエストに含まれるインデックス名を抜き出し、インデックス生成が必要な場合はインデックスを作成。(createIndexAction#executeをインデックス分実行。この辺りは更新編を参照。)
- インデックス生成が終わったらexecuteBulk()でBulk処理を行う。
- 対象シャードごとにbulkリクエストリストを作成し、そこにbulkのリクエストを一行ずつ分つめていく。
- 対象シャードが空ならここでレスポンスを返す。
- シャードごとにTransportShardBulkAction#execute()を実行して処理していく。

TransportShardBulkAction
- TransportShardBulkAction#execute()からTransportShardReplicationOperationAction.AsyncShardOperationAction#start()が実行される。
- 対象シャードがローカルであればbulkのThreadPool上で以降の処理を行う。他ノードであれば対象ノードにリクエストを送信する。
- shardOperationOnPrimary()にてプライマリシャードを対象にBulkリクエストを一つずつ順次処理。
- IndexShard#index()やIndexShard#delete()などで更新していく。
- プライマリの後はshardOperationOnReplicaでレプリカシャードに対して処理。
- 全てのシャードで処理が終わったらレスポンスを返却する。

Elasticsearchのコードを読んでみる② 更新編

備忘録第二だん更新処理

curl -XPUT localhost:9200/testindex/type1/_create -d '{"hogehoge" : "fugafuga"}'
という感じのリクエストをしてインデクスされるまでの更新処理。ざっくり

更新リクエスト処理

RestIndexAction : インデックスリクエストを処理するクラス
- client.index()を実行。めぐりめぐってNodeClient#execute()が実行される。


NodeClient : 各ノード内部のリクエストを実行するクライアントクラス
- TransportIndexAction#execute()を実行。


TransportIndexAction : インデックスリクエストをノード間で処理するクラス
- AutoCreateIndex#shouldAutoCreate()でインデックス作成有無を判定してインデックス作成処理を行う。
- インデックスを作成する場合はTransportCreateIndexAction#execute()を実行。
- ちなみにTransportActionクラスはexecute()のなかからdoExecute()を呼び出すようになっていて、TransportIndexActionなどの子クラスでdoExecute()に個別の処理を実装する感じの作りになっている


TransportCreateIndexAction : インデック生成スリクエストをノード間で処理するクラス
- 自ノードがマスターだったらMetaDataCreateIndexService#createIndex()を実行。
- 自ノードがマスターではなかったらマスターにインデックス生成リクエストを送信。マスターノードはTransportMasterNodeOperationAction.TransportHandlerでリクエストをうけ、リクエストをTransportIndexAction#execute()あたりから処理してMetaDataCreateIndexService#createIndex()が実行される。


MetaDataCreateIndexService : インデックスのメタ情報を設定するクラス
- 対象のIndexクラスやIndexServiceクラスを作成してMappingなどいろいろ設定する。
- アロケーションも行う。
- 一連の処理が完了したあたりでクラスターチェンジイベントを発行。各ノードがハンドルして対象シャードについてMetaDataCreateIndexServiceのcreateIndex()が呼ばれて同様に設定される。
- 成功したらListenerのonResponseを実行してTransportIndexActionまでもどる


TransportIndexAction
- 各シャードごとにドキュメント登録処理を行う。
- まずプライマリーシャードに対してshardOperationOnPrimary()が実行され、そこでInternalIndexShard#index()を実行。
- おわったらレプリカシャードに対してshardOperationOnReplica()が実行され、そこでもInternalIndexShard#index()を実行
- おわったらlistenerにレスポンスを渡す。


InternalIndexShard : シャードのインスタンスクラス
- InternalEngine#index()を実行


InternalEngine : 検索エンジンを操作する感じのクラス?
- LuceneのIndexWriter#addDocuments()を実行する。

Elasticsearchのコードを読んでみる① 検索編

検索のリクエストを受けてからレスポンスを返すまでざっくり追ってみた。
過去何回か追ってみて、時間が経つとすぐ忘れちゃうので備忘録的ななにか。


検索リクエスト処理

RestSearchAction : 検索リクエストを処理する
- client.search NodeClient#search()を実行。いろいろまわってNodeClient#execute()が実行される。


NodeClient : 各ノード内部の検索リクエストを実行するクライアントクラス
- transportAction.execute TransportSearchAction#execute()を実行している。


TransportSearchAction : ノード間で分散検索を行うためのクラス
- doExecute()が実行される。
- 検索タイプによって処理が分かれる。デフォルトでqueryThenFetch(検索後にFetch)。TransportSearchQueryThenFetchAction#execute()が実行される。


TransportSearchQueryThenFetchAction : queryThenFetchを処理するクラス
- doExecute()が実行される。
- AsyncAction#start()を実行。検索対象がなければここでレスポンス返す。


AsyncAction : 各シャードへのリクエストを行う。
- コンストラクタで対象シャードを作成
- startで各シャード毎に処理する。
- performFirstPhase() sendExecuteFirstPhase()でシャードごとに検索処理。SearchServiceTransportAction#sendExecuteQuery()を実行。


SearchServiceTransportAction : 検索通信のためのクラス
- sendExecuteQueryでクエリーを送信。
- 対象シャードがローカルノードなら自ノードのスレッドプールからスレッドを立ち上げてSearchService#executeQueryPhase()を実行。
- 対象シャー度が他ノードなら対象ノードへリクエストを送信する(TransportService#sendRequest())。 対象ノードでSearchQueryTransportHandlerでリクエストを受け、SearchService#executeQueryPhase()を実行。結果を返す。
- 検索が完了したらlistenerに結果を渡す。


SearchService : 検索とか実行するクラス
- LuceneのIndexSearcherなどつかってごにょごにょ


TransportSearchQueryThenFetchAction
- listenerで結果を受け取り、onFirstPhaseResultで処理。全ノードからレスポンスを受けたらmoveToSecondPhase()を実行して次フェース(Fetch)へ移行。
- SearchServiceTransportAction#sendExecuteFetch()を実行してFetchする。


SearchServiceTransportAction
- SearchService#executeFetchPhase()を実行する。(対象が自ノードなら別スレッド、他ノードならリクエストする)
- 完了したらlistenerに結果を渡す。


TransportSearchQueryThenFetchAction
- listenerで結果を受け取り、全シャードを処理し終えたらfinishHimを実行。
- 検索スレッドプールでマージ(SearchPhaseController#merge())。
- 結果をlistener(RestActionから受け取ったActionListener)に渡す。


RestStatusToXContentListener : RestActionで渡されるListenerクラス
- SearchResponseをいい感じにJsonに直してレスポンスを返す。


めでたしめでたし