Windows@i386でのatomic 64bit store

Windows@i386でのatomic 64bit store。_InterlockedCompareExchange64を使ったほうがいいのかな?だいたい、ちゃんと動作してるのかしら…ツッコミ求む。

#include <windows.h>
#include <stdio.h>

#define int32_t INT32
#define uint32_t UINT32
#define int64_t INT64
#define uint64_t UINT64

void
atomic_set_64bit(uint64_t *p, uint64_t v)
{
  uint32_t v1, v2;
  v1 = *(((uint32_t *)&(v))+0);
  v2 = *(((uint32_t *)&(v))+1);
  __asm {
  _set_loop:
    mov esi, p
    mov ebx, v1
    mov ecx, v2
    mov eax, dword ptr [esi]
    mov edx, dword ptr [esi + 4]
    lock cmpxchg8b qword ptr [esi]
    jnz  _set_loop
  }
}

int
main(int argc, char *argv)
{
  uint64_t i = 0x0123456789abcdefULL, j = 0xfedcba9876543210ULL;
  printf("%08llx\n", i);
  printf("%08llx\n", j);
  atomic_set_64bit(&i, j);
  printf("%08llx\n", i);
}

【指令】Brianを捕獲せよ

ほぼ私信のようなエントリです。


やっと以下のバグが直って、個人的にはほっとしているところのlibmemcachedです。

libmemcached-rubyMEMCACHED_BEHAVIOR_CACHE_LOOKUPSフラグを「有効」にしていて、このパッチなしでは動かないという悲しい状態でした。libmemcachedもlibmemcached-rubyもどっちもどっちという感じですが…


今、Groongaのmemcached binary protocol互換サーバのデバッグ中です。だけれども、binary protocolのドキュメントだけでは実装ができません。

たとえば、キーがすでに存在してaddが失敗したときに、「Key exists」を返せばいいのか、「Invalid arguments」を返せばいいのか、「Item not stored」を返せばいいのかこのドキュメントだけではわかりません。


こういうときは、実装を見るのもよいですが、元となったテキストプロトコルを参照するとよいでしょう。

を見ると…

  • "NOT_STORED\r\n" to indicate the data was not stored, but notbecause of an error. This normally means that thecondition for an "add" or a "replace" command wasn't met.

ふむ。ということは、キーがすでに存在してaddが失敗したときには「Item not stored」を返すとよさそうですね。
さっそく実装、そしてlibmemcachedを使ってテスト… むむむ、プロトコルエラー!?なんでだなんでだ。

    switch (header.response.status) 
    {
    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
      rc= MEMCACHED_NOTFOUND;
      break;
    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
      rc= MEMCACHED_DATA_EXISTS;
      break;
    case PROTOCOL_BINARY_RESPONSE_E2BIG:
    case PROTOCOL_BINARY_RESPONSE_EINVAL:
    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
    default:
      /* @todo fix the error mappings */
      rc= MEMCACHED_PROTOCOL_ERROR;
      break;
    }

んぺぺ!(舌を噛み切る


というわけで、今週MySQL U.C.にいく人はBrianを捕まえてここの部分を実装させてきてください!
絶対だぞ!
あとbinary protocolのドキュメントに、どんなエラーのときどんなコードを返せばいいかを記述するのもヨロシク。

ニコニコ大百科のアーキテクチャ

Twitter
mongrelP: @tasukuchan グニャラくーん、ニコ百の鯖がEeePCという話が持ち上がってますがただの監視用ですよね(しんぱいそうなめでみている)

ニコニコ大百科アーキテクチャについてメモしておきます。


本当は、このネタでRuby Kaigiに申し込もうと思ったけど、すっかり忘れていたのでエントリを起こしておきます。Rubyあんま関係なかったし。

全てのリクエストを受付、セッション情報も保持するEeePC

次世代サーバプラットフォーム EeePC

ニコニコ大百科宛ての全てのリクエストは、全てEeePCに送られます。
実物の写真を載せておきます。

EeePCは2台稼動しており、1台はホットスタンバイです。


EeePCは、SSDUPSを備えた次世代サーバプラットフォームです。
メンテナンスの際、キーボードやモニタをつなぐ必要もありません。
また、各種Linuxの導入情報が充実しています。
メモリ増設などを行っても5万未満で調達を行うことができます。
消耗品として扱えるため、減価償却の必要もありません。
ラック内占有体積も少ないです。
というわけで、サーバにオススメだと思うのですが、あんまり受け入れられないんですよねー…

        ____
       / \  /\ キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \   <EeePCは、SSDとUPSを備えた
    |      |r┬-|    |      次世代サーバプラットフォーム
     \     `ー'´   /

     クスクス  ___
       /      \
      /ノ  \   u. \ !?
    / (●)  (●)    \
    |   (__人__)    u.   |
     \ u.` ⌒´      /
    ノ           \
  /´               ヽ
 |    l              \
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))

ワラワラ
         ____
       /      \!??
      /  u   ノ  \
    /      u (●)  \
    |         (__人__)|
     \    u   .` ⌒/
    ノ           \
  /´               ヽ
 |    l              \
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))

注意点として、

  • メモリは増設する。
  • LANも必要ならばUSBで増設する。
  • ログ関係はほとんど止めておく。
  • ext3だったら、noatimeを設定しておく。
  • 液晶のバックライトは消しておく。
  • どうしてもファイルに何かを一時的に書き出したいときには、tmpfsを使う。

って感じでしょうか。
あとは、最近リリースされたLinuxディストリビューションならすんなり導入できるでしょう。


このEeePCは、PLANEXのUSB LANコネクタを付けてあります。
Amazonで3,000円くらいで買いました。
メモリも、EeePC用のテキトーなのを数千円で買いました。

EeePC上で動いているサービス

LVSフロントが後ろに控えるWebサーバにリクエストを振り分けます。Webサーバとは、USB LANケーブルを通じて内側のLAN経由で接続されます。また、Webサーバはセッション情報をはじめとしたデータを、memcached互換サーバであるrepcachedに保存します。


repcachedは、弊社で開発しているgroongaに置き換え予定です。groongaでは、memcachedのバイナリプロトコル互換のサーバ機能を有します。(casとかflagsも対応する)

安価だがバランスのとれたPowerEdge 860

Webサーバ

Webサーバは、DellPowerEdge 860です。もちろん10万円未満で調達したものです。10万超えると、消耗品じゃなくなって減価償却必要になっちゃうからです。OSは、Debianのtestingです。Webサーバは3台存在し、LVSフロントからリクエストが振り分けられます。

httpdは、lighttpd 1.4.19です。mod_nicodhという、ニコニコ大百科専用のlighttpdモジュールを組み込んでいます。mod_nicodhは、C言語で簡単なアクセスハンドリングなどを行うモジュールです。ニコニコミュニティ掲示板の認証なども、mod_nicodhで処理します。


ニコニコ大百科は、ほとんどのコンテンツが静的になるように注意深く設計してあります。動的な要素が欲しい場合でも、Cookie/AJAXなどを用いてローカルで動的にページを生成できるようにします。たとえば、ニコニコ大百科の右メニューはログイン時・非ログイン時で表示が変わりますが、これはCookieの「login」という値を見てブラウザ側が動的に生成します。


静的なページは、ファイルとして保存されています。lighttpdは、そのファイルをそのまま返したり、gzip圧縮したりして返します。非常にシンプルで、かつパフォーマンスも悪くありません。


静的なページがファイルで保存されていなかったり、全体が動的なページがリクエストされたりした場合には、mod_nicodhで判定を行い、FastCGI経由でRubyに処理を渡します。FastCGIは、プロセスがWebサーバと分かれるのでハンドルしやすいです。ただ、プロセスが複数立ち上がるので、mmapなどをして論理空間・物理空間の浪費を防ぐ必要があります。


ニコニコ大百科Rubyを使って構築した、と言うと「Railsなんですね〜」とよく言われます。しかし、Railsは使っていません。ニコニコ大百科専用に、テキトーなフレームワークを書き起こしました。


FastCGIのハンドリング部分は、fcgiモジュールを使って書いています。また、Ruby標準のcgiモジュールは使わず、桑田誠さんがリライトしたcgi/cgiextモジュールを改造して使っています。テンプレートエンジンは、桑田誠さんのErubisを使っています。O/Rマッパは、テーブルごとに手で書いています。今であれば、FastCGIのハンドリング部分はRackを使いたいところですね。


ニコニコ大百科には、キーワードの自動リンク機能があります。以下のエントリにもあるように、Sennaは高速にキーワードの自動リンクを生成することができます。

キーワードリンクを行うRubyモジュールをC言語で書いて、利用しています。


静的なコンテンツで、キャッシュファイルが存在しない場合には、それを生成します。次回から、同じコンテンツに対するリクエストはlighttpdのみで処理されます。


Rubyを用いたのは、当時Rubyをほとんど使ってなかったので復習のために使いたかったのと、同僚にRubyが書ける人がいたからです。Rubyは遅いといわれますが、実用上困っていません。遅い部分は、C言語で書いたlighttpdのモジュールやRubyのモジュールが処理しているためです。むしろ、Hpricotのメモリリークや、libxml-rubyメモリリークやバグや仕様変更、libmemcachedのRubyバインディングの挙動に悩まされました。今だったらNokogiri使えっていう話なんでしょうけど…


ちなみに、webサーバの種別は、Apache Baseball Armyにしてあります。

DBサーバ

DBサーバも、DellPowerEdge 860です。もちろん10万円未満で調達したものです。OSは、FreeBSD 7.0です。弊社では、多くのデータベースサーバがFreeBSDで稼動しています。RDBMSは、MySQL 5.0 + Tritonnを使っています。マスタ1台+スレーブ1台の構成です。


SELECTを含めた、ほとんどのリクエストは「マスタ」に対して行われます。Webサーバでは、生成したhtmlなどを静的なファイルでキャッシュするため、マスタに対してリクエストを送ってもパフォーマンス上全く差し支えないし、レプリケーション遅れを気にする必要がないからです。


スレーブのみに、全文検索用のインデックスを付与したテーブルが存在します。スレーブは、主に全文検索クエリ用に用いています。


「データベースにリクエストが届いた時点で負け」という思想で、データベースについては目立ったチューニングは行っていません。負荷的にはまだ余裕があります。

APIサーバ

APIサーバは、libeventのevhttpというWebサーバ機構を用いて全てC言語で書かれています。Sennaとlibmysqlにリンクしています。APIサーバは、物理的にはWebサーバと同じです。ポートを分けています。


ニコニコ動画watchページでは、動画タイトルとタグの横に「百」「?」というマークが出ます。動画のタイトル/タグそれぞれ1つずつに対して存在するかどうか確認するリクエストが行われます。ニコ動のwatchページのPVの数倍のリクエストが来ることになります。


その他、ニコニコ動画の検索ページに大百科の記事のサマリーを出したり、ニコニコ市場に大百科の記事を出したり、さまざまなAPIを実装しています。


昔のバージョンのlibeventでは、evhttpが高負荷時に挙動が怪しかったです。というわけで、evhttpを使って書いたWebサーバに対して、リバースプロキシとしてVarnishでキャッシュを行っています。Varnishでは、これまたC言語を用いて拡張を行っています。


Varnishのキャッシュサーバは2台存在します。これもまた、DellPowerEdge 860で、OSはFreeBSDです。キャッシュサーバは同僚に書かせました。


現在のevhttpは高負荷時の挙動が安定してきているので、直にリクエストを受けてもいいのかもしれません。

まとめ

EeePCすばらしい。

groongaデータベースAPIについて概説

groongaにおいて、データベースを扱うためのAPI群について概説します。
groongaは、RDBMSでいうところのテーブル・カラムを扱うAPIを提供します。
テーブルは、内部的にハッシュテーブルもしくはパトリシアトライが基となっています。


それぞれの要素について、どのような操作が行えるかを説明します。

grn_hash

grn_hashとは、以下の操作を行えるAPI群です。

  • 任意のkeyを指定したデータ保存
  • 任意のkeyを指定したデータ取得
  • 任意のkeyを指定したデータ削除
  • カーソルを用いた、全てのkey/valueの取得・設定・削除

内部の実装は、ハッシュテーブルです。
メモリ上に作成することも、ファイルとして作成することもできます。


いわゆる*DBMと同等のことができます。
Tokyo CabinetでいうところのTCHDBですね。

grn_pat

grn_patとは、以下の操作を行えるAPI群です。

  • 任意のkeyを指定したデータ保存
  • 任意のkeyを指定したデータ取得
  • 任意のkeyを指定したデータ削除
  • 与えられた文字列内で、最左最長一致するkeyの検索
  • 与えられた文字列と前方一致するkey群の検索
  • 与えられた文字列と後方一致するkey群の検索
  • 与えられた文字列と前方最長一致検索するkeyの検索
  • カーソルを用いた、全てのkey/valueの取得・設定・削除

内部の実装は、パトリシアトライです。
メモリ上に作成することも、ファイルとして作成することもできます。


groongaは、全文検索を目的に開発されています。
Sennaの時代から、全文検索の語彙表を表現するためにパトリシアトライを用いてきました。
ハッシュテーブルとは異なり、keyの前方一致検索や前方最長一致検索を行うことができます。


内部的に半無限文字列をパトリシアトライに追加するオプションがあります。
このオプションを付与すると、
keyの前方一致検索だけでなく、後方一致検索を行うことができます。


「与えられた文字列内で、最左最長一致するkeyの検索」を用いることによって、
はてなキーワード自動リンク付与のような処理を行うことができます。

grn_table/grn_column

grn_tableとは、以下の操作を行えるAPI群です。

  • 任意のkeyを指定したレコード検索・作成・削除
  • 任意のkeyと前方最長一致するレコード検索・作成・削除(オプションによる)
  • カーソルを用いた、全てのレコードの取得・削除
  • 任意の名前と型を持ったgrn_columnの作成・取得
  • 任意のカラム値を用いたソート・上位n件取得
  • 任意の外部参照テーブルのカラム値(多重参照も可)を用いたソート・上位n件取得
  • 任意の関数を用いたソート・上位n件取得
  • 任意のカラム値を用いたグループ化
  • 任意の外部参照テーブルのカラム値(多重参照も可)を用いたグループ化
  • 任意の関数を用いたグループ化
  • テーブル間での和・差テーブルの取得
  • 全データの削除
  • レコード数の取得

grn_tableの実装は、grn_hashもしくはgrn_patを拡張する形で行われています。
メモリ上に作成することも、ファイルとして作成することもできます。


grn_columnとは、以下の操作を行えるAPI群です。

  • 値の取得・設定
  • grn_columnが転置インデックス型の場合、インデックスの更新
  • 属するgrn_tableの取得

grn_columnの内部の実装は、固定長配列・可変長配列・grn_table・転置インデックスのいずれかです。
メモリ上に作成することも、ファイルとして作成することもできます。
たとえば、ファイルとして作成されたgrn_tableに、メモリ上の一時的なgrn_columnを付与することができます。


grn_tableとgrn_columnについては、
RDBMSでのテーブルを想定していただければイメージがわきやすいと思います。


テーブルにおいて、1つのレコードはただ1つの値を保持することができます(key-value store的な感じ)。
また、1つのレコードは、複数のカラム(grn_col)を持つことができます(RDBMS的な感じ)。
key-value storeの1つのkey-valueペアに対して、カラムが複数個くっついているイメージを持ってください。


grn_hashやgrn_patとは異なり、
ソートやグループ化、集合演算などを行うことができます。
その場合、任意のカラムや関数でソートやグループ化を行えます。


grn_columnは、他のgrn_tableのレコードへの参照保持することができます。
いわゆる外部参照キーを保持するイメージを持ってください。
外部参照先のgrn_tableのカラムを用いたソートやグループ化を高速に行うことができます。


grn_columnは、転置インデックスを保持することができます。
転置インデックスを用いて、高速な全文検索を行うことができます。
詳細については、別稿で述べます。


groongaのmemcachedバイナリプロトコル互換実装では、
flagsやexptime、casなどの値を保存するためにgrn_columnを用いています。

サンプルコード

groongaパッケージのexampleディレクトリに、kv.cというソースコードがあります。
これは、上記のそれぞれのAPIを用いて、
key-valueの保存・参照を100万回行うサンプルプログラムです。


kvを起動すると、以下のようにusageが表示されます。

usage: kv dbpath [put|get] [col|table|hash|pat|ql] [value_size]

第1引数に、データベース名を指定します。
第2引数に、データの保存ならput、データの取得ならgetを指定します。getの場合には、1度putを行う必要があります。
第3引数に、groongaが持つAPIセットのうちどのAPIセットを用いるかを指定します。
第4引数に、保存する値のサイズを指定します。


このサンプルコードを読めば、
上記の構成部品についてごく基本的な使い方をマスターすることができます。

まとめ

groongaでは、さまざまなデータ構造に対応したAPIセットがあります。

  • keyをハッシュテーブルで保持するgrn_hash
  • keyをパトリシアトライで保持するgrn_pat
  • keyをgrn_hash/grn_patで保持し、任意個のgrn_columnを持つことができるgrn_table

これらのデータ構造は、メモリ上に作成することもファイルに保存することも可能です。


grn_hashは気軽なkey-value storeとして用いることができます。
grn_patはkeyの前方一致・後方一致が行えるkey-value storeとして用いることができます。
grn_tableは、grn_hash/grn_patを拡張したものです。ただ1つしか持てないvalueに加えて、複数個のcolumnを保持することができます。
またgrn_tableは、grn_hashやgrn_patにないソートやグループ化機能を備えます。

全文検索エンジンgroongaをテストリリースしました。

全文検索エンジンのgroongaをテストリリースしました。

本日開催された、key-value store勉強会で発表させていただきました。


今まで、Sennaには

  • Tritonn経由で使った場合、MySQL側のインデックスとの併用が難しく、Senna本来のパフォーマンスが発揮できなかった。
  • 従来のインターフェースでは、トークナイザの切り替えなどの柔軟性がなかった。

といった問題がありました。


groongaは、それに対する返答です。

  • 自分でデータベース書けばいいんじゃね?
  • 柔軟なAPI用意すればいいんじゃね?

ってことですね。


データベースは、key-valueストアを組み合わせたcolumnストア的な感じになっています。
詳細については、今後別エントリやドキュメントで述べます。


今後は、Sennaはバグ修正のみ行うメンテナンスモードに移行します。

実際使ってみよう

今回は、groongaが備える「memcached互換プロトコル対応機能」を使ってみましょう。

groongaは、独自のデータベース・全文検索機能をAPI経由で提供するライブラリです。そのライブラリを使って、memcached互換のデーモンを書いてみたよ、というお話ですね。プロトコルmemcached互換ながら、データはHDD/SSDに保存されます。


以下のようにインストールします。
今回は、全文検索は行わないため、
MeCabなしでインストールしてみましょう。

> tar xvfz groonga-0.0.1.tar.gz
> cd groonga-0.0.1
> ./configure --without-mecab
> make
> su
# make install

以下のように、groongaデーモンを起動します。
デフォルトでは、ポート番号10041でlistenします。

> groonga -s <データベースファイル名>

Gronngaは、独自プロトコルmemcached互換プロトコルをサポートしています。
今回は、memcached互換プロトコルを使ってみましょう。
memcachedのバイナリプロトコルをサポートしているクライアントが必要です。


今回は、libmemcachedを直に使ってみます。
livedoorの池邊さんがWEB+DB pressに書いたコードのパクりですが…

#include <stdio.h>

#include "libmemcached/memcached.h"

int
main(int argc, char *argv[])
{
  struct memcached_st *memc;
  struct memcached_server_st *servers;
  memcached_return rc;
  char *val;
  size_t val_len;
  uint32_t flags;

  memc = memcached_create(NULL);
  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
  servers = memcached_servers_parse("127.0.0.1:10041");
  rc = memcached_server_push(memc, servers);
  if (rc != MEMCACHED_SUCCESS) {
    fprintf(stderr, "Error: %s\n", memcached_strerror(memc, rc));
    return -1;
  }
  rc = memcached_set(memc, "key", 3, "value", 5, 0, 0);
  if (rc != MEMCACHED_SUCCESS) {
    fprintf(stderr, "Error: %s\n", memcached_strerror(memc, rc));
    return -1;
  }

  val = memcached_get(memc, "key", 3, &val_len, &flags, &rc);
  if (rc == MEMCACHED_SUCCESS) {
    printf("val: %.*s\n", val_len, val);
  }
  if (val) {
    free(val);
  }

  memcached_server_list_free(servers);
  memcached_free(memc);

  return 0;
}

'key'というキーに、'value'という値が設定して、
それの取得ができましたね。
キャッキャッ。

PHPのセッション維持をgroongaでやってみる

PECLのmemcacheライブラリは、最近バイナリプロトコルをサポートしたようです。
が、試してみたらうまく動かなかったっす。
というわけで、今回は、PECLmemcachedライブラリを使いました。
libmemcachedのラッパーですね。


PECLのmemcache/memcachedは、
PHPのセッションをmemcachedに保存するための機能を持っており、
php.iniを編集するだけでセッション情報をmemcachedに保存することが可能です。
ただし、memcachedのテキストプロトコルが使われてしまうんですねー…


よって、PHPのセッション維持をmemcachedのバイナリプロトコルを用いて行う
テストプログラムを書きました。
こんなんでうまく動くはずです。

<?php
extension_loaded('memcached') || dl('memcached.so') || exit(1);

class MemcachedBinarySession
{
  private static $memcached;
  private static $lifetime;

  public static function open() {
    self::$lifetime = ini_get('session.gc_maxlifetime');
    $m = new Memcached;
    $m->setOption(Memcached::OPT_BINARY_PROTOCOL, 1);
    $ret = $m->addServer('localhost', 10041);
    self::$memcached = $m;
    return $ret;
  }

  public static function close() {
    return TRUE;
  }

  public static function read($session_id) {
    return self::$memcached->get($session_id);
  }

  public static function write($session_id, $session_data) {
    return self::$memcached->set($session_id, $session_data, self::$lifetime);
  }

  public static function destroy($id) {
    return self::$memcached->delete($session_id);
  }

  // don't delete.
  public static function gc($max_lifetime) {
    return TRUE;
  }
}

ini_set('session.save_handler', 'user');

session_set_save_handler(array('MemcachedBinarySession', 'open'),
                         array('MemcachedBinarySession', 'close'),
                         array('MemcachedBinarySession', 'read'),
                         array('MemcachedBinarySession', 'write'),
                         array('MemcachedBinarySession', 'destroy'),
                         array('MemcachedBinarySession', 'gc')
                        );

if (session_id() == '') session_start();

if (isset($_SESSION['counter'])) {
  $_SESSION['counter']++;
} else {
  $_SESSION['counter'] = 1;
}
echo '<br/>SessionID: '. session_id() .'<br/>Counter: '. $_SESSION['counter'];
?>

groongaサーバをlocalhostで動かしているサーバに、
上記のスクリプトを置いてみましょう。
ブラウザで確認すると、カウンタが増えていきますねー。
わーい。

大事な注意

とりあえず、今日の発表会のためだけにリリースをしてので、
以下のような制限事項があります。


groongaはリポジトリgithubで公開しています。
http://github.com/groonga/groonga/tree/master
ぜひぜひパッチを!give me patch!!!

  • テストリリースのため、APIドキュメントがまったくないです。

APIドキュメントは今必死に書いてます。
memcachedバイナリプロトコル互換APIで遊んでみてね。

  • Macでテストしてないっす。kqueueサポートしてないっす。

現在、Linux(amd64)で開発・テストしています。
Macでもテストしてません。
また、kqueueサポートもしていないため、多重度が高いテストをMacFreeBSDで行うと遅いと思います。

現在、各種LL言語のためのバインディングがありません。
バインディング大募集中です!

  • exptimeは保存されていますが、処理は行っていません。

Tokyo Tyrant等のmemcached互換実装では、flagsやexptimeを無視するものがあります。
groongaでは、flagsやexptimeをきちんと保存しています。
が、exptimeの処理を書いていないので、expireが行われません。
きちんと保存はしているので、あとはexpireの処理の実装が必要です。

とりあえずは、getの際にexptimeを越えていたら値を消す、
的な実装からつけていきたいところです。

  • ファイルフォーマットが変わるかもしれません。

テストリリースなので、ファイルフォーマット変わるかもしれません。

  • MySQLから使えません。

現在、MySQL経由では利用できません。
これについては、現在…ゲホゲホ 闇の組織がー!! ぐふっ
というわけで、ご期待あれ。

まとめ

  • Sennaの次世代バージョンのgroongaをテストリリースしました!
  • githubでソース公開してます!
  • みんなのツッコミ待ってます!

ニコニコ動画データ解析発表会でニコニコ大百科の宣伝を行いました(発表資料もあるよ!)

昨日2009年1月25日に、GLOCOMで行われたニコニコ動画データ分析研究発表会で発表を行いました。

USTREAM経由を含め、聴講してくださった方ありがとうございました!


解析の妥当性などのツメが甘いのでジョーク枠とさせていただいたのですが、
ジョークが少ない!ジョークがすべっている!と大変不評で嬉しい限りです。
あと、マイクの音割れがあったようで申し訳ございませんでした。
早口で聞き取りづらく、基本ノープランな発表でしたが、
大体「くぎゅうううううううう」的ななにかで救われた気がします。


発表資料一式のPDFをzipで固めて置いておきました。
ぜひニヤニヤしてみることをオススメします。



  • 2タグのANDタグ検索の検索結果数(LGL形式)
  • 関連タグネットワークのファイル(XGMML形式)

などが欲しい方は個別にご連絡をー!って、面倒ですよね。
どこかに公開するのでお待ちください。


Voronoi Treemapsを描画するコードについては、CodeReposgithubに遺棄しておきます。
意外と実装に手間取ったので、捨てるの勿体ないっす。

Skypeの会議通話をニコニコ生放送する方式を考える

Skypeの会議通話を、ニコニコ生放送(やその他インターネット配信)で配信する方法を手探りしているメモです。Windows/Mac両方での方法をメモしたいです。


Windowsではステレオミキサーを使う方法、
Macでは、Soundflowerというソフトを使う方法がよく紹介されます。
これらのツールはPC内で発生した音全てを拾うため、
配信したくない音まで配信してしまいます(エラー音など)。


というわけで、ステレオミキサーやSoundflowerに頼らない方法を紹介します。

やりたいことの概念図
[マイク]-+->[Skype]-+->[モニタ用音声出力(他人の声のみ)]
           |               |
           +----------+->[配信用出力]->[ニコニコ生放送]

Skypeの会議通話を配信するためには、2つの問題をクリアしないといけません。それらの問題について、それぞれ解決方法を紹介します。

問題点1:

ニコニコ生放送の入力、Skypeの出力ともに
物理的なデバイスとして認識される必要があります。

解決方法1: USBサウンドバイスを使って、ヘッドホン端子とマイクとをつなぎます。

USBで、ヘッドホンとマイク端子を追加できる製品があります。
その製品を購入して、ヘッドホンとマイク端子をケーブルでつなぐという方式です。
1点注意があります。ケーブルは「抵抗入り」を買ってください。

安いUSBサウンドバイスとケーブルをAmazonで見繕ってきました。

解決方法2: 仮想サウンドカードを使う

Virtual Audio Cableというソフトを使えば、
解決方法1と同じことをパソコンの中だけで実現できます。
お金払わないと「金払えー」と怒られる。


まず、Virtual Audio Cableをインストールしてください。
そして、Skypeの音声出力を「Virtual Cable 1」とし、
ニコニコ生放送の音声入力を「Virtual Cable 1」にしてください。
こうすることによって、Skypeの出力を直に配信することができます。

  • Mac:詳しくないです…情報求む

問題点2:

Skypeでは、自分が話した声が出力されません。

解決方法1: 会議通話に、聞くだけのユーザを招待します。

話すためのSkypeとは別に、
発言を行わず、会議通話を聞くだけのSkypeを使う方法です。

概念図
[マイク]->[Skype(話す用)]->[モニタ用音声出力(他人の声のみ)]
[Skype(聞く用)]->[配信用出力]->[ニコニコ生放送]


パソコンが2台あれば、話は簡単ですね。実は、パソコン1台でもできます。
複数アカウントでのSkypeのログイン方法は、以下のブログを参照ください(Windowsのみ)。
http://share.skype.com/sites/ja/2006/10/26/2instances_of_skype.html


会議通話を聞くだけのユーザの音声出力先を、

  • 問題点1の解決方法1を選んだ場合: USBサウンドバイス
  • 問題点1の解決方法2を選んだ場合: Virtual Cable 1

にしてください。

解決方法2: マイクの音を横取りするソフトを使う

この方式だと、自分の声が入らないモニタ用出力が難しい気がする。


マイクの音を横取りして、それを指定のデバイスに出力することができます。

どちらも、マイクの音を横取りして、指定の出力先に音を出すことができます。

音声出力先は、

  • 問題点1の解決方法1を選んだ場合: USBサウンドバイス
  • 問題点1の解決方法2を選んだ場合: Virtual Cable 1

にしてください。