abcdefGets

ゲッツ!

Firebase SDK for javascript

Firebase SDKの使い方・注意点等について書く。

インストール

scriptタグで直接CDNから読み込むのが一番かんたん。

<script src="https://www.gstatic.com/firebasejs/live/3.0/firebase.js"></script>

バンドルしてしまう場合は

npm install --save firebase

でnpmからインストール

準備

Firebase Consoleから新規プロジェクトを作成

f:id:brn_take:20170227181124p:plain f:id:brn_take:20170227181340p:plain

コンソールから設定を取得

f:id:brn_take:20170227181559p:plain

f:id:brn_take:20170227181629p:plain

npmの人は// Initialize Firebase以下をコピー

ここまでで、こんな感じになります。

index.html

<!doctype html>
<html>
    <head>
       <script src="https://www.gstatic.com/firebasejs/3.6.10/firebase.js"></script>
       <script>
           // Initialize Firebase
           var config = {
                 apiKey: "AIzaSyD8BQ8oDDcXEmZgEWNz1KYLhBWIZDCR8aw",
                 authDomain: "test-proj-509cf.firebaseapp.com",
                 databaseURL: "https://test-proj-509cf.firebaseio.com",
                 storageBucket: "test-proj-509cf.appspot.com",
                 messagingSenderId: "107396821085"
           };
           firebase.initializeApp(config);
       </script>
   </head>
    <body>
    </body>
</html>

使う

firebaseは主にfirebaseオブジェクトのメソッドから操作する。

データベースを参照する

const databaseRef = firebase.database().ref('production/messages');

refの引数は参照する階層になる。

データベースに値が追加されたら通知する。

databaseRef.on('child_added', snapshot => {
  const value = snapshot.val();
  const key = snapshot.key();
});

child_addedキーでref以下の階層に値が追加された場合に通知が飛ぶ。
通知の引数になるsnapshotから値を取得する場合はval()メソッドで値を取得する。
もし自身のパスが取得したければ、key()で取得できる。

データベースから値が削除されたら通知する。 

databaseRef.on('child_removed', snapshot => {
  const value = snapshot.val();
  const key = snapshot.key();
});

データベースの値が変更されたら通知する。 

databaseRef.on('child_changed', snapshot => {
  const value = snapshot.val();
  const key = snapshot.key();
});

データベースの値が移動したら通知する。 

databaseRef.on('child_moved', snapshot => {
  const value = snapshot.val();
  const key = snapshot.key();
});

最初に接続した時にDBに値があれば、child_addedかvalueに通知が来る。

全てのイベントを通知する。

databaseRef.on('value', snapshot => {...});

値を追加する

基本

const newRef = databaseRef.push();
newRef.set({foo: 'bar'});

pushで新たなエントリーを生成し、setで値を設定する。

push(value: any, onComplete: () => void)

ユニークキーを生成して、そのキーで新たなエントリーを生成する。
valueを指定した場合は後述するsetも同時に行われる。
キー生成の詳細については The 2120 Ways to Ensure Unique Identifiers

set(value: any, onComplete: () => void)

現在のロケーションに値をセットする。

フィルターをかける

フィルター系で注意したいのは、firebaseは複数のフィルターを組み合わせられないという点
なので、データ構造は十分考慮する必要があるし、場合によってはjavascript側で並べ替えることも考慮した方がいい。

順序を変える。 

sqlorder by的なもの

databaseRef.orderByChild('createdAt').on(...);
databaseRef.orderByKey().on(...);
databaseRef.orderByValue().on(...);

orderByChild(propertyName: string)

指定された子要素のプロパティ値で順序を決める。
多分一番使う気がする。デフォルトで昇順になる。

orderByKey

キーでソートする。
キーに順序をもたせた場合はこれを呼ぶだけでいい。

orderByValue

値でソートする。
プリミティブが直接子要素になっている場合以外に使い道がない気がするが。

値を指定する。

子要素の値を指定してフィルターする。
このメソッドはorderByに影響を受け、orderByの指定があった場合はそのプロパティを比較に使う。
もしorderByの指定がなければ、第二引数で比較する値を指定する。

databaseRef.startAt(Date.now(), 'createdAt');
databaseRef.orderByChild('createdAt').startAt(Date.now());

databaseRef.endAt(Date.now(), 'createdAt');
databaseRef.orderByChild('createdAt').endAt(Date.now());

databaseRef.equalTo(Date.now(), 'createdAt');
databaseRef.orderByChild('createdAt').equalTo(Date.now());

startAt(value: any, propertyName?: string)

値が一致する要素から開始する。
一致しない要素は全てスキップされる。

endAt(value: any, propertyName?: string)

値が一致したら終了する。
一致するまでは全ての要素が流れる。

equalTo(value: any, propertyName?: string)

値が一致した要素のみを流す。

件数を制限する

databaseRef.limitToFirst(1000).on(...)
databaseRef.limitToLast(1000).on(...);

limitToFirst(value: number)

指定した件数を先頭から取得する。

limitToLast(value: number)

指定した件数を最後尾から取得する。

注意点・Tips等

Firebaseのイベントで気をつけなければいけないのは、初回に繋いだ瞬間全ての値が流れてくること。

キャッシュ等をしていて、差分からの値が欲しければ、最後の値をstartAt()に渡してイベントをスキップするような実装にする必要がある。
また、valueとchild_addedを一緒に指定すると、valueとchild_addedの両方に値が流れるので注意。

基本的にはvalueは使わず、child_added/moved/changed/removedをちゃんと使い分けたほうがよい。

HTML5とか勉強会「Webパフォーマンス」に参加してLTしてきた

LTしてきた。

とりあえず、早口すぎたなと思った。
時間を気にしすぎてしまったかも。

以下勉強会メモ

先入観とバイアスを考慮したWebサイトパフォーマンス改善

t.co

竹洞さん

日本の現状

世界基準

  • 表示開始時間 0.5秒以内
    • Webブラウザ上に最初の1ピクセル目が表示された時間
  • 表示完了時間 2秒以内
    • DOM Complete
    • DOM処理が終わったタイミング

アメリカのEコマース

(アメリカのEコマース)https://www.dynatrace.com/en/benchmarks/united-states/retail/ns

日本

(日本のWebサイトパフォーマンスランキング)https://www.dynatrace.com/en/benchmarks/japan/retail/ns

どのプロジェクトでも2秒切れば直帰率は50%減る。
CMOがパフォーマンスを確認する
パフォーマンスが売上に直結している。

パフォーマンスは売上を引きずる要員であり、上げる要員ではない

先入観とバイアスだらけ

最低保証パフォーマンスを規定する

寒いマンション

マンションのほうが死亡率が高い。
寒いから。寒さ・暑さ対策といえば断熱材
ほんとに?

遮熱材が入っていない。
コンクリート自体が冷たさを溜め込む 冷輻射

我々WEB業界は建築業界を責められない

この辺はたとえの話だったのだが、結構マンション・不動産の詳細な
話に踏み込んでいたので、ちょっと戸惑った。

知らないという事を認識しよう

計測してみるまでは、実際のことはわからない

Don’t guess, measure!

ボトルネックを特定せよ
早まったコンポーネントの最適化

要は何が起きてるかを理解するまでは、最適化や修正をすべきではないってこと。
憶測だけでは状況は悪化する。

非科学的手法は削除する

以下のツールは使うな!

  • Google PageSpeed Insights
    • このツールだけでは高速化できない。このツールはベストプラクティスに合致しているかどうかを判定するツール。業務では使うべきではない
  • Chromeの開発者ツール。あたりを付けるぶんには問題ない。でもこれは真の値ではない。ユーザーが何秒で見ているかの比率を見るべき
    • カバー率の問題。自分のISPがどれほどの範囲をカバーしているのか
    • カバー率(時間)の問題。自分が見たタイミングがほんとに正しいか。
    • インターネットが変わらないという先入観
  • Webpage Test
    • この計測環境の仕様を知っているか。PCのスペック

ここで使えないと言われているサービスの問題点は、パフォーマンスをある一点からしか計測していないからである。
大事なのはユーザーの環境で実際に何秒かかったのかという一点。

統計学を学ぼう!

統計的な知識でグラフを見ることでほんとに重要なことが読み取れる。

法律での瑕疵担保責任の変化

瑕疵とは?
請負側に品質保証責任があることが明記される。
品質が達成されるまでは無料で働かなければならない。

仕様の実現から目的の実現へ

今まで
ソフトウェアはPL法の対象にならない。 ハードウェアは対象

これから
ソフトウェアの請負も品質保証書が必要になる。

つまりクライアントの目的(パフォーマンスも含む)が達成されない場合、損害賠償の可能性がある。

まとめ

  • 高速化するときには先入観で見ない。
  • お金をかけてでも、製造業のような品質保証をする。

まあまあ最近のパフォーマンスAPIなど

yakura @myasaka

最近みたクライアントサイドの話

jsの比重が大きくなっている。48%ほど

パフォーマンスまわりの仕様

  • 計測関連のAPI
  • 遅くさせないための仕組み
  • スケジューリング

計測関連

User Timing

Safariにそろそろ来そう…?

Performance Observer

(使い方)https://developers.google.com/web/updates/2016/06/performance-observer

エントリのタイプもこれから増えそう

Long Tasks

長くかかったタスクを検出(50ms以上とか)

First Paint

適切なFirst Paintがどこなのか

  • FirstContentPaint
  • FirstMeaningfulPaint

人間の体感的なメトリクス

遅くさせないための仕様

Intersection Observer

scroll と getBoundingClientRectの組合せはおそい!

そこでIntersectionObserver。表示範囲との交差を検出して領域判定を必要としない。
LazyLoadingとかにも使える

CSSからのアプローチ

position:sticky

ある程度までスクロールすると、要素がfixedになる

CSS Contained

大きさが変わらない要素を宣言して高速化する

.widget {
  contain: layout style paint;
}

スケジューリング

HTTP Linkヘッダ

  • のHTTPヘッダ版
  • HTMLのパースを待たずにDL開始

Link<style.css>:rel=stylesheet

preloadヘッダ

WebフォントやCSS

requestTimingIdleCallback

アイドル時間に実行させる優先度の低いタスクを渡す。

大量の要素を高速に表示する婆バーチャルレンダリング入門

久保田 @anatoo

バーチャルレンダリングとは

speakerdeck.com

  • パフォーマンスのためのテクニック
  • ウェブページに大量の要素を高速に表示するためのテクニック

普段から使っている(react-infinite)https://github.com/seatgeek/react-infiniteとかのことだったので、
あんまメモってない。
iOSのUITableViewとかもそうだったはず。

こっからLT

WebWorker & Atomics

自分

www.slideshare.net

組織にパフォーマンスを根付かせる

speakerdeck.com

始めた経緯

どんな事を勉強していけばいいかわからなくて悩んでます。

半年くらい前に、こんな質問を新人さんにされたことがきっかけ。

パフォーマンスの勉強をやってもらうのがいいかも

ServiceWorkerのnavigation-preloadについて

ちょっとごたごたしてあまり聞けなかった。。。

まとめ

ソフトバンク本社凄くきれい。
LT5分てやっぱきついな

Typescript 2.2 変更点

Typescript 2.2がでた。

変更点が少々あるので確認しておきたい。

Mixinのサポート

遂にMixinがサポートされた。やり方が少々直感的ではないけども。

公式のサンプルコードで確認する。

class Point {
    constructor(public x: number, public y: number) {}
}

class Person {
    constructor(public name: string) {}
}

type Constructor<T> = new(...args: any[]) => T;

function Tagged<T extends Constructor<{}>>(Base: T) {
    // 今まではここでエラーになっていた。
    return class extends Base {
        _tag: string;
        constructor(...args: any[]) {
            super(...args);
            this._tag = "";
        }
    }
}

const TaggedPoint = Tagged(Point);

let point = new TaggedPoint(10, 20);
point._tag = "hello";

class Customer extends Tagged(Person) {
    accountBalance: number;
}

let customer = new Customer("Joe");
customer._tag = "test";
customer.accountBalance = 0;

上のコードのnew(...args: any[]) => TがMixinのコンストラクタとして認識され、
Tagged関数内で無名クラスでnew(...args: any[]) => Tを継承することが許されるようになった。

type Constructor<T> = new(...args: any[]) => T;

function Loggable<T extends Constructor<{}>>(Target: T) {
    return class extends Target {
        protected log(content: string) {console.log(content)}
    }
}

class Base {}

class Derived extends Loggable(Base) {
  public doSomething() {
    this.log('...');
  }
}

みたいにTrait的な感じで使える。

object型のサポート

今までのtypescriptはnumber | string | boolean | symbol | null | undefined以外にPrimitive型を持っていなかったが、
今回からobject型が追加された。object型は上記のPrimitive型以外の全てに対応する。

これも公式のサンプルだが、

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

のような感じ、要はPrimitive以外を受け付けるanyのような感じか。

new.targetのサポート

new.targetがtypescriptでもサポートされた。
あまり使う機会は無いが、例ではErrorの継承があげられている。

class CustomError extends Error {
    constructor(message?: string) {
        super(message); // 'Error' breaks prototype chain here
        Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
    }
}

ErrorだけでなくArray等の、
constructorを単純に呼び出すだけではうまく継承できないビルトインクラスを継承する場合に使う。

null/undefinedチェックの強化

式中のnull/undefinedのチェックが強化された。
以下の場合はエラーになる。

  • もし、+オペレーターのオペランドがnullableで、オペランドがstringでもanyでも無いとき。
  • もし、-, *, **, /, %, <<, >>, >>>, &, |, ^オペランドがnullableのとき。
  • もし、<, >, <=, >=, inオペランドがnullableのとき。
  • もし、instanceof の右辺がnullableのとき。
  • もし、+, -, ~, ++, -- の単項がnullableのとき。

stringをキーにしたオブジェクトにドットでアクセスできるようになった

以下のような型

interface StringMap<T> {
    [x: string]: T;
}

にたいしてドットでプロパティアクセスしてもOKになった。

var stringMap: StringMap;
stringMap.foobar; // ok
stringMpa['foobar']; // ok

jsxの子要素に対するspreadオペレーターがサポートされた。

これも公式の例を拝借

function Todo(prop: { key: number, todo: string }) {
    return <div>{prop.key.toString() + prop.todo}</div>;
}

function TodoList({ todos }: TodoListProps) {
    return <div>
        {...todos.map(todo => <Todo key={todo.id} todo={todo.todo} />)} //ここ!
    </div>;
}

let x: TodoListProps;

<TodoList {...x} />

のように、直接子要素を展開する構文がサポートされた。

jsx: react-nativeがサポートされた

これはそのまま。
react-nativeでコンパイルすると、jsx構文がそのまま残った上でjsの拡張子になる。

まとめ

Mixinが嬉しい!

WebWorker & SharedArrayBuffer & Atomics (2)

二回目です。
前回の記事はWebWorkerとSharedArrayBufferとAtomics(1)です。

Memory Model

ES2017のドラフトからMemoryModelという項目が追加された。
これはSharedArrayBufferのDataBlockに適用されるモデルで、プログラムがとりうるメモリの順序を示したものである。

ES2017ではSequential Consistency(SeqCst)かUnorderedが定義される。

Unordered

Unorderedとはメモリの順序に対して、各種スレッドが何の制約も持たいない状態である。

// main.js
sharedArrayBuffer[0] = 0;
sharedArrayBuffer[1] = 0;

// thread1.js

sharedArrayBuffer[0] = 1;
sharedArrayBuffer[1] = 1;

// thread2.js

const v1 = sharedArrayBuffer[0];
const v2 = sharedArrayBuffer[1];

console.log(v1, v2); // 1, 0

// thread3.js

const v1 = sharedArrayBuffer[0];
const v2 = sharedArrayBuffer[1];

console.log(v1, v2); // 0, 1

このように各スレッドによって値の見え方と順序は異なる。

Sequential Consistency(SeqCst)

Sequential Consistencyはアクセスの原子性に加えて、各スレッドから見たメモリアクセスも決まった順序が保証される制約である。

// main.js
sharedArrayBuffer[0] = 0;
sharedArrayBuffer[1] = 0;

// thread1.js

Atomics.store(sharedArrayBuffer, 0, 1);
Atomics.store(sharedArrayBuffer, 1, 1);

// thread2.js

const v1 = Atomics.load(sharedArrayBuffer, 0);
const v2 = Atomics.load(sharedArrayBuffer, 1);

console.log(v1, v2); // 1, 0 or 0, 1

// thread3.js

const v1 = Atomics.load(sharedArrayBuffer[0]);
const v2 = Atomics.load(sharedArrayBuffer[1]);

console.log(v1, v2); // 1, 0 or 0, 1

Sequential Consistencyが保証されている場合、thread2.jsとthread3.jsで値の見え方に差が出ることはありえない。
何故ならば、Sequential Consistencyは全てのスレッドに対して順序通りの実行結果が観測される事を保証しているからである。

RacesとDataRaces

ES2017にはRacesとData Racesという状態が記述されている。

happens-before

DataRacesの前にhappens-before状態を理解せねばならない。
happens-beforeとは以下の制約を満たす状態である。

  • EventsSet(execution)に含まれるような全てのE,Dに対して
  • E agent-order before Dならば
  • あるいは E synchronizes-with Dならば、
  • あるいは EとDがSharedDataBlockEventSet(execution)に含まれ、E.[[Order]]がInitで、EとDの領域が重なっており
    • D.[[Order]]がInitではない
    • E happens-before Dである
  • あるいは E happens-before Fを満たすようなFがあり、F happens-before Dが満たされるとき、E happens-before Dである。

これだけの説明だと非常に理解しづらいが、単純に E happens-before DとはイベントEがイベントDの前に発生する関係性である。

var x = 0;
var y = x;

ただし、一見このプログラムではx happens-before yが成り立ちそうに見えるが、コンパイラによる最適化、CPUによる実行順序の入れ替えにより、
x happens-before yを確実に成り立たせることはできない。
特にjavascriptには他の言語にある、volatile修飾子のような仕組みが無いため、よりコントロール不可能である。

Races

Racesとはプログラムが以下の状態であることである。

  • E, D2つのイベントがあったとき
  • E happens-before D、D happens-before Eを満たせず
  • EとDがメモリへの書き込みを伴うイベントで
  • EとDのメモリアドレスが重なり合うとき あるいは E reads-from D か D reads-from Eを満たすとき

これは以下のような状態である。

// thread1
sharedArrayBuffer[0] = 1; // E

// thread2
console.log(sharedArrayBuffer[0]); // D

ここではE・DともにE happens-before Dを完全に満たしていない為、Racesである。

// thread1
Atomics.store(sharedArrayBuffer, 0, 1); // E

// thread2
console.log(Atomics.load(sharedArrayBuffer, 0)); // D

この場合はAtomicsを用いてE happens-before Dを満たしているのでOK

Data Races

Data Raceは以下の状態である。

  • Races状態のE、Dが
  • [[Order]] SeqCstを持っていないか、EとDのアドレスが重なっているとき

このRaces、Data Races状態になければ Data Race Free Programe SC-DRFと呼ばれる状態である。

全体的に、Specificationからのセマンティックな処理についての話になってしまったので、少々理解しづらいが、

基本的には

  • EcmascriptにはSeqCstかUnorderedの2つの実行順があり、
  • 全ての変数アクセス・書き込み順がSeqCstであれば、DataRaceFreeである。
  • つまりSharedArrayBufferには常にAtomicsでアクセスしましょう

ってことを覚えておけばいいんじゃなかろうか。

おまけ(V8実装)

現在のV8のAtomicsの実装はruntime-atomics.ccにある。
なかの実装を見るとわかるけど、実際の処理はGCC__atomic_xxx系かVSのInterlockedXXXで簡易に実装してある。
また、isLockFreeの実装は以下のようになっていて、

inline bool AtomicIsLockFree(uint32_t size) {
  return size == 1 || size == 2 || size == 4;
}

32ビットまでの配列に対応しているようだ。

WebWorker & SharedArrayBuffer & Atomics (1)

遂にShared Memory and AtomicsがES2017のstage4に
JSの世界にマルチスレッド・共有メモリ・排他制御の仕組みが備わることになった。

Javascript/Browserにおけるマルチスレッド・並列実行

Javascriptの世界では長らく協調的スレッドと呼ばれるような仕組みで擬似的に並列実行を行っていた。
いわゆるノンプリエンプティブなスレッドである。

例えば

(function loop1() {
    console.log('loop1 start');
    console.log('loop1 end');
    setTimeout(loop1, 100);
})();
(function loop2() {
    console.log('loop2 start');
    console.log('loop2 end');
    setTimeout(loop2, 100);
})();

これはタイマーを利用した再帰処理だが、ブラウザがスケジューリングしたタイミングでそれぞれ
loop1とloop2が処理を行う。
loop1とloop2はそれぞれ非同期に実行されるが、全てメインスレッドでスケジューリングされるため、
各処理に割り込みが入ることはない。

つまり必ず

loop[1] start
loop1[1] end

の順番で出力される。

loop[1] start
loop1[2] start

とはならない。

Concurrent.Thread

Concurrent.Threadという古のライブラリがある。
このライブラリはこんなふうに使う

function hello(id) {
    document.write("[" + id + "] " + "hello,<br />");
    Concurrent.Thread.sleep(id * 1000);
    document.write("[" + id + "] " + "world!<br />");
}
Concurrent.Thread.create(hello, 1);
Concurrent.Thread.create(hello, 2);
Concurrent.Thread.create(hello, 3);

こうすると

1hello
2hello
3hello

1world
2world
3world

というまさにプリエンプションが行われたかのような結果となる。
このライブラリは渡された関数の各行をsetTimeoutでラップすることで、各ステートメントを非同期化し、
再スケジューリングすることでコンテキストスイッチを実現している。

しかしあくまでメインスレッド上で分割して実行しているため、
あくまで、並列であり並行ではない。

並行と並列の定義の違いはparallel と concurrent、並列と並行の違い
を参照

Web Worker

Web Workerというものがある。これはまさに前述の並行処理を可能にするもので、本物のスレッドである。
しかし各スレッド間はメッセージングでやりとりを行い、JSONのやり取りしかできない。

つまり処理は並列だが、各スレッドが共有する値にアクセスすることはできない。
ただ、このWokerの仕組みを採用した事により排他制御の複雑さからは逃れられている。

Shared Array Buffers

SharedArrayBufferはWebWorker間で値を共有できない問題を解決するために導入された、
Worker間をまたいだバイト配列共有の仕組みである。

しかしSharedArrayBufferをスレッド間で共有すると問題が発生する。

スレッド間可視性

// main.js
sharedArrayBuffer[0] = 1;
sharedArrayBuffer[0] = 2;

// thread.js
while (sharedArrayBuffer[0] === 1) {}
console.log(sharedArrayBuffer[0]); //A

この場合Aの値は1かも知れないし、2かもしれない。
1か2のどちらかになるだろう。

これは一例であるが、

  1. main 代入処理 sharedArrayBuffer[0] = 1
  2. thread グローバルなメモリ領域からsharedArrayBuffer[0]を読み込み
  3. thread sharedArrayBuffer[0]を読み込み
  4. main 代入処理 sharedArrayBuffer[0] = 2

といったような順序で処理が行われている場合、AのsharedArrayBufferはまだ初期化されていない可能性がある。

というようにスレッドの可視性の問題によって、また、CPU・コンパイラによる各種最適化によって
Aスレッドで更新された値がBスレッドから確実に読めるかという疑問はかなり不確定な答えになってしまう。

Atomics

これを解決するのがAtomicsである。

Atomics.store(sharedArray, 0, 1);

while (Atomics.load(sharedArray, 0) === 1) {}
console.log(Atomics.load(sharedArray, 0));

この場合、
sharedArrayBuffer間の値の読み書きの順序は整合性を持つことになる。

説明としてはこんぐらい。
基本的にスレッド間の変数の整合性・一貫性を保つのがAtomicsの役割。

Atomics API

Atomics.load(typedArray: SharedArrayBuffer, index: number): number

アトミックにtypedArrayのindexから値を取得する。

Atomics.store(typedArray: SharedArrayBuffer, index: number, value: number): number

アトミックにtypedArrayのindexにvalueを書きこみその値を返す。

Atomics.sub(typedArray: SharedArrayBuffer, index: number, value: number): number

アトミックにtypedArrayのindexの値からvalueを引きその結果を返す。

Atomics.wait(typedArray: SharedArrayBuffer, index: number, timeout: number): number

typedArrayのindexがwakeされるか、timeoutまでsleepする。
mainスレッドでは呼び出せない。

var int32Array = new Int32Array(sharedArray);
Atomics.wait(int32Array, 0, 0);
// int32Arrayの0番目の値が0の場合スリープし続ける。

Atomics.wake(typedArray: SharedArrayBuffer, index: number, count: number): void

count個のwait中のtypedArrayのindexをwakeする。

var int32Array = new Int32Array(sharedArray);
Atomics.wake(int32Array, 0, 1);
// 1つのwaitしているSharedArrayBufferのsleepを解除する。

Atomics.or(typedArray: SharedArrayBuffer, index: number, value: number): number

アトミックにtypedArrayのindexとvalueの論理和を行いその結果を返す

Atomics.add(typedArray: SharedArrayBuffer, index: number, value: numebr): SharedArrayBuffer

指定されたtypedArrayの指定されたindexにvalueを設定する。
内部的にはAtomicReadModifyWrite(typedArray, index, value, op)を使い、Atomicに値をロード、変更、storeする。

Atomics.and(typedArray: SharedArrayBuffer, index: number, value: numebr): SharedArrayBuffer

指定されたtypedArrayの指定されたindexの値と指定されたvalueの論理積とり、指定されたindexに設定する。
内部的にはAtomicReadModifyWrite(typedArray, index, value, op)を使い、Atomicに値をロード、変更、storeする。

Atomics.compareExchange(typedArray: SharedArrayBuffer, index: number, expectedValue: number, replacementValue: number): number

typedArrayのindexの値をexpectedValueと比較し、等しければreplacementValueを書き込む。
戻り値は更新前のtypedArrayのindexの値。

例.

let computedValue = 1;
let initialValue;
let totalValue = Atomcs.load(sharedArray, 0);
const append = 10;
do {
  initialValue = totalValue;
  computedValue = initialValue + append;
  totalValue = Atomics.compareExchange(sharedArray, 0, initialValue, computedValue);
  // 値がinitialValueと等しければ+10にアトミックに更新
  // 値がinitialValueと等しクない場合は、他のスレッドから更新されたので、再度initialValueをアップデートして再更新
} while (initialValue !== totalValue);

Atomics.exchange(typedArray: SharedArrayBuffer, index: number, value: number): number

typedArrayのindexにvalueを書き込み、以前のindexの値を返す。

Atomics.isLockFree(size: number): boolean

指定されたサイズがロックフリーオペレーションが可能かを返す。

まとめ

WebWorkerでShareArrayBufferを使う場合は常にAtomics経由でアクセスしたほうが良い。
もちろんしなくても良いパターンもあるが、Atomicオペレーションのコストより安全側に倒したい。

すごく適当な説明だけど、すごく疲れたから詳細はまた次回

LigShip #5に参加した

LIGShipとは

株式会社LIG様が主催のデザイナーイベント
今回のテーマは Web(デザイン) x 何か

発表

Web x インタラクション

最初の発表は LIGのデザイナーの tommy さん

netflixを例に良いインタラクションの説明
スペース・時間・アニメーションの3つのキーワードを主軸に解説されていました。

Because Recollectionというサイトの例に待ちを感じさせないインタラクションの説明
これは非常に面白かった。自分が能動的に行動していると感じさせるだけで、これだけストレスが軽減されるのは本当に素晴らしい。

全体的にインタラクションの基本を抑え、実例を交えていて非常に分かりやすかったです。

Web x グラフィックデザイン

次はLIGデザイナーの 森一機 さん

元々DTPオペレーター・グラフィックデザイナー出身らしく、 webデザイナーになって驚いたこと をベースにした発表でした。

で、Webデザイナーになって驚いたことリスト

  • Photoshopでデザイン
  • 工数で作業時間を計る -> 時間は関係なかった
  • ワイヤーフレームがある
  • 動作を考えなくてはいけない
  • 使い勝手を考えなければならない
  • 自由度がない

確かにWeb系はPhotoshop大好きだよねって思った。
あと工数の考え方がWebと紙ではだいぶ違うみたいでした。

そして、これからのWebは 広告デザイン x エディトリアルデザイン ということで

Webでの エディトリアルデザインの進化 が起きたことでWebでもエディトリアルデザインが重要になってくる

進化したもの

さらに たてよこWebアワード のようなサイトも現れ、
グラフィックデザインとWebデザインの融合が技術の進歩で可能になったよというお話でした。

Webデザイン x ソーシャルデザイン

次はストラカン田中亮 さん

そもそもソーシャルデザインとはというところからお話がスタート

ソーシャルデザインとは

社会における様々な問題をデザインで解決すること

どんなことをするのか。

  1. 情報収集し問題を調べる
  2. 目的を決める (膨大過ぎてしっかり目的を絞らなければ解決は難しい)
  3. 仲間づくり (地域の人々を巻き込まなければ難しい)
  4. つくる
  5. 実施・運用

この中でWEBサイトはプロジェクトとユーザーをつなぐ重要な媒介となり、

  • 社会課題に気づかせる(認知)
  • 社会課題に共感させる(共感)
  • 社会課題に参加させる(行動)

といった作用をもたらす。

事例紹介では ホームレスへの募金サイト を例に説明。
このサイト初めて知ったのですが、最高によくできていて、素晴らしかったです。

このサイトは

airbnb風ホームレス募金サイト
airbnbと同じ作りにし、ホームレスのねぐらを紹介する
宿泊ボタンで寄付を行う。

更に今はもう無くなってしまったのですが

Dog A Like

捨て犬と里親探しのマッチングサイトで、自分の顔と似ている犬を探してくれるという
面白いサイト。犬に対して愛情を持たせる為に自分の顔との類似マッチングという方法を使っている。

更に現在リクルートと共同で取り組んでいるのが、 Social Greeting という大学生向けのボランティアサイト

大学生にボランティアにもっと参加してもらいたい!
旅行+ボランティアでボランティアの敷居を下げる
旅行のついでにボランティアって感じでボランティアに対する抵抗をなくす。

要はボランティアって意識高くないとできないよねってのをもっと気軽にできるようにしようってことですね。
人の意識を上げるのではなく、対象の難易度を下げる。
こういうソーシャルデザインの考え方はすごく大事だと思った。

Webデザイン x ブランディング

休憩を挟んで、次は LIGのデザイナーの みやっち さん

ブランディングとは

戦略的ブランド・マネジメント

webにおけるブランディング

  • 機能ベネフィット
  • 情緒ベネフィット
  • 自己表現ベネフィット

この3つの割合

機能ベネフィット

情緒ベネフィット

自己表現ベネフィット

機能ベネフィットについては MONO AIR を例に紹介していました。
機能を中心にブランディングし、優れている点をフィーチャーする。

情緒ベネフィットはちょっとよく見れませんでした。

自己表現ベネフィットについてはToyota 86を例に紹介。
構図のダイナミックさで車の素晴らしさを、感情に訴えかける。

ブランディング事例紹介

大阪の大きなソーシャルゲーム会社A

ブランディングのためのデザイン

ターゲットとポジショニングから特徴を抽出する。

  • イキイキと働く社員
  • 大きめのグリッドとマージン
  • トップへコピー

これらをデザインに落とし込む。

まとめ

ブランディングとは企業が押し出すものではなく
ユーザーに共通の認識を持ってもらうための手法

Webデザイン x コミュニケーションデザイン

次は 猿人 より 矢崎剛史 さん

コミュニケーションデザイナーとは

ツール・場所・メディア問わず、ユーザーと対象物とのコミュニケーションをデザインする。

4p(売りて視点)

  • Product
  • Price
  • Place
  • Promotion

4c(消費者支店)

  • Consuer
  • Cost
  • Convonience
  • Communication

の結びつけをするのがコミュニケーションデザイン

電通岸勇希さんが提唱した。
恥ずかしながら初めて知りました。

コミュニケーションデザインにも変遷があったようで、

というような変遷を辿ったようです。
最近はサイネージとかつかったプロモーションも増えましたよね。
それが、まさに2.0なんですかね。

事例として、ACUVUEのプロモーションを紹介。
視力検査看板に見立てた看板で視力の重要性に気づかせる。
アキュビュー® 「スポ×コン応援団」 | ARCHIVES | アキュビュー®
35種類それぞれ作って街をジャックしたらしい(凄い)。
ソーシャルデザインをさらに進めて、実際にユーザーに働きかけるデザインでした。
ほんと感心させられる発想というか。
大変面白かったです。

まとめ

コミュニケーションデザインに大切なことは

虫の目 鷹の目

を持つこと。

全体的にスケール感のあるお話で、凄く参考になりました。
このLTを聞いて、自分はエンジニアですが、コミュニケーションデザインに関してはむしろエンジニアの方が向いていると感じました。
エンジニアもこのような大局的なデザイン感はもっていたいですね。

最後はクロストークで質疑応答しながら会話

各テーマでの参考書籍

融けるデザイン ―ハード×ソフト×ネット時代の新たな設計論

融けるデザイン ―ハード×ソフト×ネット時代の新たな設計論

ソーシャルデザイン実践ガイド――地域の課題を解決する7つのステップ

ソーシャルデザイン実践ガイド――地域の課題を解決する7つのステップ

コミュニケーションをデザインするための本 (電通選書)

コミュニケーションをデザインするための本 (電通選書)

まとめ

デザイナーの勉強会ではあったが、小手先のデザインよりも概観的な話が多かったので非常に楽しめた。
エンジニアももっと大局的なデザイン感はもたないとね。

あとLIG.incはちゃんとした会社だった。

RxjsでもbaconjsのObservable.updateを使いたい

なので実装した
rx-observable-update

インストール

いつものように

npm install rx-observable-update

jspmの人は

jspm install npm:rx-observable -o "{'main': 'system/index.js'}"

commonjsがいい人は

jspm install npm:rx-observable -o "{'main': 'commonjs/index.js'}"

使い方

使いかたはbaconjsのBacon.updateとほぼ同じ。

import {
  Subject
} from 'rxjs/Rx';
import update from 'rx-observable-update';


const source1 = new Subject();
const source2 = new Subject();
const source3 = new Subject();

update(
  1,
  source1, (oldValue, newValue) => {return oldValue + newValue},
  source2, (oldValue, newValue) => {return oldValue + newValue},
  source3, (oldValue, newValue) => {return oldValue + newValue},
).subscribe(value => {
  console.log(value);
});

source1.next(2);
source2.next(3);
source3.next(4);

一点だけ、トリガーとなるObservableを配列で受け付けない点のみ注意。

最近CRUDのSPA作るときは必須。