日本野望の会 » article http://yabooo.org いずれにせよITで世界征服をたくらむ悪の組織です。 Mon, 28 Dec 2009 14:30:41 +0000 http://wordpress.org/?v=2.8.3 ja hourly 1 野望の会プロヂュースのミニフィルム作りました http://yabooo.org/archives/237 http://yabooo.org/archives/237#comments Mon, 28 Dec 2009 14:30:41 +0000 hirokidaichi http://yabooo.org/?p=237 おひさしぶりです。事務局長のひろきのだいちです。

この間映画をプロヂュースしたので、ぜひ見てください。
予算の内訳とかあとで書くかもですが、社会人でも合間をぬってコンテンツがつくれるのかなーというトライアルです。
年1くらいでは続けていきたいです

タイトルは肉食女子

現代社会の縮図とも言える肉食女子のサイエンスドキュメンタリーです。

いいかんじにくだらないので見てやってください。

]]>
http://yabooo.org/archives/237/feed 0
[イベント]そろそろWebを再起動しよう http://yabooo.org/archives/205 http://yabooo.org/archives/205#comments Sun, 22 Mar 2009 14:48:56 +0000 http://www.yabooo.org/?p=205 どうも、日本野望の会事務局長のひろきのだいちです。おひさしぶりです。

ひさびさの野望の会イベントです。

WWWが生まれて20年ちかくたちますが、このずっと起動しっぱなしだったWebというものを今一度、若い目線で見直してみようという一大イベントを開催します。オレンジや青の大手SNSをはじめ、誰もが知ってる大手ポータルサイトの歴歴の若手たちが一同に終結し、Webの今後を語り合います。そんなイベントを開催するにふさわしい場所が、コミュニティサイトの最長老niftyのお膝元である「Tokyo Culture Culture」というイベントホール。題して「Web2.0中の人ナイト」。

日時は3/29(日)

nakanohitonight_02

この浮ついた感もあるチープな名前と適度なサブカル臭が、日本野望の会の真骨頂なのですが、なかなかどうして今回はそうそうたる面々からのWeb業界の事情やライフスタイルなどがかんがみえます。

Web2.0とはなんだったのか。

Webの中、どうなってんの?

そろそろ再考してみてもいい時期かもしれません。

http://tcc.nifty.com/cs/catalog/tcc_schedule/catalog_090225201886_1.htm

チケットはe+から購入または当日券もございますyo

チケット残件わずか!となってしまいました。当日券は期待しないでe+からお買い求めください。

では!

]]>
http://yabooo.org/archives/205/feed 0
Safari/Webkitのおせっかいキャッシュとその対策。 http://yabooo.org/archives/180 http://yabooo.org/archives/180#comments Sat, 29 Nov 2008 06:40:19 +0000 http://www.yabooo.org/?p=180 どうもひろきのだいちです。

最近のモダンなブラウザには、Backfowardキャッシュと呼ばれるブラウザの戻るボタンを押した際に利用されるキャッシュ機構が用意されています。この機構は普段ウェブブラウジングを行う際には間違った操作からの復帰が早く非常に重宝するのですが、一部のWebアプリケーション設計の際にはこの仕組みが厄介に働くことがあります。


そういったケースでよく使用されるテクニックとしてはwindow unloadイベントへのハンドリングで、このページはすでに終端処理を済ませていますよ、ということを通知することで再度インラインjsや、onload後の処理を行うことができます。

JAVASCRIPT:
  1. window.onload=function(){alert('test');}

だけではページ遷移後、戻るを押してもloadEventは発火されません。

しかし、

JAVASCRIPT:
  1. window.onload=function(){alert('test');}
  2. window.onunload=function(){};

とすることで、「戻る」のあとにもonloadイベントは発火されるようになります。

これである程度の問題は解決するはずが、Safariなどの場合、このunloadを付与した場合のForm要素系のタグ、つまりinput,select,option,textareaなどの動作がおかしくなります。

input追加をクリックするたびに、innerHTMLをつかってinputタグが生成されるというケースを考えて見ましょう。

このときに、inputタグのvalueにユーザ入力によって値を設定します。

削除を押すと、inputタグがinnerHTML=""によってクリアされます。

さらに2つほどinputタグを生成して、再びユーザ入力によって値を設定します。

この後、何らかのリンクをたどって「戻る」という状態にすると、unloadが設定されているので、onloadEventが発火し一番最初の状態に戻ります。なので、Backforwardキャッシュ機構は停止されて、まったく最初と同じ状態になっているはずです。ところが、ふたたびinput追加をクリックしてinput要素を追加すると以下のように、いままでのユーザ入力のデータが保存された状態で現れてしまいます。

ちなみにinputタグはname属性やid属性もふられておらず、ただ同じような位置に存在するということだけでそのvalueがキャッシュされてしまっているようなのです。

これではJemplate/EJS/HTMLTemplate.jsなどのテンプレートモジュールを利用してElementの値を再構築するようなアプリケーションやinput hiddenなどで値をサーバサイドから提供するアプリケーションに深刻な不具合をもたらしてしまいます。

これはappendChildのみですべてのUIを実装するというかなりおそろしいやり方をするというのは、中規模以上のアプリケーションではかなり問題になります。ちなみにcreateContextualFragmentを用いてstringからHTML要素を生成する場合でもどうようにこのようなバグが発生します。

では、その対策にはどのような方法があるでしょうか。

まずぱっと思いつくのはそのノード自体をガベコレの対象とするためにremoveChildするような方法です。

JAVASCRIPT:
  1. window.onload=function(){
  2.   // inputタグすべてにたいして
  3.   e.parent.removeChild(e);
  4. }

ところが、このおせっかいキャッシュ機構のいやらしいところは、Elementがremoveされたとしてもvalueの汚染が続くということです。なので、Elementのremoveは効果がありません。

さらに、innerHTML=""などでclearされたElementはjavascript領域からは消えてしまうので取得することができないというやっかいさも抱えています。

このバグ(といっても差し支えないだろう)的なキャッシュ機構に対応するためには、そのページで生成されては消えていったすべてのinput系タグを、"戻る"後に生成されるElementとは異なるものであることをレンダリングエンジンに教えてあげなければいけません。

なので

JAVASCRIPT:
  1. window.onload=function(){
  2.   // inputタグすべてにたいして
  3.   e.name = (new Date).getTime();
  4. }

のようにname属性を二度と参照されない値に変更することで、valueを汚染されることを防ぎます。

さらに、そのページで生成されては消えていったすべてのinput系タグを取得する方法として以下のような戦略をとります。

DOM Event Level2のMutation Eventの中でSafariで利用可能なDOMNodeInsertedを利用して、DOMに変化が生じるたびに"まだマークされていない"すべてのinputエレメントを取得し、キャッシュに保存しておきます。

最後にキャッシュされたすべてのエレメントのname属性を変更することで、このようなバグから開放されることとなります。

以下、これらをPrototype.js 1.60をベースに実装したものを晒しておきます。
ただ、これにも一部既知のバグが存在していて、innerHTML+=で発生するバグや途中でidやname属性を動的に変更されたElementなどをフォローすることができないのです。

しかし、いずれもjavascript的にはマナーの悪いこととされているのでコーディングルールなどでこれらのバグを避けるようにすることが得策かもしれません。

JAVASCRIPT:
  1. if (Prototype.Browser.WebKit)(function() {
  2.   Event._observe = Event.observe;
  3.   function _search(hash, searchText) {
  4.     if (hash[searchText]) {
  5.       return (Object.isFunction(hash[searchText])) ? hash[searchText] : Prototype.emptyFunction;
  6.     } else {
  7.       return (Object.isFunction(hash['_default'])) ? hash['_default'] : Prototype.emptyFunction;
  8.     }
  9.   }
  10.   var firstUnload = true;
  11.   Event.observe = function(element, name, func) {
  12.     return _search({
  13.       'beforeunload': function() {
  14.         return element.addEventListener('beforeunload',
  15.         function(evt) {
  16.           return func.bind(element)(evt);
  17.         });
  18.       },
  19.       'unload': function() {
  20.         if (firstUnload) Event._observe(window, 'unload', (function() {
  21.           var cache = {};
  22.           var selector = $w('input option select textarea').join(':not(._marked),') + ':not(.marked)';
  23.           function storeCache() {
  24.             $$(selector).each(function(e) {
  25.               cache[e.identify()] = e;
  26.               e.addClassName('_marked');
  27.             });
  28.           }
  29.           Event._observe(document.body, 'DOMNodeInserted', storeCache);
  30.           Event._observe(window, 'load', storeCache);
  31.           return function() {
  32.             var time = (new Date).getTime();
  33.             alert(Object.toJSON($H(cache).keys()));
  34.             $H(cache).each(function(e, i) {
  35.               e.value.name = time + "_" + i;
  36.             });
  37.           };
  38.         })());
  39.         firstUnload = false;
  40.         return Event._observe(element, name, func);
  41.       },
  42.       '_default': function() {
  43.         return Event._observe(element, name, func);
  44.       }
  45.     },
  46.     name)();
  47.   }
  48.   Object.extend(window, {
  49.     observe: Event.observe.methodize()
  50.   });
  51. })();

]]>
http://yabooo.org/archives/180/feed 2
再入門JavaScript -目次- http://yabooo.org/archives/158 http://yabooo.org/archives/158#comments Tue, 28 Oct 2008 16:41:00 +0000 http://www.yabooo.org/?p=158 こんにちは、ひろきのだいちです。

JavaScriptの再発見からさらに2年がたち、モダンなWeb開発では欠かせない存在となったJavaScript。さまざまなライブラリが乱立し、言語としての基礎を得ないままでもある程度のアプリケーション開発ができるようになった現在。

再入門JavaScriptと題して、中上級者を目指すために入門書を超えてじっくりとJavaScriptを学びなおすことが重要だと考え、ここを中心にまとめていきたいと思います。

ここで掲載するトピックは本当の基礎の基礎は他の媒体にゆだねた上で、「仕事でつかえる」レベルのコードを記述するために重要で比較的高度なものを取り扱うつもりです。

また、ここでいう仕事で使えるとは"多人数で開発を進める"ことを前提とした開発環境を想定しており、他サイトのAPIの使い方やライブラリの使用方法といった枝葉のリファレンスではありません。

また、ここに書かれていることはたいてい僕のメモなので、責任はもちませんw

再入門JavaScript -フロントエンドエンジニア資料集

再入門JavaScript -JavaScriptでの中大規模開発

  • 再入門JavaScript - コード成長過程
  • 再入門JavaScript - MarkupエンジニアとScriptエンジニア、サーバサイドエンジニアとの協調
  • 再入門JavaScript - グレースフルデグラデーション
  • 再入門JavaScript - MVCモデル
  • 再入門JavaScript -  クライアントサイドMVC
  • 再入門JavaScript -  デザインパターン

再入門JavaScript -名前空間とスコープ

再入門JavaScript -オブジェクト指向と関数オブジェクト

  • 再入門JavaScript - オブジェクトとプロトタイプチェーン
  • 再入門JavaScript - 継承・ダックタイピング
  • 再入門JavaScript - 引数アサーションと動的ヴァリデーション
  • 再入門JavaScript - 動的バインディング
  • 再入門JavaScript - ビルドインオブジェクトのプロトタイプ拡張

再入門JavaScript -DOM

  • 再入門JavaScript - イベントとバブリング
  • 再入門JavaScript - XHTML拡張
  • 再入門JavaScript - CSSの扱い

再入門JavaScript -DOM上のDSL

  • 再入門JavaScript - CSS Selector
  • 再入門JavaScript - XPath
  • 再入門JavaScript - E4X

再入門JavaScript -テストとドキュメンテーション

  • 再入門JavaScript - UnitTest
  • 再入門JavaScript -  Seleniumによる結合テスト
  • 再入門JavaScript -  JsDocによるドキュメンテーション

再入門JavaScript -パフォーマンス/高速化

  • 再入門JavaScript - プロファイリング
  • 再入門JavaScript - DOM描画フェーズ/タイマー
  • 再入門JavaScript - 事前コンパイルを利用した高速化
  • 再入門JavaScript - VMレベルでの動作を意識する
  • 再入門JavaScript - メモリリークとガーベジコレクタ
  • 再入門JavaScript - defer属性/script後置とminifier
  • 再入門JavaScript - 先読みと
  • 再入門JavaScript - Google Gears

再入門JavaScript -通信

  • 再入門JavaScript - クロスドメイン制約
  • 再入門JavaScript - 同一ドメイン通信
  • 再入門JavaScript - location.hashによるヒストリ管理
  • 再入門JavaScript - 通信の効率化とサーバサイド連携
  • 再入門JavaScript - クロスドメイン通信方法と注意点
]]>
http://yabooo.org/archives/158/feed 0
IEの腐ったEventを直す方法 http://yabooo.org/archives/122 http://yabooo.org/archives/122#comments Mon, 13 Oct 2008 09:51:01 +0000 http://www.yabooo.org/?p=122 こんにちは。ひろきのだいちです。

今日はブラウザ界のやんちゃボーイ Internet ExplorerのEvent実行順序を調整する方法を考えたんでつらつら書きます。

ただ、すべてのDOMイベントを他のブラウザと互換を取るのはむずかしいので、prototype.js(1.6 or later)のdom:loadedイベントとwindow のloadイベントの実行順序を整列させます。

その後、単一のイベント間の実行順序がattach順にならないというIEのバグをDOM準拠のAPIを追加することで修正します。

JAVASCRIPT:
  1. 10..times(function(i){
  2.     Element.observe(window,'load',function(){
  3.         alert('window loaded'+i);
  4.     });
  5.  
  6. })
  7. 10..times(function(i){
  8.     document.observe('dom:loaded',function(){
  9.         alert('dom loaded'+i);
  10.     });
  11.  
  12. })

dom:loadedとはDOM Treeのパースが終わってjsからさわっても大丈夫だよ!
というイベントです。(細かい定義はしらない。)

またwindowオブジェクトのloadイベントはHTML内の全部のコンテンツのロードがおわったよ!
というイベントです。

これをIE以外のブラウザで実行すると

dom: loaded:0123456789
window load:0123456789

の順番で実行されます。

ところがIEで実行すると・・・・

window load:5432689710
dom: loaded:1324689750

シュールすぎる・・・・TT

さて、まずどこから手をつけましょうか。

dom:loadedイベントとwindow onloadイベントの実行順序が逆っていうのから対処しましょうか。

実はコレ、
HTML中に画像が1つでもあれば、大丈夫で、画像の存在するページで実行すると

dom: loaded:1324689750
window load:5432689710

上記のようにdom loadedイベントが先に発生します。

ところが、これらの画像が全部キャッシュされていた場合・・・・


window load:5432689710
dom: loaded:1324689750

またもや、window loadが先に実行されます。

そこで、

JAVASCRIPT:
  1. if(Prototype.Browser.IE)
  2.     (function(){
  3.         var flag =true;
  4.         Event.observe(window,'load',function(){
  5.             if(flag){
  6.                 document.fire('dom:loaded');
  7.                 document.stopObserving('dom:loaded');
  8.             }
  9.         });
  10.         document.observe('dom:loaded',function(evt){
  11.             flag =false;
  12.         });
  13.     })();

のようにIEの場合のみ、window loadイベントが先に発生し場合に
dom:loadedイベントを発生させて、その後のおこるdom:loadedイベントを全部キャンセルしてみましょう。

すると

dom: loaded:1324689750
window load:5432689710

画像アリ、ナシともにdom:loadedが先に発生しているようです。

次に実行順序です。

問題はEvent.observe内で行っているattachEventが、まともじゃないってことなので
これを是正しましょう。

これは結構根の深い問題なので、
attachEventを極力使いたくありません。

なのでIEにaddEventListener/removeEventListenerを実装してしまいましょう。

そしてその中で1つだけattachEventをもちいて、

JAVASCRIPT:
  1. element.attachEvent('on'+eventName,function(evt){
  2.      cache.each(function(e){e(evt)});
  3. })

のようにキャッシュに積んでおいてあるEvent Handlerたちを実行すれば、
attachEventは一度しか使わないのできれいに整列されます。

そうすると・・・・

dom: loaded:0123456789
window load:0123456789

このようにIEでも実行順序を間違えることなくきれいに整列させることができました!
以下コードです。

JAVASCRIPT:
  1. if (!Prototype) throw ('Event.Wrapper require prototype.js');
  2. if (parseInt(Prototype.Version)> 1.6) throw ('Event.Wrapper require prototype.js v1.6 or later');
  3.  
  4. if(Prototype.Browser.IE)(function() {
  5.  
  6.     var eventCache ={};
  7.     var wrapperCache = {};
  8.     function getEventCache(elementID,eventName){
  9.         if(!eventCache[elementID])eventCache[elementID]={};
  10.         if(!eventCache[elementID][eventName])eventCache[elementID][eventName]=[];
  11.         return eventCache[elementID][eventName];
  12.     }
  13.     function createFixedOrderWrapper(elementID,eventName){
  14.         var wrapper= function(event){
  15.             getEventCache(elementID,eventName).each(function(func){
  16.                 func(event);
  17.             });
  18.         };
  19.         if(!wrapperCache[elementID])wrapperCache[elementID]= {};
  20.         wrapperCache[elementID][eventName] = wrapper;
  21.         return wrapper;
  22.     }
  23.     function getEventId(element) {
  24.         return element._prototypeEventID || element._eventID;
  25.     }
  26.     function addEventListenerIE(element,eventName,func,capture){
  27.         var id = getEventId(element);
  28.         var length =getEventCache(id,eventName).push(func);
  29.         if(length == 1){
  30.             element.attachEvent('on'+eventName,createFixedOrderWrapper(id,eventName));
  31.         }
  32.     }
  33.     function removeEventListenerIE(element,eventName,func,capture){
  34.         var id = getEventId(element);
  35.         var cache =getEventCache(id,eventName);
  36.         if(cache.length>0){
  37.             eventCache[id][eventName]=cache.without(func);
  38.             if(eventCache[id][eventName].length == 0){
  39.                 element.detachEvent('on'+eventName,wrapperCache[id][eventName]);
  40.             }
  41.         }
  42.     }
  43.    
  44.     Element.addMethods({
  45.         addEventListener:addEventListenerIE,
  46.         removeEventListener:removeEventListenerIE
  47.     });
  48.     Object.extend(window, {
  49.         addEventListener: addEventListenerIE.methodize(),
  50.         removeEventListener: removeEventListenerIE.methodize()
  51.     });
  52.     Object.extend(document, {
  53.         addEventListener: addEventListenerIE.methodize(),
  54.         removeEventListener: removeEventListenerIE.methodize()
  55.     });
  56.     (function(){
  57.         var flag =true;
  58.         Event.observe(window,'load',function(){
  59.             if(flag){
  60.                 document.fire('dom:loaded');
  61.                 document.stopObserving('dom:loaded');
  62.             }
  63.         });
  64.         document.observe('dom:loaded',function(evt){
  65.             flag =false;
  66.         });
  67.     })();
  68. })();

]]>
http://yabooo.org/archives/122/feed 0
はてブはソーシャルブックマークじゃないかもしれない。 http://yabooo.org/archives/109 http://yabooo.org/archives/109#comments Sun, 13 Jul 2008 06:55:46 +0000 http://www.yabooo.org/archives/109 どうも、ひろきのだいちです。おひさしぶり。
先日7/12に東工大の大岡山キャンパスでSBM勉強会が開かれ、いってまいりました。

今話題のiPhoneのソフトバンクモバイルではなく、
「ソーシャルブックマーク」勉強会ということで方々に誤解を招いているSBM勉強会ですが、tomoさんの勉強会としては過去最大級の規模100人越え(実参加は80人くらいか)の大盛況振りでした。

講演者の方々への感想はすでにいろいろなところで書かれているので
今回、僕はあえて次回のソーシャルブックマーク勉強会に期待することと
今回語られなかったことを洗い出してゆきたいとおもいます。

この語られなかったことは懇親会の二次会、恵比寿のバーでぐだぐだと語られたこと(深夜0:00まで)でココでの議論が実はもっとも有益なものだったのではないかと思っています。

それをシェアするのも重要だと考え、ブログにしたためます。


SBM勉強会で語られなかったこと

  • ソーシャルブックマークとは何か
  • ソーシャルブックマークは存在するのか
  • 属人性のある情報の価値
  • コミュニケーションツール or 情報整理・発見ツール
  • そもそもブックマーク/タギングが必須なのか
  • 既存のWebにオーバレイすること問題点
  • 誰が編纂者なのか
  • 将来のソーシャルブックマーク=~s/ブックマーク/something/

ソーシャルブックマークとは何か

現状のソーシャルブックマークサービスと呼ばれているものの正体についてはさまざまな講演者が語ってくれていて、それはそれで現状や歴史の整理になり有益だったのですが、そもそも論としてのソーシャルブックマークについての考察があまりなかったように感じました。

小島さんのソーシャルグラフAPIのお話が、もっともそこに近づいたのですがそれが違和感になるほどに"ソーシャル"であることについての言及があまりありませんでした。

そもそも、ソーシャルと名を関するサービスはそれ自体を単なる場図ワードとして取り扱っている面も否めませんが、これらの指すソーシャルが現実の社会的関係ネットワーク、つまりソーシャルグラフを意図している部分はたぶんにあると思われます。

では、果たして現状のソーシャルブックマークで
「現実の社会的関係」を重要視し、これらの構築を意図しているような部分は存在するでしょうか。

僕ははてブ「お気に入り」などの機能がそれに類するものだと考えますが
ソーシャルグラフを意図するには不十分であるように感じられます。

私見では現状のソーシャルブックマークと呼ばれているサービスは
記名/顕名性シェアリングブックマークサービスでしかなく、
十分にソーシャルである(不思議な日本語ですが)サービスは多くないように感じます。

少なくともはてブは「シェアリングブックマークサービス」であるように
理解しています。

これについて異論のある方もいらっしゃると思いますが
こういった議論が今後なされていくことを望みます。
(あるいは、僕が問題提起&サンプルアプリを作るとか。)

ソーシャルブックマークは存在するのか

上述のとおり、現状のソーシャルブックマークとよばれるサービスは
俺俺定義の「ソーシャルブックマークサービス」ではないように思われます。

では、ソーシャルブックマークサービスに必要なものは何なのでしょうか。
この必要条件についても考察が必要で、それこそが今後の発展系を見据えるために
重要なポイントではないかと考えます。

ローカルブックマーク

オンラインブックマーク

シェアリングブックマーク← 今ここ?
↓            ← あるいはココだ!
ソーシャルブックマーク

ソーシャルごにょごにょ

というように発展系や未来型のSBMについての議論がなされることを望みます。
もし、可能ならば次回はそのような問題提起を起こしていきたいと思っております。

属人性のある情報の価値

井口さんが講演で述べられていた「匿名性P2P型ソーシャルブックマーク」について考察するときに以下にみずからのプロファイル情報を隠すかというお考えでアルゴリズムを作られていましたが、これはオレオレ解釈のブックマークサービス像で考えると、

「シェアリングブックマークをローカルブックマークのように使いたい。」

というニーズになるように思われます。

現状のはてブが「誰がブックマークしたか/コメントしたか」という属人性のある情報を取り扱えていることが、ここが単純なシェアリングブックマークではなく
顕名性を採用していることから発生するメリットであるように考えると
この議論はソーシャルブックマークの方向性とは逆行しているように考えられますが、奥様の「お気に入りを公開する?正気?」発言からするとマスにアプローチする手段としては有効なのかもしれません。

しかし、参入障壁としてP2Pを考えると賢明な方法なのか・・・という議論の余地はあるでしょう。

嗜好のベクトル情報/プロファイル情報のみの交換ということなので
SBMサイトでもっともPVをあつめ、マスアプローチに成功している
人気のエントリーであるとか「ランキング」のようなものが成立しないということでどのような評価になるのかも楽しみです。

このような意味で、
「属人性のある情報」がソーシャルであるための重要なポイントでありながら
この部分の議論があまり進んでいないのは残念ともいえます。

コミュニケーションツール or 情報整理・発見ツール

果たして、ソーシャルブックマークシステムは「何のためのツール」なのでしょうか?そして国内市場を見たときにそのモデルは有効なのでしょうか。

個人的には情報整理・発見ツールとしては
Google Bookmarkのラベル&検索のほうが使い勝手がよいと思います。

ナレッジサイエンスの分野では情報整理・発見のツールとしての価値のある研究がすすんでいるように思われますが、この知見が今後ブックマークサービスに生かされるようになることを望みます。

しかし、コミュニケーションツールとしての側面を考えたときにはてブのよさが
でてきていて、それがそのままソーシャルブックマーク的なサービスのよさになっていると思います。

そろそろ、
ソーシャルブックマークの目指すところを議論してもよいのかもしれません。

そもそもブックマーク/タギングが必須なのか

既存のSBMサービスには2つの障壁があります。
・1つはその価値を理解すること
・もう1つは導入のためのブックマークレットなどを設定できること

そして、いざブックマークする!となったときに
・ブラウザのブックマークボタン以外のボタンとしてブックマークレットを押す
・コメント&タギングする

という行為を行う必要があります。
これらのアノテーションサービスの難しさはこの行為そのものの理解であると思います。たとえばニコニコ動画は「集合知」という観念に対して「集合情」という概念を創出し、アノテーションへの抵抗を減らしました。

この背景にあるものもコミュニケーションというものです。

「集合情」を起点にはてブを見れば「これはひどい」タグには重要な可能性が眠っているということもいえます。

星さんの講演で質問したように
感情共有こそがコミュニケーションサービスにおいて重要なポイントだからです。

ところで、そもそも
ブックマークである必要があるのでしょうか?
タギングする必要があるのでしょうか?

これらの行為は非常にハードルが高く高コストです。

既存のWebにオーバレイすること問題点

これは懇親会の帰りに星さんと話したことなのですが、
コモンズ・マーカーにしろ、既存のはてブなどにしろ記事のオーサとの関連が低く
記事そのもののコメント機能ではなくそれらにオーバレイする形でコメントや批判がなされる形というのはどうなのでしょうか。

たとえばHTML上にコメント/hidden属性でオーサアカウント固有情報を書き込むなどすることでより発展的なオーサとの関連性を高めることはできないでしょうか。

はてブのようにはてなダイアリーも同時に所有してるサービスならば
ここの関連を自動化することもできますが、他のオンラインメディアとの関係性の築き方が今後の課題ともいえるでしょう。

誰が編纂者なのか

ソーシャルブックマークサービスでブックマークという行為のハードルが高いことにも関連しますが、横田さんの講演によるとソーシャルブックマークサービスの利用者は全体の7%程度です。ブックマークの上位ランキングを見るものが9割おり、のこり10%がブックマーク行為をしたとします。しかし10%のうち9%は残りの1%のフォロワーのようにして誰かがブックマークして、上位に入り込んだエントリーのブックマークをしているような状況が現状と仮定します。(数字についてのソースはないです、すみません。)

このような現状のときに1%の誰かによる煽動や好みというのがダイレクトにのこり99%に広がります。この状況を好ましいと思える場合にはよいのですが、好ましいと思えない場合にはどうでしょう?このブックマークサービスを利用していない93%のネットユーザにとって、魅力的なサービスでしょうか?

いわゆる「はてな村」問題の原因はこういった狭い志向性をもった情報が一律的にランキングされ、情報としてあがってくることにあります。逆に懇親会でよく聞かれた意見としてはブックマーカーランキングがあがってゆくことがとても楽しく感じ、どんどんと地位が向上してくるような錯覚を味わうことで「はてブ廃人」になりそうだったというものがありました。

MMORPGと同じように狭い世界でのランキングや名誉欲を刺激するサービスがこういったコアユーザを生み出すことはよくあることですが、このようなサービスはマス向けではなくやはり、限られたユーザだけのものになってしまいます。

それもまたアリだと思います。たとえば横田さんの講演にあった専門特化のSBMなどはまさにそれでノイズの割合を下げることにもつながるからです。

しかし、一律のランキング性は「もりあがる」にせよ、多様性を保障しません。

各人にうまくカスタマイズされるようにすること、たとえばryoくんのKikkerのように学習性をもったり、お気に入り情報をもっと上手く利用することなどによってパーソナライズすることがソーシャルである重要な部分であり、多様性の保障によってより多くのユーザに楽しんでもらえるサービスになるのではないでしょうか。

1%の編纂者問題は重要なテーマです。ブックマークサービスの抵抗をさげ、さらに発展するためにはこのような問題へのシステム的な対応が必要になると考えます。

将来のソーシャルブックマーク=~s/ブックマーク/something/

散々、語りましたが最後に将来のソーシャルブックマークについての考えを述べたいと思います。

前述のように現状のSBMサービスは「シェアリングブックマーク」とその発展の域から出ていないように感じます。ソーシャルグラフとの関連が進むことはコミュニケーションサービスとしての観点からは間違いないだろうと考えます。

これはGoogle Social Graph APIやOpen IDなどによって単純なシェアリングブックマークやオンラインブックマークをソーシャルブックマークに変えることが容易になるだろうということからも考えられます。

また、分散しているブログコミュニティやモバイルコミュニティがブックマークではないにしろ、URLをシェアするサービスが出てきたときに偏った編纂者問題が複数のサービスによって解決されるという状況が想定できます。

これは専門家SBMなどの流れにも関連します。

ソーシャルグラフベースのSBMサービスが2ホップ圏内の情報をまとめることによっても偏った編纂者の問題は緩やかに解決されるとも考えられますが、既存のコミュニティからの脱却が難しく(はてな村からの脱走)、閉じられたまま収束する可能性も否定できません。

群発し、乱立し、多様化する状況になると1つの可能性としてはOnline Bookmark APIの方向性がありえるでしょう。

XML/RSSベース・JSONPベース、いろいろ方法はあると思いますが複数のブックマークサービスの統合管理ということも起こりうる未来でしょう。

また、既存のインフラ/ガジェットベースで競合が発生した場合を考えてみましょう。

携帯電話会社やIE8などが自動でWeb履歴の一部を秘匿とシェアを行えるサービスをビルドインしたらどうなるでしょう?

いままで、そのようなサービスをつかったことのないユーザが新たな文化圏を形成し、一気に既存のSBM市場を駆逐してしまったら?

あるいはその際にどこかの強力なサービスを買収・連携したら?

最後に

非常に楽しい勉強会でした。しかしP2P関係者多いなw

これを問題提起として、次のSBM勉強会がより高次なサービスの本質への議論へ進むことを望みます。

tomoさん、よろしくおねがいします><

]]>
http://yabooo.org/archives/109/feed 1
見るだけで生産性が10倍になる気がする16の番組 http://yabooo.org/archives/67 http://yabooo.org/archives/67#comments Thu, 08 May 2008 16:30:20 +0000 http://www.yabooo.org/archives/67 どうも、おひさしぶりです。ひろきのだいちです。
テレビ番組が面白くなくなったといわれて久しいですが、
根っからのテレビ世代だった僕らとしては
昨今のテレビ番組の劣化は悲しい限りです。

それでもなお面白い番組はたくさんあると僕は思うので、簡単に紹介したいと思います。
昔の番組や終わってしまった番組もいろいろとあるんですが、この動画サイト全盛の時代なので
うまいことやってください。

1.ガイアの夜明け
日経版プロジェクトXみたいな番組。役所広司が分裂することで有名な経済ドキュメント番組。
信じられないくらいたくさんの役所広司が出てくるのでオススメ。
・・・というのは冗談にしても1つにつき1つは気づきがあったりしてステキな番組です。

2.がっちりマンデー
マンデーとついているのに日曜日にやっている番組。
これを見て月曜日にがっちり儲けましょうという趣旨らしいが、いつも月曜日だと勘違いしてしまいがち。
年収は優に3000万を超えているはずなのに年収300万円時代の生き方を説く森永卓郎さんの素にちかい側面を見ることができる
面白い番組。毎回さまざまな角度からがっちり儲かるビジネスを紹介してくれます。

3.爆笑問題のニッポンの教養
天才大田光と怪物ウーチャカがさまざまな学問の権威とただ話し合うという番組。
大田とゲストがあつく語り合っているときに完全に興味を失っている田中に注目することで、
聞き流すということを学ぶことができます。

4.トップランナー

毎回、その業界のトップをひた走る孤高なアーティストの内面に迫る番組。
なんだかしらないけど、途中でお菓子を食べさせてくれる。
MCのあまり上手くない司会のおかげで全体的にゆるーい空気が流れるのが特徴。
NHKってこんなかんじだよなーってのを楽しむ番組。

5.そのとき歴史は動いた

歴史が変わる瞬間の出来事のあたりを大体1人の人物に
スポットを当てて紹介する歴史バラエティ。だれも「その時」に注目していないのに
「それでは、今日の"その時"です。」とずれた感じの引きを作るあたりNHKの丁寧な
仕事ぶりを感じる。


6.NHKスペシャル

ノンフィクション系ではフジのTHEノンフィクションも捨てがたいけど、やっぱりこっち。
ドキュメンタリー形式でワープアとか最近気になる世の中の側面を不安たっぷりに見せてくれる番組。
大体のフリーターは愛知県の自動車工場に消える。

7.ワールドビジネスサテライト

WBSの愛称で知られるテレビ東京の経済ニュース番組。トレンドのたまごという流行一歩手前みたいなものを
紹介してくれる。ある種マッチポンプともいえるがそこらへんのワクワク感を見事演出してくれる。

"トレたま"と省略させたいらしいが、いまだここらへんのマッチポンプは成功していない。


8.タモリクラブ

タモリという才能を日本に残してくれてありがとうございます。
と毎回感謝する番組。昔の深夜ラジオのノリをどんどん熟成していくとこんな味のチーズになるんだっていう
番組。尻が今はCGになってしまったが一部本物の尻もある。

"洋楽が好き"と嘯くひとの1割は空耳スト。

9.プロフェッショナル 仕事の流儀

さまざまな世界のプロフェッショナルたちが仕事に対する姿勢やジンクスを語る番組。
脳科学者がなぜかMC。それにしてもアハ体験って言葉はなんだか怪しい薬の気配がする。

10.10minボックス

10分間で学ぶ教養。中高生レベルで常識的なことも多いが10分間にまとめるという演出がステキ。

オンデマンドで見られるようになれば最高な番組の1つ。
11.フジテレビ批評

朝っぱらから自己批判。視聴者に対してよりもBPOに対して言い訳ばかりしているのが気になる。

1年に一度、芸人やタレントがびっくりするほど出てくる。一度、ハナエモリがBPOの委員会で
滝川クリステルのニュースを読む角度について文句を言っている映像が流れていたりして、
あー世の中ってこんなふうに動くんだなって思う瞬間。松本 方哉ファン必見。

12.たけしのコマネチ大学数学科
13.皆殺しの数学

大学生レベルの数学を扱っている数少ない番組たち。特に皆殺しの数学は10年以上前の番組なのにハイセンス。
フジテレビ深夜番組黄金期のJOCXジャングル枠の1つ。 DVDは出てないようなのでニコ動やyoukuなどでどうぞ。

14.たほいや
15.カノッサの屈辱

これもまたジャングル枠の番組。カノッサの屈辱は最近1回きりのリバイバルをしたので記憶に新しい人も多いかも。
この時代の番組は金がかかってなさそうでかかっている。バブルへGO!


16.鈴木タイムラー

もしかしたらもっともあげた中では知名度の低い番組かもしれない。
しかし、コアなファンを中心に人気の超深夜番組。

エアギターで有名な金剛地武志もこの番組でプチブレイク。
サブカルな雰囲気が好きなら是非DVDを。

途中から駆け足でしたが、まだまだ面白いテレビ番組は眠ってると思います。
あなたの好きなテレビをぜひ教えてください><

]]>
http://yabooo.org/archives/67/feed 0
Javascriptでカプセル化のコスト http://yabooo.org/archives/70 http://yabooo.org/archives/70#comments Thu, 07 Feb 2008 12:28:58 +0000 http://www.yabooo.org/archives/70 どうも、ひろきのだいちです。

Javascriptでカプセル化を実現する!の続編みたいなものです。

この記事を投稿したところ、chokodogさんから次のような指摘を受けました。
(コメントありがとうございます><)

カプセル化した場合、コンストラクタ内でメソッドが定義されているので、new するたびfunctionが定義され、prototypeで定義するよりメモリを多くとられてしまうということはないのでしょうか?

たしかにそのとおりです。

今回はカプセル化を先のような方法で行うとどのようなコストがかかるのかということ探ってみました。

メモリを使うのでは?ってどういうこと?

chokodogさんの指摘の意味を簡単に説明したいと思います。

まずは以下のjavascriptのプログラムを見てください。

JAVASCRIPT:
  1. //オブジェクトのプロトタイププロパティを設定
  2. Object.prototype.objprop=100;
  3. //Classオブジェクトの作成
  4. var Class=function(){};
  5. //Classのインスタンスオブジェクトの作成
  6. var instance=new Class();
  7. //Classプロトタイププロパティを設定
  8. Class.prototype.classprop=200;
  9. //instanceの
  10. instance.insprop=300;
  11.  
  12.  
  13. log(instance.objprop);
  14. //-->100
  15. log(instance.classprop);
  16. //-->200
  17. log(instance.insprop);
  18. //-->300
  19. log(instance.hasOwnProperty("objprop"));
  20. //->false
  21. log(instance.hasOwnProperty("classprop"));
  22. //->false   
  23. log(instance.hasOwnProperty("insprop"));
  24. //->false
  25. /*
  26.  ここでinstanceのプロトタイプチェーンをたどって
  27.  みつかったプロパティをOwnプロパティとして設定
  28. */
  29. instance.objprop=instance.objprop;
  30. instance.classprop=instance.classprop;
  31.  
  32. log(instance.hasOwnProperty("objprop"));
  33. // -->true
  34. log(instance.hasOwnProperty("classprop"));
  35. // -->true
  36. log(instance.hasOwnProperty("insprop"));
  37. // -->true

JavaScriptは通常のクラスベースのオブジェクト指向とことなりプロトタイプベースという別のプログラムパラダイムを採用しています。
JavaScriptのオブジェクトはすべてハッシュのようなものになっていますが、これに少しばかり細工がしてあります。

それがプロトタイプチェーンというやつです。

オブジェクトは、自身のプロパティで見つからないようなハッシュ値を自分自身のコンストラクタのプロトタイプへと探しにいきます。

たとえば、上のプログラムの場合、
objpropというプロパティを探しにいったときに

・自分自身のプロパティではない
・自分のコンストラクタのプロトタイププロパティではない。
・チェーンの終端であるオブジェクトのプロトタイププロパティで発見

というような順番で探っています。

しかし、次のようにするとプロトタイプ経由のプロパティを自分自身のプロパティとして利用することができます。

JAVASCRIPT:
  1. /*
  2.  ここでinstanceのプロトタイプチェーンをたどって
  3.  みつかったプロパティをOwnプロパティとして設定
  4. */
  5. instance.objprop=instance.objprop;
  6. instance.classprop=instance.classprop;
  7.  
  8. log(instance.hasOwnProperty("objprop"));
  9. // -->true
  10. log(instance.hasOwnProperty("classprop"));
  11. // -->true
  12. log(instance.hasOwnProperty("insprop"));
  13. // -->true

さて、プロトタイプチェーンの仕組みを踏まえて
次のようなプログラムを見てください。

JAVASCRIPT:
  1. /*
  2.     プロトタイプとしてメソッドを実装
  3. */
  4. Object.prototype.test=function(){alert(”hello”)};
  5. var t1={val:2};
  6. var t2={val:1};
  7.  
  8. // ===で同一のリファレンスか確認
  9. console.log(t1.test===t2.test);//true
  10.  
  11. /*
  12.     instanceのown propertyとして実装
  13. */
  14. var Class=function(){
  15. this.test=function(){alert(”hello!”);}
  16. }
  17. var c1=new Class();
  18. var c2=new Class();
  19.  
  20. //こちらは別のリファレンスになってしまう。
  21. console.log(c1.test===c2.test);//false

このように、オブジェクトのメソッドを定義する際に、
オウンプロパティとして実装する場合では、

2つのインスタンスの定義した関数のそれぞれのさすリファレンスがことなることがわかります。

リファレンスとはC言語でいえばポインタ。
つまりコンピュータのメモリ上の格納場所が異なるということです。

なので、

カプセル化した場合、コンストラクタ内でメソッドが定義されているので、new するたびfunctionが定義され、prototypeで定義するよりメモリを多くとられてしまうということはないのでしょうか?

冒頭のこのようなコメントを頂戴するわけです。
このコメントに対して、僕はあろうことか鼻くそほじるように
「トレードオフじゃないですか~。サーセンwwフヒヒ」(嘘おおげさ紛らわしい)と答えてしまいました。

やっぱりどのくらいコストがかかるのか確かめてみようと思い、実験を行いました。

実験内容

二つのjavascriptプログラムの実行時間とメモリ消費量を調べる。

JAVASCRIPT:
  1. /*
  2.     アンダーバー記法のクラス
  3. */
  4. //人間を作るときの関数(コンストラクタ)
  5. var Human=function(name,year){
  6.     this._year=year;
  7.     this.name=name;
  8.     this._checkEto();
  9. };
  10. //人間のDNA(設計図)を決める
  11. Human.prototype={
  12.     name:"",_year:1983,_eto:"亥",
  13.     //干支を生まれ年から計算する
  14.     _checkEto:function(){
  15.         this._eto=["子","丑","寅",
  16.             "卯","辰","巳",
  17.             "午","未","申",
  18.             "酉","戌","亥"][(this._year-4)%12];
  19.     },
  20.     //年齢を決める。
  21.     setYear:function(year){
  22.         this._year=year;
  23.         this._checkEto();
  24.     },
  25.     getYear:function(){return this._year;},
  26.     getEto:function(){return this._eto;}
  27. };

JAVASCRIPT:
  1. /*
  2.     クロージャによるカプセル化クラス
  3. */
  4. var Human=(function(){
  5.   var constructor=function(name,year){
  6.     var inner={
  7.       name:name,
  8.       eto:"",
  9.       year:year,
  10.       /*
  11.         private
  12.       */
  13.       checkEto:function(){
  14.         inner.eto=["子","丑","寅",
  15.           "卯","辰","巳",
  16.           "午","未","申",
  17.           "酉","戌","亥"][(inner.year-4)%12];
  18.       }
  19.     };
  20.     inner.checkEto();
  21.  
  22.     this.setName=function(name){
  23.       inner.name=name;
  24.     
  25.     };
  26.     this.setYear=function(year){
  27.       inner.year=year;
  28.       inner.checkEto();
  29.     };
  30.     this.getName=function(){
  31.       return inner.name;
  32.     };
  33.     this.getYear=function(){
  34.       return inner.year;
  35.     };
  36.     this.getEto=function(){
  37.       return inner.eto;
  38.     };
  39.   }
  40.   
  41.   return constructor;
  42. })();

この2つのプログラムの生成にかかるコストをこのような
プログラムをそれぞれに行い調査します。

JAVASCRIPT:
  1. for(var i=0;i<10000;i++){
  2. var x=new Human("DAICHI"+i,i);
  3. }

実行時間

# time js none.js
real    0m0.006s

# time js cap.js
real    0m0.007s

# time js underbar.js
real    0m0.007s

# time js c_cap_10000.js 
real    0m1.741s

# time js c_underbar_10000.js
real    0m0.867s

jsインタプリタにはspidermonkeyを使います。

none.jsはただjsインタプリタを起動するのにかかった時間をはかるために何も書いていないjsファイルをtouchして作っただけです。

読み込みにはそれぞれ0.001secしかかかっていません。
実行時間は10000個のインスタンス生成におよそ0.874秒のコストがかかっています。

ということは、カプセルかによって

87.4マイクロ秒

のコストが1つのインスタンス生成あたりにかかっているようです。

メモリ消費量について

次はメモリの消費量です。
これは昨日作ったfleafeedを使ってみます。
C言語でメモリ使用量をカウントする!

timeコマンドのオプション使えやって思った人は正しいんですが、
せっかくなので使ってみたくなっちゃったんだもん><

#fleafeed js none.js
< fleafeed >
-----------fleafeed results------------

--USING HEAP    :   48574 bytes

#fleafeed js cap.js
-----------fleafeed results------------

--USING HEAP    :   59641 bytes

# fleafeed js underbar.js
-----------fleafeed results------------

--USING HEAP    :   56019 bytes

# fleafeed js c_cap_10000.js
-----------fleafeed results------------

--USING HEAP    :12925508 bytes

# fleafeed js c_underbar_10000.js
-----------fleafeed results------------

--USING HEAP    : 1731685 bytes

とこんな感じ。

jsの実装はほとんどHEAPしか使わないので、HEAP領域のみをピックアップしてみました。

まず、読み込みにかかるコストの比較ですが

アンダーライン記法:11067 bytes
クロージャ記法	    :7745	bytes

あれ?なんかしらんけどクロージャ記法のほうが読み込みは少ないっぽいです。不思議。

次に生成1つあたりのメモリコストの違いですが
これはでかいですね。

これを計算してみると1つあたりのメモリコストは

1,110 bytes

となっているようです。およそ1kのメモリが余分に使われてしまうわけです。
これは確かにコスト高な感じはします。

富豪プログラミングをしたいひとにはオススメということで
どうでしょうか(泣)

]]>
http://yabooo.org/archives/70/feed 0
twitterの正しい使い方 http://yabooo.org/archives/68 http://yabooo.org/archives/68#comments Wed, 06 Feb 2008 15:11:50 +0000 http://www.yabooo.org/archives/68 twitter

どうも初めまして、ujihisaと申します。
いきなりですが、ここにtwitterというウェブサービスの“正しい”使い方を記したいと思います。

0. はじめに
知人が何人かtwitterをはじめることになって、twitterの使い方を簡単に教えたりしています。
何度も個別に教えるより一つの文章にまとめた方がとても効率がよいので、今回頑張って文章化してみることにしました。

twitterの“正しい”使い方を説明するにあたって、まず正しいという言葉を定義しなければなりませんが
ここでは「ujihisaの思考・行為は全て完全に正しい」という仮定のもとで話を進めていくことで
複雑な問題を回避するのが合理的かつ経済的ではないかと思います。

1. Following 30人
twitterをはじめると、まずは元々の知人を適当にfollowします。
そしてその知人がfollowしている人を適当にfollowします。
30人くらいになるまで頑張って続けます。

みんなの発言を読んで、気になったものがあればレスします。
携帯電話から利用する方法を学んで、電車の中でも発言するようにするといいでしょう。

ちなみにtwitterの読みは「とうぃらー」です。
ついったーとかとゅいったーは完全なる誤りです。

この後Follow人数が増えていくと、技術的な質問をすると
大抵は即座に返ってくるようになり、あなたの生産性が向上します。

twitterは不安定なサービスで、頻繁にダウンします。
ダウンしているのが通常の状態ですので、長期間安定動作していると
不安な気持ちになってくる…。そう、それこそが正しいtwitter使いの姿なのです。

2. Following 500人
じわじわとFollowする人を増やしていき、500人程度になるまで続けます。
followしている人のログを読むのがだんだんと厳しくなってきて、最終的には
ログを読むことを放棄するようになります。
この、“ログを読まない”ということが頭でなく心で理解できるようになるまで
習慣づけるのがポイントです。

電車の中で携帯でtwitterを覗くのも、みんなのログを追うためではなく
別の意味を持つようになるでしょう。

ustreamで自分を配信するのもよいでしょう。
配信するときには必ず素顔を晒しましょう。
声だけ配信とか画面だけ配信など、もっての他です。
女性の場合は必ず水着配信しなければなりません。
(例: まめこ)

3. 退会する
毎日朝6時までtwitterする生活が続き、生産性がはっきりと低下します。
twitter以外の何も考えられないような日常を送るようになったとき、
そのときがあなたの退会のチャンスです。

twitterはアカウントを取得して退会するまでがtwitterです。
まだ退会していない人は、真のtwitterを未だ体験していないモンキーです。
はやく退会しましょう。

]]>
http://yabooo.org/archives/68/feed 0
C言語で使用メモリをカウントする。 http://yabooo.org/archives/65 http://yabooo.org/archives/65#comments Wed, 06 Feb 2008 13:58:28 +0000 http://www.yabooo.org/archives/65 どうもひろきのだいちです。

最近、初心者にとっていちばんよい言語は・・みたいな話が出てますが、
いちばんよい言語というのはたぶん「近くに一番優しくわかりやすく丁寧に教えてくれる人のいる言語」だと思います。

別に言語なんて関係ないです。

でも、いろいろとできることが違うという意味ではC言語はすごいです。
今日はC言語を使ってプログラムの利用メモリを出力してくれるようなソフトを書いてみました。

はじめに

こんな風にランダムに生成した数字をquick sortして順番に出力するプログラムがあったとします。

$ ./qsort 10
      133557644      467172391
      587048537      700406542
      924651875      942877877
     1231884300     1236726036
     1563773570     1858205801

こんな風にランダムに生成した数字をquick sortして順番に出力するプログラムがあったとします。
これにfleafeedとつけるだけで・・・

$fleafeed ./qsort 10
      133557644      467172391
      587048537      700406542
      924651875      942877877
     1231884300     1236726036
     1563773570     1858205801

-----------fleafeed results------------
--USING STACK   :    1160 bytes
--USING HEAP    :       0 bytes
--ALLOC times   :       0
--FREE times    :       0

こんな付加情報を追加してくれるやつを作ってみました。

さらにただ、mallocして放置するというドSなプログラムを

C:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(void){
  4.    int i=0;
  5.    for(;i<100;i++){
  6.       void *p=malloc(100);
  7.       printf("%x",p);
  8.    }
  9.    printf("hello!world");
  10. }

試してみると・・・

-----------fleafeed results------------
--USING STACK   :    1076 bytes
--USING HEAP    :   10000 bytes
--ALLOC times   :     100
--FREE times    :       0

こんなかんじで、計算どおりヒープの数とmallocの数がカウントされてます。

これの作り方の前にちょっと基礎知識を。
わかる人は読み飛ばしてください。まちがった説明するかもなので><

スタックとかヒープとかってなに?

スタックとかヒープとかってのは、プログラムの管理領域であるメモリの役割につけられた名前です。

スタックは関数呼び出しや引数、関数内自動変数などを管理するメモリの領域です。
面倒なので、wikipedia先生に頼ると
スタック
コールスタック

こんなかんじのものです。

ヒープとは固定サイズじゃなくて自由に別途に確保できるところにあるメモリーです。
通常mallocでメモリーをもらってfreeで返します。

もらったものは必ず返さないといけないんですが、最近の言語ではGC(ガーベジコレクション)というステキ機能がついていて
変わりに返してくれます。連帯保証人みたいなひとです。

これだけだとあれなのでまたまた、wikipedia先生に・・
ヒープ領域
ヒープ構造

スタック編

理屈は簡単です。
一番最初に一度使われる前のスタック領域を俺色に染め上げて、
プログラムを実行し、なんらかの形で利用されると別の値になってしまうので
一番最後に俺色になっていないところの数を数え上げるという方法です。

そのために

C:
  1. #define FF_FIRST __attribute__ ((constructor))
  2. #define FF_LAST  __attribute__ ((destructor))

こんな宣言をしてmain関数より前に関数を実行させます。

C:
  1. #define FF_MAGIC 0xf1eafeed
  2. #define FF_MAX 1024*1024
  3. FF_FIRST int fleafeed_fillstack(){
  4.    int p[FF_MAX];
  5.    int i=0;
  6.    for(;i<FF_MAX;i++){
  7.       p[i]=FF_MAGIC;
  8.    }
  9. }
  10. FF_LAST void fleafeed_checkstack(){
  11.    int p[FF_MAX];
  12.    int i=0;
  13.    for(;i<FF_MAX;i++){
  14.       FF_USESTACK+=(p[i]==FF_MAGIC)?0:4;
  15.    }
  16. }

このときに埋め立てる値を0xf1eafeedとう値にしたので
このプログラムの名前はfleafeedになりました。

適当に16進数で表現できる8文字の英語をいれただけです。
意味はわかりません><

これで、スタックの仕様数はわかりました。
これを

$gcc fleafeed.c -share -fPIC -o libfleafeed.so

のようにしてコンパイルします。これでできたライブラリをリンクしてやれば、スタックの使用量がわかります。

次はヒープです。

ヒープ領域編

ヒープは、よほど無理をしないかぎり、mallocなどから呼ばれるのでこの関数をwrapperしてやればヒープの使用量はわかります。
というわけで、

C:
  1. void *malloc(size_t size){
  2.    FF_ALLOCCOUNT++;
  3.    FF_USEHEAP+=size;
  4.    return malloc(size);//本物のmalloc?
  5. }

というような感じでラッパしたいのですが、これだとmallocという名前が衝突してしまいます。
そんなわけで

C:
  1. #define GNU_SOURCE
  2. #include <dlfcn.h>
  3. static void*(*libc_malloc)(size_t);
  4. static void*(*libc_calloc)(size_t,size_t);
  5. static void (*libc_free  )(void *);
  6.  
  7. void *malloc(size_t size){
  8.    FF_ALLOCCOUNT++;
  9.    FF_USEHEAP+=size;
  10.    return (*libc_malloc)(size);
  11. }
  12. FF_FIRST int fleafeed_fillstack(){
  13.    libc_malloc=dlsym((void *)-1L,"malloc");
  14. }

こんな感じにdlsymのRTLD_NEXTをつかって、mallocのポインタをlibc_mallocという代理人にあずけておきます。
なぜかRTLD_NEXTが#defineされてなかったので即値で対応しました。

共有ライブラリを事前に読み込む

ソースコードがあればそこからビルドするときになんとかすればいいんですが、そうではないので事前にライブラリを読み込むようにしてコマンドを呼び出すという方法をとります。

alias fleafeed=LD_PRELOAD=./libfleafeed.so

こんなかんじに。LD_PRELOADはこのライブラリは最初に読み込んじゃって!という環境変数です。
これで準備は万端。

ためしにgccでコンパイルをするときの利用状況を見てみましょう。

$ fleafeed gcc test.c

-----------fleafeed results------------
--USING STACK   :    6072 bytes
--USING HEAP    :  832510 bytes
--ALLOC times   :    1776
--FREE times    :     833

-----------fleafeed results------------
--USING STACK   :    2272 bytes
--USING HEAP    : 1810165 bytes
--ALLOC times   :     863
--FREE times    :      48

-----------fleafeed results------------
--USING STACK   :    5980 bytes
--USING HEAP    : 1715525 bytes
--ALLOC times   :    1185
--FREE times    :     355

-----------fleafeed results------------
--USING STACK   :    2012 bytes
--USING HEAP    :   25998 bytes
--ALLOC times   :     128
--FREE times    :      35

-----------fleafeed results------------
--USING STACK   :    5840 bytes
--USING HEAP    :   33885 bytes
--ALLOC times   :     336
--FREE times    :     181

うわなんかいっぱい出たw

プロセス分だけ終わりがあるので、プロセスごとに出力されるようです。

最後に全体のソースコード。

C:
  1. #define GNU_SOURCE
  2.  
  3.  
  4. #include <dlfcn.h>
  5. #include <stdio.h>
  6. #define FF_FIRST __attribute__ ((constructor))
  7. #define FF_LAST  __attribute__ ((destructor))
  8. #define FF_MAGIC 0xf1eafeed
  9. #define FF_MAX 1024*1024
  10.  
  11. int FF_ALLOCCOUNT=0;
  12. int FF_FREECOUNT=0;
  13. int FF_USEHEAP=0;
  14. int FF_USESTACK=0;
  15.  
  16.  
  17. static void*(*libc_malloc)(size_t);
  18. static void*(*libc_calloc)(size_t,size_t);
  19. static void (*libc_free  )(void *);
  20.  
  21. void *malloc(size_t size){
  22.    FF_ALLOCCOUNT++;
  23.    FF_USEHEAP+=size;
  24.    return (*libc_malloc)(size);
  25. }
  26. void *calloc(size_t nmemb,size_t size){
  27.    FF_ALLOCCOUNT++;
  28.    FF_USEHEAP+=size*nmemb;
  29.    return (*libc_calloc)(nmemb,size);
  30. }
  31. void free(void *ptr){
  32.    FF_FREECOUNT++;
  33.    (*libc_free)(ptr);
  34. }
  35. /*void *realloc(void *ptr,size_t size){
  36. }*/
  37.  
  38. FF_FIRST int fleafeed_fillstack(){
  39.    int p[FF_MAX];
  40.    int i=0;
  41.  
  42.    libc_malloc=dlsym((void *)-1L,"malloc");
  43.    libc_free=dlsym((void *)-1L,"free");
  44.    libc_calloc=dlsym((void *)-1L,"calloc");
  45.  
  46.    for(;i<FF_MAX;i++){
  47.       p[i]=FF_MAGIC;
  48.    }
  49. }
  50. FF_LAST void fleafeed_checkstack(){
  51.    int p[FF_MAX];
  52.    int i=0;
  53.  
  54.    for(;i<FF_MAX;i++){
  55.       FF_USESTACK+=(p[i]==FF_MAGIC)?0:4;
  56.    }
  57.    fflush(stdout);
  58.    fprintf(stderr,"\n-----------fleafeed results------------");
  59.    fprintf(stderr,"\n--USING STACK\t:%8d bytes",FF_USESTACK);
  60.    fprintf(stderr,"\n--USING HEAP\t:%8d bytes",FF_USEHEAP);
  61.    fprintf(stderr,"\n--ALLOC times\t:%8d",FF_ALLOCCOUNT);
  62.    fprintf(stderr,"\n--FREE times\t:%8d\n",FF_FREECOUNT);
  63. }

]]>
http://yabooo.org/archives/65/feed 1