Google Drive File Stream で mount_dfsfuse に失敗してた件

High SierraGoogle Drive File Stream をインストールしたんだけど、アプリ開始時になんかエラーがでて動かない。通知センターに「エラー起きたから同期を止めた」みたいなエラーが出てた。

~/Library/Application\ Support/Google/DriveFS/Logs/drive_fs.txt には以下のログ。

2017-12-02T17:37:42ZE [123145486962688] stderr: mount_dfsfuse: the DFSFUSE file system is not available (255)
2017-12-02T17:37:42ZE [123145488572416] mount.cc:92:Mount Could not mount fuse at /Volumes/GoogleDrive.
2017-12-02T17:37:42ZE [123145488572416] core.cc:235:MaybeUpdateExitCode Terminating with error: FILE_SYSTEM_FAILURE
2017-12-02T17:37:42ZE [123145486962688] stderr: fuse: failed to mount file system: No such file or directory

kextstat すると確かに dfsfuse は無く、どういうエラーが出てるのかわからないので強引に kextutil(8) してみた。

% sudo kextutil -v 6 /Library/StagedExtensions/Applications/Google\ Drive\ File\ Stream.app/Contents/MacOS/dfsfuse.kext
Kext user-space log filter changed from 0xff2 to 0xfff.
Kext kernel-space log filter changed from 0xff2 to 0xfff.
Kext library architecture set to x86_64.
Can't stat /AppleInternal - No such file or directory.
Defaulting to kernel file '/System/Library/Kernels/kernel'
Kext library recording diagnostics for: validation authentication dependencies warnings.
Reading loaded kext info from kernel.
(kernel) User-space log flags changed from 0x0 to 0xfff.
(kernel) Received 'Get Loaded Kext Info' request from user space.
(kernel) Returning loaded kext info.
Loaded kext info:
{
}

Kext rejected due to system policy: <OSKext 0x7f8833625760 [0x7fff86190570]> { URL = "file:///Library/StagedExtensions/Applications/Google%20Drive%20File%20Stream.app/Contents/MacOS/dfsfuse.kext/", ID = "com.google.dfsfuse.filesystems.dfsfuse" }
Diagnostics for /Library/StagedExtensions/Applications/Google Drive File Stream.app/Contents/MacOS/dfsfuse.kext:
%

"Kext rejected due to system policy" でググったら以下を確認せよ、と。

% sqlite3 /private/var/db/SystemPolicyConfiguration/KextPolicy '.dump kext_policy'
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE kext_policy ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, developer_name TEXT, flags INTEGER, PRIMARY KEY (team_id, bundle_id) );
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmioplug.17.1.2',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmx86',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmnet',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmci',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EQHXZ8M8AV','com.google.dfsfuse.filesystems.dfsfuse',0,'Google, Inc.',4);
COMMIT;

きっとこの flags=0 なのが悪いんだろうなと思って KextPolicy でググってたら、
Technical Note TN2459: User-Approved Kernel Extension Loading というページが見つかった。

結論として、 System Preferences の Security & Privacy に allow ボタンがあるので押せば動くようになりました。

% sqlite3 /private/var/db/SystemPolicyConfiguration/KextPolicy '.dump kext_policy'
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE kext_policy ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, developer_name TEXT, flags INTEGER, PRIMARY KEY (team_id, bundle_id) );
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmioplug.17.1.2',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmx86',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmnet',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmci',1,'VMware, Inc.',8);
INSERT INTO kext_policy VALUES('EQHXZ8M8AV','com.google.dfsfuse.filesystems.dfsfuse',1,'Google, Inc.',1);
COMMIT;

フレッツ小型 ONU + ヤマハ NVR510

ちょっと前の話ですが、ヤマハNVR510 を買って、フレッツの ONU小型 SFP モジュールのやつ に交換しました。

NVR510 からは onu というデバイスが見えて、 onu1 って名前のインタフェースができてます。


# show onu-module info
ONU1:
Ethernet Standard: 1000BASE-PX
Vendor Name: NTT
Vendor ID: 0x000000
Product Name:
Serial Number:

差し込むとこんな感じで飛び出し気味。

モジュールの下に2つステータス用の LED がついてます。

とくに環境に変わりはないですが、ひかり電話を後から追加した都合、今まで ONU, HGW (RT-500MI だったかな?), ルータ (RTX1210) と 3 つの機器が 1 つにまとまったので大変スッキリしました。

NVR510 は CPU0/1 の 2 つあって IIJ の DS-Lite で速度もまあまあ出てるようです。

Re: The MySQL 5.7 Optimizer Challenge

This is just a translation of my former, explanation-less post in this Apr.
It still reproduces with 5.7.7-rc. Straightforwardly I should report a bug, but I find this: http://www.tocker.ca/2015/07/15/the-mysql-5-7-optimizer-challenge.html -- I would like a polo :)

procedure

% cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"
% dpkg -l|grep mysql
ii  mysql-apt-config                    0.3.5-1ubuntu14.04               all          Auto configuration for MySQL APT Repo.
ii  mysql-client                        5.7.7-rc-1ubuntu14.04            amd64        MySQL Client meta package depending on latest version
ii  mysql-common                        5.7.7-rc-1ubuntu14.04            amd64        MySQL configuration for client and server
ii  mysql-community-client              5.7.7-rc-1ubuntu14.04            amd64        MySQL Client and client tools
ii  mysql-community-server              5.7.7-rc-1ubuntu14.04            amd64        MySQL Server and server tools
% seq 1000000 > seq.out
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.7-rc MySQL Community Server (GPL)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> use test
Database changed

mysql> create table foo1 (id int, col1 int default null, col2 int default null, primary key (id), key (col1)) engine=innodb;
Query OK, 0 rows affected (0.02 sec)

mysql> create table foo2 (id int, col1 int default null, col2 int default null, primary key (id), key (col1)) engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> load data local infile '/home/ichii386/seq.out' into table foo1 (id);
Query OK, 1000000 rows affected (7.85 sec)
Records: 1000000  Deleted: 0  Skipped: 0  Warnings: 0

mysql> load data local infile '/home/ichii386/seq.out' into table foo2 (id);
Query OK, 1000000 rows affected (2.42 sec)
Records: 1000000  Deleted: 0  Skipped: 0  Warnings: 0
mysql> explain select sql_no_cache * from foo1 where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null;
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | foo1  | NULL       | ref  | PRIMARY,col1  | col1 | 5       | const |   10 |     0.50 | Using index condition |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select sql_no_cache * from foo1 where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 | NULL | NULL |
|  2 | NULL | NULL |
|  3 | NULL | NULL |
|  4 | NULL | NULL |
|  5 | NULL | NULL |
|  6 | NULL | NULL |
|  7 | NULL | NULL |
|  8 | NULL | NULL |
|  9 | NULL | NULL |
| 10 | NULL | NULL |
+----+------+------+
10 rows in set (0.12 sec)

mysql> explain select sql_no_cache * from foo2 where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+------------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                              |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+------------------------------------+
|  1 | SIMPLE      | foo2  | NULL       | range | PRIMARY,col1  | PRIMARY | 4       | NULL |   10 |   100.00 | Using index condition; Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select sql_no_cache * from foo2 where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 | NULL | NULL |
|  2 | NULL | NULL |
|  3 | NULL | NULL |
|  4 | NULL | NULL |
|  5 | NULL | NULL |
|  6 | NULL | NULL |
|  7 | NULL | NULL |
|  8 | NULL | NULL |
|  9 | NULL | NULL |
| 10 | NULL | NULL |
+----+------+------+
10 rows in set (0.00 sec)

It use pk with foo2 of MyISAM, but not with foo1 of InnoDB, resulted with 0.12sec.

高速に並列処理: xargs -P vs parallel -j vs split -n r/

最近になって、 GNU Coreutils の split(1) に --filter ってオプションがあり、入力を並列処理する方法の1つになることを知りました*1

並列処理をしたいときに使うものとして GNU Findutils の xargs(1) -P, --max-procs (おそらく GNU 拡張) と、そのままの GNU parallel があります。サーバ管理で並列にログインしてなんかやる系だともっと多くのバリエーションが有るでしょうが、 synax sugar の域を超えないのでここでは考えません。

尤も split も本来の目的がちょっと違うので同じように比較するのはおかしいんですが、思ったより効率が良いようなので試してみました。

環境は SunOS, Xeon E5-2630 v3 @ 2.40GHz の 2 socket で 32 threads というとこです。

それぞれの実装

  • xargs
    • --max-procs の数まで fork して execvp する実装
ichii386@abby% xargs --version
xargs (GNU findutils) 4.5.14
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
  • parallel
    • 出力の整形や halt-on-error の設定ができるなど、とくに並列 ssh するときの便利スクリプト系な雰囲気です。
    • perl で書かれていて IPC::Open3 を使い SHELL 環境変数を参照する。
ichii386@abby% parallel --version
GNU parallel 20121122
Copyright (C) 2007,2008,2009,2010,2011,2012 Ole Tange and Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
GNU parallel comes with no warranty.

Web site: http://www.gnu.org/software/parallel

When using GNU Parallel for a publication please cite:

O. Tange (2011): GNU Parallel - The Command-Line Power Tool,
;login: The USENIX Magazine, February 2011:42-47.
  • split
    • 一般的な使い方は「ファイルを n 分割する」ことですが、 --filter を指定することで出力ファイルたちを open(3) するのではなく fork して SHELL を execl(3) し pipe を繋げます。
    • それゆえ xargs などと違って「最初に n プロセスだけを起動し、入力を分割して渡す」という方針。
    • -n r/N で入力を N 個の出力に round robin させる (よって入力の終端は起動時には不要)
ichii386@abby% split --version
split (GNU coreutils) 8.23
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Torbjorn Granlund and Richard M. Stallman.

ということで、ナイーブには a. を改善しようとして b. or c. になるところ、いやいやプロセス起動が無駄だろ、と思いつつ d. にするのが調整めんどいよね、というときに良いようです。

  • a. 並列度1で1の入力を処理する、を100回やる
  • b. 並列度1で100の入力を処理する、を1回やる
    • 複数の入力を一度に処理できるようにする
  • c. 並列度5で1の入力を処理する、を20回やる
    • xargs 的な方針
  • d. 並列度5で20の入力を処理する、を1回やる
    • split -n r/N --filter の方針

たんに起動するだけ

それぞれの得意分野だけ比較するのもずるいので、以下の条件で統一するようにします。

  • /bin/sh は必ず経由する
  • 入力を引数として何かを実行できる
ichii386@abby% seq 10e3 | ptime xargs -I{} -P32 sh -c '/bin/true {}'

real       10.983304378
user        8.317562721
sys        24.905662776
ichii386@abby% seq 10e3 | SHELL=/bin/sh ptime parallel -k -j 32 /bin/true {}

real       29.879385199
user       21.170876665
sys        53.838705772
ichii386@abby% seq 10e3 | SHELL=/bin/sh ptime split -u -n r/32 --filter 'while read i; do /bin/true $i; done'

real        1.055647177
user        3.119058968
sys        10.104064297

/bin/true が 10e3 回実行されるのは同じですが、こんなに差がでます。ほんとか??

素因数分解ぽい何か

openssl genrsa 32 で作った 2849443549 = 52223 * 54563 が確かにこれで素因数分解できる感を確認する。

ichii386@abby% seq 2 52223 | ptime xargs -I{} -P32 sh -c 'expr 2849443549 % {} != 0 >/dev/null || echo {}'
52223

real     1:00.233418446
user     1:00.874658739
sys      3:06.241644775
ichii386@abby% seq 2 52223 | SHELL=/bin/sh ptime parallel -k -j 32 'expr 2849443549 % {} != 0 >/dev/null || echo {}'
52223

real     2:49.511349011
user     2:08.351005238
sys      5:23.125255516
ichii386@abby% seq 2 52223 | SHELL=/bin/sh ptime split -u -n r/32 --filter 'while read i; do expr 2849443549 % $i != 0 >/dev/null || echo $i; done'
52223

real        5.541663743
user       25.044178700
sys      1:17.303706104

圧倒的すぎて不安になってきます。

まとめ

とにかく圧倒的に split が速いです。正直なんでこんな差がでるのかピンときてません (が、ちゃんと調べてません) 。

parallel なんかは親が重たい図体してるくせに安易に fork してるからってのはあるでしょうけど。なんとなく気軽に xargs 使っているなら考えなおしたほうが良いかも。

(こういう用途で) split に唯一弱点があるとすれば、起動したコマンドが exit -1 した時に異常終了できないことです。

上の素因数分解の例で言えば、xargs の場合 seq inf を入力にしつつ "(echo {}; exit -1)" すれば見つかったところで終了してくれます。それが split だと出来ない。

論理削除とオプティマイザ (のつもりだったけどただのメモ)

タイトルまで書いたけど面倒になったんでやめた。

% seq 1000000 > aho.out
mysql> create table aho (id int, col1 int default null, col2 int default null, primary key (id), key (col1));
mysql> load data local infile '/home/ichii386/aho.out' into table aho (id);

col1 が論理削除フラグだと思ってください。

mysql> select sql_no_cache * from aho where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 | NULL | NULL |
|  2 | NULL | NULL |
|  3 | NULL | NULL |
|  4 | NULL | NULL |
|  5 | NULL | NULL |
|  6 | NULL | NULL |
|  7 | NULL | NULL |
|  8 | NULL | NULL |
|  9 | NULL | NULL |
| 10 | NULL | NULL |
+----+------+------+
10 rows in set (0.13 sec)

妙に遅い。

mysql> select sql_no_cache * from aho force index (primary) where id in (1,2,3,4,5,6,7,8,9,10) and col1 is null;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
|  1 | NULL | NULL |
|  2 | NULL | NULL |
|  3 | NULL | NULL |
|  4 | NULL | NULL |
|  5 | NULL | NULL |
|  6 | NULL | NULL |
|  7 | NULL | NULL |
|  8 | NULL | NULL |
|  9 | NULL | NULL |
| 10 | NULL | NULL |
+----+------+------+
10 rows in set (0.00 sec)

期待通り。

                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "access_type": "ref",
                      "index": "col1",
                      "rows": 10,
                      "cost": 12,
                      "chosen": true
                    },
                    {
                      "access_type": "range",
                      "rows": 8,
                      "cost": 14.02,
                      "chosen": false
                    }
                  ]
                },

理由は select に col2 が入ってるのに col1 is null な ref を使っちゃうから。

なんで practical にも論理削除はやめてほしい。 orm の都合で index hinting 使えないとかあるあるなんで。