調べたこと、作ったことをメモしています。雑多なメモはこっち:https://memo.shimazu.me/

2020年に買ってよかったもの

Amazonの購入履歴とか見ながら振り返ってみた。

小さい充電器

GaNってかいてあるやつ。小さくて持ち運びにとても便利。

Chromebook (Lenovo IdeaPad Duet)

タブレットとしてAndroidのアプリもつかえる。キーボードもスタンドもついているので、漫画リーダー+レシピリーダー+ちょっとした検索用デバイスとして活躍してる。コスパとても良かった。

食洗機(NP-TH-3)

在宅だとご飯作る必要があるけど、食洗機があると食器洗うのが自動なので洗い物のことを考えてやる気が減ることがない。食器をちょっと余分に使ったりしても罪悪感もなくとても良かった。

低温調理器真空パック器

在宅勤務だとお昼を作らないといけないけど仕事中は何作るか考える余裕ないのでいつも困ってたところ、低温調理器が来て鶏ハムを作り置きするようにしてから昼飯にあまり困らなくなった。日曜に1kg(おおよそ4枚)くらい作っておけば平日はそれ食べればだいたいいけるのでとてもいい感じ。 BONIQの加熱時間基準表をとても参考にしてる。

キーホルダーの着脱アダプタ 

自転車の鍵をキーケースにくっつけるために購入。ワンタッチでつけ外しできてとても便利。

Huawei Watch FIT

デジタルウォッチ。電池が10日(常時点灯だと5日)持つのが売り。ほんとに5日くらい持つので、ちょっとした旅行とかなら充電心配しなくていいのでとても良い感じ。コスパ

Insta360 One X2

360度カメラ。録画が基本の使い方。スノボの録画用に買ったけど、雑に写しても思ったより写りが良くて音も結構きれいに取れるのでとてもいい感じ。一緒に買った公式の1.2mの自撮り棒は使う前は少し短いかなとか心配してたけど、使ってみると丁度いい感じ。

Sony α6600

きれいに撮れるよ。最近Webカメラとしても使えるようになった。写真撮るの楽しい。 ズームレンズキットでついてくるレンズで色々撮れて楽しい。

ISUCON10 予選に出てみました

練習もしてなかったのでどうせ本戦通らんでしょ〜という感じでお昼の14時頃から気楽にやり始めたものの、思ったより手詰まりにならず常時やることがたくさんあり、最終的には時間ギリギリまでいろいろ試していました。 最後のベンチマークの結果は1768でした。

時系列を追ってやったことを書いていきます。

はじめの準備

  • vscodesshする
  • localhostでサイトが開けることを確認する
  • gitでソースを管理する
  • etckeeperをいれて/etcをgitで管理する
  • goじゃなくてnodejsを有効にする

アプリの動作確認

まずはじめにベンチマークを回し、動作確認をしました。 topを見てみたところ、mysqlが80%, nodeが20%程度CPUを使っていることがわかりました。 つまり、mysqlを別のマシンに載せ替えるだけで20%程度はスコアが上がりそうです。

また、どういう動作をするアプリなのかということをサイトを操作してみて、以下のような点を確認しました。 はじめに全体のおおよその動作を確認することで、コードを読むときに何をしようとしているのかがわかりやすくなったと思います。

  • トップページ
    • たくさん物件や椅子がでてくる
  • 椅子の検索
  • 物件の検索
    • 同上
  • 椅子の詳細ページ
    • 物件もでてくる
    • 椅子の購入操作ができる。
  • 物件の詳細ページ
  • なぞって検索ページ
    • いかにも何かありそう

結果:初回ベンチマーク484

Slow Queryの確認

mysqlが重いことがわかったので、Slow Queryのログを有効にし、サイトを手動で動かしてみました。1

  • indexがつかわれていなさそう。初期化スクリプトも確認したところ、全く設定されていなさそうだということを確認しました。
  • なぞるページを開くと大量のクエリが出る
  • なぞるページで広い範囲を検索すると0.5sとかかかる

indexを張ってみる

SQLを思い出すために、alter tableやらcreate indexやらを書いてみました。 適当に、よく使われていそうなestate.rentにインデックスを張ってみて/initializeにPOSTして動作を確認したりしていました。

結果:変化なし

なぞってページの最適化

なぞってページのクエリについてコードを見ながら確認してみたところ、以下のような動作をしていることがわかりました。

  • まず最初のクエリでbounding box内に入る全ての物件を取ってくる
  • その後、各物件に関してselectを投げて範囲内にあるかST_Containsで確認する

SQLなのに集合処理をしていない・・・

ということで、クエリを1つにしてみることにしました。 まず、latitude, longitudeをひとつのGeometry型のカラムに入れるための初期化スクリプトを1つ増やしました。

ALTER TABLE isuumo.estate ADD place_point GEOMETRY;
UPDATE isuumo.estate SET place_point = POINT(latitude, longitude);
ALTER TABLE isuumo.estate MODIFY COLUMN place_point GEOMETRY NOT NULL;

また、これを使って以下のようなクエリを投げると、1つのクエリで取ってこれるようになります。

SELECT * FROM estate WHERE ST_Contains(ST_PolygonFromText(%s), place_point) ORDER BY popularity DESC, id ASC LIMIT %d;

最後に、初期化スクリプトにSPATIAL INDEXを足しました。

CREATE SPATIAL INDEX place_point_index ON estate(place_point); 

結果: 509 (without SPATIAL INDEX), 627 (with SPATIAL INDEX)

botに503を返す

nodeのCPUがあまりそうだったので、expressでパパっとスキップするmiddlewareを書きました。 正規表現はレギュレーションのドキュメントからコピペしてそのまま貼りました。

const REGEXPS = [
  /ISUCONbot(-Mobile)?/,
  /ISUCONbot-Image\//,
  /Mediapartners-ISUCON/,
  /ISUCONCoffee/,
  /ISUCONFeedSeeker(Beta)?/,
  /crawler \(https:\/\/isucon\.invalid\/(support\/faq\/|help\/jp\/)/,
  /isubot/,
  /Isupider/,
  /Isupider(-image)?\+/,
  /(bot|crawler|spider)(?:[-_ .\/;@()]|$)/i,
]

module.exports = function (req, res, next) {
  const ua = req.get('user-agent');

  for (regex of REGEXPS) {
    if (ua.match(regex)) {
      res.status(503).end();
      return;
    }
  }

  next();
} 

結果:670

mysqlのお引越し

mysqlを別インスタンスに移住しました。

mysqld.confのbind-addressを消して、nodeサーバーのIPのためのユーザーを作ってあげればOKでした。

mysql> CREATE USER 'isucon'@'[SOURCE_IP]' IDENTIFIED BY 'isucon';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON *.* TO 'isucon'@'[SOURCE_IP]';
Query OK, 0 rows affected (0.00 sec)

+20%程度かなと思っていたので、まぁ妥当な数字が出たように思います。 CPU使用率はmysqlがほぼ100, nodejsは20%程度でした。 node側のCPUを使い切るのが目標になります。

結果:786

椅子購入クエリの最適化

なんとなく(←ひどい)「悪いUPDATEいるんじゃないかなあ」と思ったので眺めてみたところ、椅子の購入でわざわざSELECTしてからUPDATEしているのを見つけました。 stockがゼロだった場合には404を返す必要があるので、affectedRowsを使って以下のように変更しました。

    const id = req.params.id;
    await beginTransaction();
    const result = await query("UPDATE chair SET stock = stock - 1 WHERE id = ? AND stock > 0", [
      id,
    ])
    if (result.affectedRows != 1) {
      res.status(404).send("Not Found");
      await rollback();
      return;
    }
    await commit();
    res.json({ ok: true });

結果:851

mysqldumpslowの確認

ここで、次に何をするかを見極めるため、もうすこしslow queryをきちんと見てみることにしました。 mysqldumpslowをつかうとクエリごとの集計結果が見られるということだったので、使い方を調べつつやってみました。

$ sudo mysqldumpslow -s t /var/log/mysql/mysql-slow.log

Reading mysql slow query log from /var/log/mysql/mysql-slow.log                                                                                                                                                                                                                                                                                                                                                                  
Count: 829  Time=0.08s (65s)  Lock=0.00s (0s)  Rows=20.0 (16580), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                 
  SELECT * FROM chair WHERE stock > N ORDER BY price ASC, id ASC LIMIT N                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 351  Time=0.09s (31s)  Lock=0.00s (0s)  Rows=25.0 (8775), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                  
  SELECT * FROM estate WHERE rent >= N  AND rent < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 276  Time=0.11s (29s)  Lock=0.00s (0s)  Rows=20.0 (5520), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                  
  SELECT * FROM estate where (door_width >= N AND door_height>= N) OR (door_width >= N AND door_height>= N) OR (door_width >= N AND door_height>=N) OR (door_width >= N AND door_height>=N) OR (door_width >= N AND door_height>=N) OR (door_width >= N AND door_height>=N) ORDER BY popularity DESC, id ASC LIMIT N

Count: 204  Time=0.08s (16s)  Lock=0.00s (0s)  Rows=25.0 (5100), isucon[isucon]@[...]
  SELECT * FROM estate WHERE rent >= N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 144  Time=0.08s (11s)  Lock=0.00s (0s)  Rows=25.0 (3600), isucon[isucon]@[...]
  SELECT * FROM chair WHERE price >= N  AND price < N  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 111  Time=0.08s (9s)  Lock=0.00s (0s)  Rows=25.0 (2775), isucon[isucon]@[...]
  SELECT * FROM estate WHERE door_width >= N  AND door_width < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 96  Time=0.08s (7s)  Lock=0.00s (0s)  Rows=25.0 (2400), isucon[isucon]@[...]
  SELECT * FROM estate WHERE door_height >= N  AND door_height < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 144  Time=0.05s (7s)  Lock=0.00s (0s)  Rows=1.0 (144), isucon[isucon]@[...]
  SELECT COUNT(*) as count FROM chair WHERE price >= N  AND price < N  AND stock > N

Count: 171  Time=0.04s (6s)  Lock=0.00s (0s)  Rows=25.0 (4275), isucon[isucon]@[...]
  SELECT * FROM estate WHERE rent < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 72  Time=0.09s (6s)  Lock=0.00s (0s)  Rows=25.0 (1800), isucon[isucon]@[...]
  SELECT * FROM chair WHERE color = 'S'  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N 

Count: 111  Time=0.06s (6s)  Lock=0.00s (0s)  Rows=1.0 (111), isucon[isucon]@[...]
  SELECT COUNT(*) as count FROM estate WHERE door_width >= N  AND door_width < N

Count: 69  Time=0.08s (5s)  Lock=0.00s (0s)  Rows=25.0 (1725), isucon[isucon]@[...]
  SELECT * FROM chair WHERE kind = 'S'  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 78  Time=0.07s (5s)  Lock=0.00s (0s)  Rows=25.0 (1950), isucon[isucon]@[...]
  SELECT * FROM chair WHERE height >= N  AND height < N  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

Count: 96  Time=0.06s (5s)  Lock=0.00s (0s)  Rows=1.0 (96), isucon[isucon]@[...]
  SELECT COUNT(*) as count FROM estate WHERE door_height >= N  AND door_height < N

Count: 66  Time=0.08s (5s)  Lock=0.00s (0s)  Rows=25.0 (1650), isucon[isucon]@[...]
  SELECT * FROM estate WHERE door_width >= N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N

半分位の時間が

SELECT * FROM chair WHERE stock > N ORDER BY price ASC, id ASC LIMIT N

のクエリに取られていそう・・・

chairの値段順クエリ

price ASCが困っていそうだったので、indexを張ってみた。

CREATE TABLE isuumo.chair
(
    id          INTEGER         NOT NULL PRIMARY KEY,
    name        VARCHAR(64)     NOT NULL,
    description VARCHAR(4096)   NOT NULL,
    thumbnail   VARCHAR(128)    NOT NULL,
    price       INTEGER         NOT NULL,
    height      INTEGER         NOT NULL,
    width       INTEGER         NOT NULL,
    depth       INTEGER         NOT NULL,
    color       VARCHAR(64)     NOT NULL,
    features    VARCHAR(64)     NOT NULL,
    kind        VARCHAR(64)     NOT NULL,
    popularity  INTEGER         NOT NULL,
    stock       INTEGER         NOT NULL,
    INDEX price_index (price)
);

結果:1187

再度mysqldumpslow

Reading mysql slow query log from /var/log/mysql/mysql-slow.log                                                                                                                                                                                                                                                                                                                                                                  
Count: 302  Time=0.11s (32s)  Lock=0.00s (0s)  Rows=20.0 (6040), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                  
  SELECT * FROM estate where (door_width >= N AND door_height>= N) OR (door_width >= N AND door_height>= N) OR (door_width >= N AND door_height>=N) OR (door_width >= N AND door_height>=N) OR (door_width >= N AND door_height>=N) OR (door_width >= N AND door_height>=N) ORDER BY popularity DESC, id ASC LIMIT N                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 348  Time=0.08s (29s)  Lock=0.00s (0s)  Rows=25.0 (8700), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                  
  SELECT * FROM estate WHERE rent >= N  AND rent < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 165  Time=0.07s (12s)  Lock=0.00s (0s)  Rows=25.0 (4125), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                  
  SELECT * FROM estate WHERE rent >= N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 132  Time=0.08s (10s)  Lock=0.00s (0s)  Rows=25.0 (3300), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                  
  SELECT * FROM estate WHERE door_height >= N  AND door_height < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 135  Time=0.07s (9s)  Lock=0.00s (0s)  Rows=25.0 (3375), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                   
  SELECT * FROM chair WHERE price >= N  AND price < N  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 96  Time=0.08s (7s)  Lock=0.00s (0s)  Rows=25.0 (2400), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                    
  SELECT * FROM estate WHERE door_width >= N  AND door_width < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 135  Time=0.05s (7s)  Lock=0.00s (0s)  Rows=1.0 (135), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                     
  SELECT COUNT(*) as count FROM chair WHERE price >= N  AND price < N  AND stock > N                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 132  Time=0.05s (6s)  Lock=0.00s (0s)  Rows=1.0 (132), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                     
  SELECT COUNT(*) as count FROM estate WHERE door_height >= N  AND door_height < N                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 72  Time=0.09s (6s)  Lock=0.00s (0s)  Rows=25.0 (1800), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                    
  SELECT * FROM chair WHERE kind = 'S'  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 177  Time=0.04s (6s)  Lock=0.00s (0s)  Rows=25.0 (4425), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                   
  SELECT * FROM estate WHERE rent < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 66  Time=0.09s (5s)  Lock=0.00s (0s)  Rows=25.0 (1650), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                    
  SELECT * FROM chair WHERE color = 'S'  AND stock > N ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                 
Count: 96  Time=0.05s (5s)  Lock=0.00s (0s)  Rows=1.0 (96), isucon[isucon]@[...]                                                                                                                                                                                                                                                                                                                                       
  SELECT COUNT(*) as count FROM estate WHERE door_width >= N  AND door_width < N                                                                                                                                                                                                                                                                                                                                                 
                                                                                                        

次はestateテーブルに対するdoor_width/heightととrentに関するクエリが時間がかかっているっぽいですね。

door_width/heightにインデックス

とりあえず、door_width/heightにインデックスを張ってみることにしました。

CREATE TABLE isuumo.estate
(
    id          INTEGER             NOT NULL PRIMARY KEY,
    name        VARCHAR(64)         NOT NULL,
    description VARCHAR(4096)       NOT NULL,
    thumbnail   VARCHAR(128)        NOT NULL,
    address     VARCHAR(128)        NOT NULL,
    latitude    DOUBLE PRECISION    NOT NULL,
    longitude   DOUBLE PRECISION    NOT NULL,
    rent        INTEGER             NOT NULL,
    door_height INTEGER             NOT NULL,
    door_width  INTEGER             NOT NULL,
    features    VARCHAR(64)         NOT NULL,
    popularity  INTEGER             NOT NULL,
    INDEX rent_index (rent),
    INDEX door_size_index_another (door_width, door_height, popularity, id)
);

結果:1302

popularity desc, id ascとの苦闘

mysqlコマンドでいろいろcreate indexをしつつexplainを見てインデックスがうまく使われているか見てみました。

  SELECT * FROM estate WHERE rent >= N  AND rent < N  ORDER BY popularity DESC, id ASC LIMIT N OFFSET N                                                                                                                                                                                                                                                                                                                          

このクエリを最適化しようと思ったとき、rentとpopularity, あとidの3つにindexが張られていれば良さそうです。 しかし、create index idx on estate(rent, popularity, id)なんてやってもindexは使われていないようです。なんで・・・? 2

ORDER BYの最適化に関する公式のガイドを見てみたところ、どうやらDESCとASCが一緒だとだめだったりするようです。 これは最後まで解決しませんでした。。。

rent >= N and rent < N

2番めに遅いクエリの実際の値をみてみると以下のようなものでした。 SELECT * FROM estate WHERE rent >= 50000 AND rent < 100000 ORDER BY popularity DESC, id ASC LIMIT 25 OFFSET 75;

rent >= 50000 AND rent < 100000で検索をかけてみると、かなりのクエリがこのレンジのようです。 同じようなクエリが多いため、とりあえずクエリの結果をキャッシュしておいて同じクエリならそのまま返すようにすればよさそうです。

ということで、res.jsonで返すJSONmemcachedに取っておいて、もしキャッシュがあれば使うことにしました。

使うところのコードはこんな感じ。とても雑に検索の内容とqueryParamsなどをキー(memKey)に突っ込んでいます。時間がなかったことが伺えますね・・・

const memjs = require("memjs");
const client = memjs.Client.create();

...

app.get("/api/estate/search", async (req, res, next) => {

  ...

  const mGet = promisify(client.get.bind(client));
  const mSet = promisify(client.set.bind(client));

  const memKey = `${searchCondition}-${queryParams.join('_')}-${pageNum}-${perPageNum}`;
  try {
    const result = await mGet(memKey);
    if (result) {
      res.setHeader('content-type', 'application/json; charset=utf8')
      res.send(result);
      return;
    }
  } catch (e) {
    next(e);
    return;
  }

  ...

  try {

    ...

    const result = {
      count,
      estates: camelcaseKeys(estates),
    };
    await mSet(memKey, JSON.stringify(result), {expires: 60});
    res.json(result);
  } catch (e) {

    ...

公式のmemjsのドキュメントにはcallbackしか書かれていないですが、どうやらこれ、Promiseも返せるっぽいということをあとで気づきました。

あと、物件の入稿をすると結果が変わってしまうので、入稿するとキャッシュを全て破棄するようにしました。

    ...
    await client.flush();
    await commit();
    res.status(201);
    res.json({ ok: true });

結果:1727

door_width, heightのAND/ORを節約

sshでログインした直後あたり(つまり一番最初)からずっと寝ていたもう一人のチームメンバーが、終了1時間くらい前に起きてきたのでこれをお願いしました。 椅子の縦、横、高さの小さい2辺がドアに入るかを確かめればよいので、それだけをクエリに渡すコードを書いてもらいました。

結果:1768

感想

普段仕事でやっている内容ではないのでその場で勉強しながらでしたが、徐々にスコアが上がっていくのは楽しかったです。 勉強になりそうなので、過去のISUCONなども少しずつ解いていってみたいですね。 他の方のwrite upも楽しみにしています。


  1. 本当はmysqldumpslowを使ったほうが良かったと思いますが、そのコマンドの存在と使い方はコンテスト中に知りました。。。

  2. あとでDiscord見ていた感じだと、idとpopularityを1カラムにまとめてしまえば良いみたいですね。

Git管理下のファイルを自分のローカルでだけ変更してcommitされないようにする

たとえば環境変数が書かれたファイルに対して、ローカルにだけ変更をしたいときに便利な機能、skip-worktreeというのがある。

 

stackoverflow.com

 

$ git update-index --skip-worktree .dev.development # ファイルへの更新を無視する
$ git update-index --no-skip-worktree .dev.development # ファイルへの更新を反映する

僕はskip/unskipというAliasを設定して使っています。

$ git config --global alias.skip 'update-index --skip-worktree'
$ git config --global alias.unskip 'update-index --no-skip-worktree'
$ git skip .dev.development # これでファイルをスキップできるようになる

MessageChannelを使わずにService WorkerとpostMessageをしよう

Service Workerのテストを書こうとしてメッセージのやりとりにMessageChannelを使おうとしていたところ、同僚氏からこんなことを教えてもらったので備忘録代わりにメモ。

まさにコレだった・・・・

page.html

<script>
self.onload = async () => {
  const controller = navigator.serviceWorker.controller;
  if (!controller) {
    console.log('no controller.');
    console.log('registering...');
    await navigator.serviceWorker.register('sw.js');
    console.log('registered. waiting for activation.');
    await navigator.serviceWorker.ready;
    console.log('ready. please reload the page.');
    return;
  }

  navigator.serviceWorker.addEventListener('message', e => {
    console.log(`received: ${e.data}`);
  });
  navigator.serviceWorker.controller.postMessage('hoge!');
  console.log('sent: hoge!');
}
</script>

sw.js

let x = 0;
self.addEventListener('message', e => {
  console.log(`sw onmessage: ${e.data}`);
  e.source.postMessage(`${++x}`);
});

簡単!

ランダムパスワードジェネレーターをつくった

最近は基本的にログインパスワードは全部ランダムにして、Chromeに覚えさせるようにしてます。ただ、WebサービスってたまにChromeの自動生成パスワードが使えない(出てこない)ときあるじゃないですか。そういうときに適当にウェブアプリ検索してランダムパスワード生成してたんですが、なんか知らないサービス使うの怖いなっておもったので自分でつくってみました。

Random password generator

 

ソースはここで公開してます。

github.com

 

Web App ManifestとServiceWorkerつかってオフライン対応したので、スマホで開いてホーム画面追加しておくといつでも使えて便利だったりします。

 

ところで、いけてるCSSってどうやって書いたらいいんですか。ウェブよくわからない・・・(´・ω・`)

 

--

つくったのはずいぶん前なんですが、検索しても出ないのは悲しいのでとりあえず記事にしてみたっていうのは内緒。

電源入れたらRaspberryPiのターミナルがGUIで全画面表示されるようにする

概要

デモ展示では電源を刺したら自動でプログラムが起動するようにするのが失敗しないコツだと思っています。ただ、そのへんの設定をパパっとできるようにまとまってる記事とかあまり見つけられなかったので、備忘録がてら、今回行った設定を書いておきます。

今回はコンソールで日本語の表示をいい感じにしたいと思っていろいろ試しました。 その結果、GUIありでインストールして、lxterminalを全画面で自動起動した上でプログラムを走らせることにしました。もともとGUIは必要ないと思ってRasbian Streach Liteをインストールしていたので、GUIを入れるところからやりました。

GUIのセットアップ

これでGUIに必要な一式がはいります。

$ sudo apt install -y rpi-chromium-mods  python-sense-emu python3-sense-emu python-sense-emu-doc realvnc-vnc-viewer xserver-xorg xinit raspberrypi-ui-mods lightdm

インストール後、raspi-configを使ってGUIで起動するように設定すると再起動を促され、言われるがままにするとGUIが出ます。

$ sudo raspi-config

自動起動するプログラムの設定

まず適当に起動用シェルスクリプトを作ります。なんかautostartとかいうのはダブルクオートとかを勝手に展開しちゃうっぽくてシェルに渡るコマンドではうまくクオートされないという問題に悩みました。 ここではしょうがないのでターミナル起動用とターミナル内で実行するスクリプトの2つスクリプトを作ります。

/home/pi/autostart.sh

#!/bin/bash
lxterminal -t "Title for the demo" -e /home/pi/autostart_terminal.sh

/home/pi/autostart_terminal.sh

#!/bin/bash
while :
do
  echo "Hello world!"
  # 実行したいコマンド
done

次に、起動時に自動で実行するように設定します。

$ vi ~/.config/lxsession/LXDE-pi/autostart

なかみはこんな感じ。はじめの2つは消しちゃってもいいですが、そのままにしておけばデスクトップが普通に起動するので、いざというときにマウス挿してパパっと復帰できると思います。

@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
# @xscreensaver -no-splash
# @point-rpi

@xset s off
@xset -dpms
@bash /home/pi/autostart.sh

lxterminalを全画面で起動する

$ vi ~/.config/openbox/lxde-pi-rc.xml

下の方にある<applications>を探して、その中にこんなものを置きます。

<application class="Lxterminal" name="lxterminal">
        <fullscreen>yes</fullscreen>
        <!--<maximized>yes</maximized>-->
</application>

fullscreenをyesにするとターミナルの真っ黒画面が全画面で出るのであたかも普通のCUIのコンソールのように見えます。 maximizedをyesにするとターミナルのタイトルが普通に見えるので、その場合にはlxpanelやらpcmanfmやらはコメントアウトしたほうがよさそうです。

ここまでで自動起動の準備はOKです。

日本語を出せるようにする

まずフォントを入れます。 たとえばこのへんとかからNoto Sans CJK JPとか落としてきて入れるとよさそうです。

$ mkdir ~/.fonts
$ cd ~/.fonts
$ wget https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip
$ unzip NotoSansCJKjp-hinted.zip

つぎに、lxterminalで使うフォントやらなんやら変えましょう。デモの場合は文字が大きい方が見栄えがよいので、文字も大きくします。また、スクロールバーやメニューバーも消すと良いでしょう。 以下のように設定を変更しました。(これら以外はそのまま)

~/.config/lxterminal/lxterminal.conf

fontname=Noto Sans Mono CJK JP 16
hidescrollbar=true
hidemenubar=true
hideclosebutton=true
hidepointer=true

さいごに、ロケールを変えます。raspi-configでLocalization OptionsからChange Localeを選んで、ja_JP.UTF8とかを選択すると良いと思います。

$ sudo raspi-config

ここまででターミナルに日本語が出るようになっていると思います。

カーソルを消す

unclutterを入れておくと、操作がないときにカーソルが消えます。デモするときに邪魔なカーソルが必要なくなるのでとても便利です。

sudo apt install unclutter

また、unclutterを自動起動するために以下を~/.config/lxsession/LXDE-pi/autostartに追記します。

@unclutter

最後に再起動したら完成です。

さいごに

意外と自動でGUIのプログラムを起動するための手順をまとめた記事がなかったので今回まとめてみました。デスクトップ環境のシステム、あまり良くわからない・・・。 こうすると良いよ!みたいなコツとかあったらぜひ教えてください。

デスクトップPCを買ったメモ

友達が自作PC組みたいというので下調べしてたらだんだん本気になってきてしまって、お買い物当日につい手が滑って買ってしまった・・・! ということで、構成とかを備忘録的にメモしときます。

アキバでお買い回り

ひたすら歩いて回ってつかれた。。。 もしこれを見て買う人がいたら、ぜひともはじめにツクモで見積もりもらうことをオススメします・・・!(くっそ暑い中歩くのしんどい) あとケース運ぶのはとてもつらいです。車あらかじめ用意するのがおすすめです。お店から車までちょっと運んだだけなのに、2日たったけどまだ筋肉痛です。

  1. TSUKUMOパソコン本店で一通り見る
  2. パソコン工房で価格調査
  3. 昼飯くいつつ作戦会議
  4. TSUKUMO eXで友達のキーボードとマウスを選ぶ
  5. TSUKUMOパソコン本店に戻って見積もりをしてもらう
  6. パソコン工房で安いものは買う(友達がSSDと電源買ってた)
  7. TSUKUMOに戻って残りを買う(僕はここで全部購入)
  8. タイムズで車を借りる
  9. 買ったものを全部車まで持っていく(ここで筋肉痛)
  10. 帰宅(家までつれてってもらった、ありがとう)

買ったもの

こんな感じのパーツを買いました。 価格は購入時(2018年8月26日)のものです。

項目 パーツ(メーカー) 価格(税込) 備考
CPU Core i7 7820X (intel) 69098円 8コア16スレッド
クーラー H110i (Corsair) 15573円 簡易水冷, 14cmファン*2, 光る
マザボ X299 Taichi XE (ASRock) 39938円 X299, 無線LAN+BT, LAN2ポート, 電源強そう, 光る
メモリ CT2K8G4DFS8266 (Crucial) 18878円 * 2 8GB*2 * 2
SSD SSD 960 EVO 1TB (SAMSUNG) 36800円 M.2 NVMe 1TB 読み出し3,200MB/s 書き込み1,900MB/s
ケース MASTERCASE MC600P (Cooler Master) 21384円 デカい, 14cm * 2が上部に入る, 光る
その他 HM-21 (Ainex) 734円 M.2 SSDヒートシンク
その他 HT-13 (Ainex) 626円 M.2 SSDシリコーンパッド
合計 221910円 実際には保証で+4320円、割引で-1000円され、ポイントが4000くらいついた

これにもともとつかってたマシンから引っこ抜いた以下のパーツをつけました。

項目 パーツ 備考
電源 玄人志向の650W 4~5年くらいつかった気がするけどまだしばらくがんばれ
グラボ GTX650 LP(ZOTAC) 同じく5年つかってる?RTX20xxが出る(そして価格が落ち着く)まではがんばれ
SSD 480GBとかのやつ 去年くらいに買った気がするけど、調子わるい。コピーするまで待って。
HDD 2TBの適当なやつ いつから使ってるのかもよくわからない子。ガンバッテ

なんで7820X? もうすぐ新しいのでるよね?てかRyzenじゃないの?

買いたいときに買うべき!!! という信念に基づいて買っちゃいました。グラボは今持ってるので我慢したので許して。 SpectreとかMeltdownの対策がなされた8コアi7がZ370とかで秋に出るという噂もあるので、良心が残ってる人はそちらを買いましょう。

あとRyzenにすべきかCore i7(もしくはi9)にすべきかもとても悩みました。 決め手はThreadripperを組もうと思うと結局マザボが同じくらい高い上にCPUはもっと高いという点です。Ryzen7 2700Xでも良かったのだけど、シングルスレッド性能とか考えたら7820X買ってもいいかな・・・という気持ちになってきて、これくらいがバランス良いのではという判断をしました。

この子、光る・・・!

もともと安いマザボつかってたので、いいやつはこんなにヒートシンクついてるのか・・・!ごつい・・・!ととても感動してしまいましたw

f:id:amiq11:20180828223459j:plain
ごついマザボ

あとこれ光るんですよ。

f:id:amiq11:20180828223745j:plain
光るクーラーとヒートシンク
ケースも光るんですよ。

f:id:amiq11:20180828223837j:plain
光るケース

光るのたのしい・・・!!!