2013/05/28


なんびとたりとも俺の前は走らせねぇ
ガチバトルです。
rapidjson - A fast JSON parser/generator for C++ with both SAX/DOM style API - Google Project Hosting

Rapidjson is an attempt to create the fastest JSON parser and generator. Small but complete. Support...

https://code.google.com/p/rapidjson/
fastest をうたうとは度胸があるなーと思いながら、半信半疑で試してみました。
rapidjson も picojson 同様に、ヘッダファイルだけあればコンパイル出来る C++ 向け JSON パーサ(およびシリアライザ)です。
まずは rapidjson を使ったコード。
#include <rapidjson/document.h>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <time.h>

int
main(int argc, char* argv[]) {
  clock_t t;
  t = clock();
  for (int n = 0; n < 1000; n++) {
    std::stringstream ss;
    std::ifstream f;
    f.open("foo.json", std::ios::binary);
    ss << f.rdbuf();
    f.close();

    rapidjson::Document doc;  
    if (doc.Parse<0>(ss.str().c_str()).HasParseError()) {
      std::cerr << "parse error" << std::endl;
      return 1;
    }

    rapidjson::Value& entries = doc["entries"];
    int i, l = entries.Size();
    for (i = 0; i < l; i++) {
      std::cerr << entries[rapidjson::SizeType(i)]["title"].GetString() << std::endl;
    }
  }
  std::cout << "score: " << clock() - t << std::endl;
  return 0;
}
そして picojson を使ったコード #include <picojson.h>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <time.h>

int
main(int argc, char* argv[]) {
  clock_t t;
  t = clock();
  for (int n = 0; n < 1000; n++) {
    std::stringstream ss;
    std::ifstream f;
    f.open("foo.json", std::ios::binary);
    ss << f.rdbuf();
    f.close();

    picojson::value v; ss >> v;
    picojson::array a = v.get<picojson::object>()["entries"].get<picojson::array>();
    int i, l = a.size();
    for (i = 0; i < l; i++) {
      std::cerr << a[i].get<picojson::object>()["title"].to_str() << std::endl;
    }
  }
  std::cout << "score: " << clock() - t << std::endl;
  return 0;
}
picojson については、std::for_each を使っても見たけど結局自前ループで回した方が速い結果になりました。

コンパイルは両者とも g++ -std=c++11 -O2 foo.cxx でやりました。
読み込んでる JSON はこれを使いました。ウチのサイトの JSON 形式のフィードです。やってる内容は
  • ファイルを読み込む
  • パースする
  • entries の一覧を取る
  • 各 title の内容を標準エラーに出力する
これを1000回実行します。標準エラーは捨てながら計測しました。

結果は以下の通り。 rapidjson score: 3559
picojson score: 7961
こうなりました。picojson と比べて rapidjson がほぼ2倍速いという結果になりました。速い理由をソースを見ながら調べてみましたが、rapidjson は STL を使わず、自前で DOM ライクな API を提供しています。また std::string なども使いません。これによってオーバーヘッドを最小限に抑えているのだと思います。
もちろん、picojson の STL フレンドリも僕は好きですし、他の C++ ライブラリと連携する際にも便利です。

Performance - rapidjson - Compares some performance benchmark results of rapidjson 0.1 and other parsers. Also gives some analysis. - A fast JSON parser/generator for C++ with both SAX/DOM style API - Google Project Hosting

Why rapidjson is fast? rapidjson has made use of several techniques to achieve high performance. C++...

https://code.google.com/p/rapidjson/wiki/Performance
それどころか、このスコア表を見ると picojson のスコアは素晴らしいレベルだと分かりました。
唯一難点として rapidjson は確かに速いのですが、パースエラー詳細に取る方法が分かりませんでした。(あるのかもしれません。知ってる人いたら教えて下さい)

という事で、これからも picojson 使って行こうと思います。
Posted at by



2013/05/16


IRC クライアントを使って lingr 上のコミュニケーションを楽しむ場合
ruby であれば lig.rb
psychs/lingr-irc - GitHub
https://github.com/psychs/lingr-irc
perl であれば lingr-ircd
tokuhirom/lingr-ircd - GitHub
https://github.com/tokuhirom/lingr-ircd
がありますが、Go言語にもあるべきだろ!と思ったので書きました。
mattn/go-lingr - GitHub
https://github.com/mattn/go-lingr
まず IRC に関係なく Lingr API を操作するライブラリ。そしてそれを使って IRC サーバと見立てる lingr-ircd を書きました。
lingr-ircd は go-lingr の中に含まれています。

API キーをお持ちの方は下記の様に指定して下さい。
$ lingr-ircd -apikey="XXXXX" これであとはお好きな IRC クライアントから 26667 番ポート(-addr=":26668" の様に変更可能)に接続して lingr をお楽しみ下さい。

ちなみに lingr で Go言語 の部屋が無かったのでさっき作りました。
Go言語 – Lingr
http://lingr.com/room/golang
ゆるふわと、Go言語について語りましょう。
Posted at by




スクレイピング等を行う場合、スクリプト言語が大きく威力を発揮します。 例えばブログの様にタイトルと本文の組が反復される様なページをスクレイピングする場合
  • URLからHTMLを得る
  • HTMLからDOMオブジェクトを得る
  • エントリとなるDOMノードを検索する
  • エントリノードでループする
    • エントリノードからタイトルとなるDOMノードを探索しテキストを得る
    • エントリノードから本文となるDOMノードを探索しテキストを得る
この様になるかと思います。こういった処理を一般的なコンパイル型言語を使って実行しようとすると
  • エラーチェック
  • 反復処理
  • 検索処理
といったコードをゴリゴリ書かなければいけなかったりします。もちろんそれ専用のライブラリを使えば出来きますが、コンパイル型言語ではなかなか良い物がないのは事実です。javascriptに到っては jQuery を使えば簡単に出来ますが、コンパイル型言語向けのライブラリではどうしても jQuery の様に柔軟に操作が出来る物がありませんでした。
しかし最近見つけた goquery は jQuery に似せており、コンパイル型言語でありながらも jQuery に似たコードを書く事が出来ます。
PuerkitoBio/goquery - GitHub

goquery - a little like that j-thing, only in Go GoQuery brings a syntax and a set of feat...

https://github.com/PuerkitoBio/goquery
ドキュメントは以下にあります。
goquery - GoPkgDoc
http://go.pkgdoc.org/github.com/puerkitobio/goquery
今日はこれを使って、最近デザインを一新した favstar のページをスクレイピングしてみました。 package main

import (
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "strings"
)

func main() {
    doc, _ := goquery.NewDocument("http://favstar.fm/users/mattn_jp/")
    doc.Find(".fs-tweet").Each(func(_ int, s *goquery.Selection) {
        fmt.Println(s.Find(".fs-tweet-text").Text())

        s.Find("div[data-type='favs']").Each(func(_ int, s *goquery.Selection) {
            fmt.Printf("FAV(%s): %s ...\n",
                s.Find("li.fs-total").Text(),
                strings.Join(s.Find("a").Map(func(_ int, s *goquery.Selection) string {
                    a, _ := s.Attr("title")
                    return a
                }), ", "))
        })
        s.Find("div[data-type='retweets']").Each(func(_ int, s *goquery.Selection) {
            fmt.Printf("RT (%s): %s ...\n",
                s.Find("li.fs-total").Text(),
                strings.Join(s.Find("a").Map(func(_ int, s *goquery.Selection) string {
                    a, _ := s.Attr("title")
                    return a
                }), ", "))
        })

        fmt.Println()
    })
}
短いですね!実行結果は以下の様になります。 今までで一番ひどい状況だったのは、火消しで参入したプロジェクトで「コードはどこにありますか」と聞いたら「まだ1行もない」という返事だった事かな。ウンコなコードすらなかった。
FAV(129): @uk_ar, @tyru, @IKANZAKI01, @29_104, @rhythmredbeatbk, @puso_770, @Okayu_AS, @dolly380505 ...
RT (203): @j24cape, @rhythmredbeatbk, @logicaldrive, @AnotherSpooky, @ChocolatGato, @dolly380505, @mousecollector, @yuji_developer ...

そろそろ anonymous にお願いする団体、tanomimous (たのみます)が登場する予感。
FAV(89): @yuji_, @kawauso, @chilalausunai, @_michiamolaura, @ItaiHenter, @a1t0o, @WizardOfPSG, @GearMann ...
RT (227): @JiaYue, @OkibiWorksLabo, @AZliebeP, @mol_jhd, @omnibus889, @acubi_, @chibiyamaA112, @ken1479 ...

Go言語はコルーチンをgoroutine(ゴルーチン)として実装したので F# にはぜひフルーチンとして実装してほしい。
FAV(58): @hoo89, @takuan_osho, @shimozan, @ramusara, @JapTagussan, @wo_M, @TABERO, @sekimiya ...
RT (85): @wtokuno, @cinnamon409g, @kazuta46, @ide_an, @2k0ri, @JapTagussan, @st_sady, @favstar50_ja ...

俺「Vで始まってmで終わる言葉ってなーんだ」 彼女「えーとVi...、いわなきゃダメ?」 俺「ダーメ(・∀・)ニヤニヤ」 彼女「vimshell: shell on vim」 俺「え?」 彼女「vimshell」 俺「貴様まさか!」Shougo「そのまさかだ!ふははは!」
FAV(76): @hakunyan01_p, @HCOOH_2, @__papix__, @econoholic, @ibukiwatermelon, @symmet, @azyobuzin, @tayashin ...
RT (55): @monmon326, @bimalki, @A_ir_jun, @ImpureSilver11, @aragasu, @PowerPC7450, @kenkov, @yuscarlet_tkb ...

Emacsユーザーに拡散されてるけど何か用?Vim愛好家いびって楽しい?ウチのバックにはShougoっていうヤバい変態がついてるから。覚悟しといてね。遊び半分でうちら怒らせると関係ない勉強会で歌っちゃうよ?【要出典】
FAV(47): @nolze, @teotr, @sio2381, @nulltrashcan, @NA_geek, @yogata, @jiroukaja, @CD01_ ...
RT (57): @takuan_v2, @dice_zu, @ucq, @nakj, @yoshikaw, @sgur, @yogata, @taniatsu ...

「俺はVimmerだぞ」「おまえらとは格が違う」酔ってESCキーを連打、テキストファイルに暴行
FAV(48): @takashiyoshida, @teriyaki0519, @toby_net, @komiyatatsh, @RATATATO, @2n_mit, @mugijiru, @cucmberium ...
RT (53): @got4416, @JiaYue, @SkySh, @teokure_miku, @carme16d, @kuro_7_nyan, @mtk0308, @mayahu32 ...

時間あったらコード書け。コード書いてる時間無かったらコード読め。コード読んでる時間無かったらアイデアを妄想しろ。アイデア妄想してる時間無かったら、君はこの業界に向いてない。
FAV(41): @hutyao, @KazusanTw, @setoh2000, @kisaramatsui, @myu65_laurant, @kimuraya, @withgod, @tezzsy ...
RT (52): @clicktx, @quoli_1289, @nu11p0_6477, @terra_75, @psycho_weirdo, @Guttyo, @satoapp, @masa711115 ...

技術で有名になるには3つ方法がある。1つ目は人の気付かない物を見つける。2つ目は人が面倒臭がってやらない事をやる。3つ目は奇行に走る。
FAV(39): @Cside_, @ym_428, @cpp_akira, @tyru, @Utori_2, @HEXwrench, @kagiminori, @hazeseki ...
RT (53): @tenn_real, @2784k, @bleutruth, @tabihato, @kickun, @_baruth, @ico390, @tw0gm0w ...

物凄く良い記事。僕も英語下手だけとバグ報告等してきたしこれからも変わらない。ちなみに僕はVimの作者にC言語が僕らの共通言語だって言われた。 / 酷い英語をもっとお願いします|gihyo.jp … 技術評論社 http://htn.to/kXmtNJ
FAV(36): @ma_shimaro, @ramusara, @super_rti, @ryochack, @Pandora_Ovis, @sizenote, @chairisu, @rane_hs ...
RT (44): @chairisu, @rezoolab, @nezucchi_bot, @PowerPC7450, @gu4, @amaika, @gakutarou, @justice_max ...

昔いた会社の先輩がC言語のcharポインタのポインタを「キャラポイポイ」と言ってたのが未だに脳の片隅にいて消えない。
FAV(33): @owatonmaster, @kashiken, @dooriver, @ussrmichi, @beikome, @umezawa_takeshi, @hop07, @ZeitungM ...
RT (42): @yuki_B, @alto_colony, @idzuna_, @umezawa_takeshi, @hotwatermorning, @sempreff, @hop07, @hugakusan ...

go言語にどデカイ修正が入りました。今までエラーの型はos.Errorを使って来ましたがerrorというプリミティブな型に変更となります。おそらくエラーを扱っている全てのプログラムソースが影響します。 #golang
FAV(19): @yoya, @mfks17, @neguse, @sanemat, @titoi2, @golangjp, @mataka, @ts7i ...
RT (53): @noritaka_okabe, @yohgaki, @ttyokoyama, @zai2kun, @Desigrammer, @mattarijinsei, @xga, @tmybj ...

伝説のプログラマと言えば昔、とある個人事業主に1人月程度の仕事を発注して、期日の5日前に打ち合わせしたいと言われたので呼んだら「仕様を確認しに来ました。まだ作ってません。」って言われた事があった。以後その個人事業主は会社で伝説になった。
FAV(29): @takanori80, @jiikko, @ryo_dg, @tomatosuperyami, @ZeitungM, @tanabe_y, @mhiki, @tmd45 ...
RT (42): @skychibi, @chibiyamaA112, @5Further, @7aguchi, @ryo_dg, @tori_555, @tanabe_y, @daybreak_dawn ...

10年かけてC言語覚えた人より3年でC言語習得した人の方がすごいと思うし、「年数多い=良い」がいかにも「老舗=安心」大好きな日本人脳だな。海外に行くと「10年も掛かったの?」って言われそうだな。
FAV(30): @wyveelix, @yustoris, @mohammedari, @Ramencozo, @m13979201, @nobyuki, @Candle0728, @GPS_NMEA ...
RT (32): @ao_god, @junclowd, @Moosan63, @alucky0707, @RiO_2121, @noshi_296, @Todachii, @oyomeni_onihime ...

たまに営業が「この案件COBOLが絡んでるから、出来るオッサン連れてくる」とか言ってるけど、いつか「この案件C言語が絡んでるから、出来るオッサン連れてくる」と言われる日が来る。そして呼ばれるのは君だ。
FAV(20): @guldeen, @sst8024, @ayasanxxx, @nonakap, @gnue, @MatsumuraKs, @cobodo, @potechi_live ...
RT (40): @DJ_HIKOZA, @sugo__, @guldeen, @Kazzforze, @ariaribababa, @osito_kuma, @toronei, @shunuhs ...

UDID: 「You did」、日本語で「お前、やっちまったな」の意味
FAV(26): @goya4, @IZUMI162i6, @Utori_Z, @hkoba, @seaki, @sleepydog_tsjp, @dw3w4at, @shintaks94 ...
RT (34): @IZUMI162i6, @mizoken001, @alexielseraphin, @yokook, @daga_kotowaru, @nagowl, @lamaille_mayuko, @dw3w4at ...

vim-jpはスキあらば暴走する数名のpatch書きと、いつもその暴走を止める1名で構成されていますが、暴走を止める人がいないとこうなります。 https://t.co/06BrJJtU
FAV(16): @hogedigo, @ikk775, @na4zagin3, @plaster, @h_east, @ToQoz, @giw, @glidenote ...
RT (39): @kikuchan98, @rohinomiya, @na4zagin3, @yosida95, @teyosh, @ksaito8, @sol_ursus, @chiastolite ...

Vim人Tシャツ着た人とEmacs人Tシャツ着た人が街中ですれ違いに肩当たって一触即発みたいな映画観たい。 #仁義無きテキストエディタ
FAV(25): @sayu2144, @_keichi_, @takehiro0740, @hecomi, @fu_ryukei, @EiM_GTPE_, @yoshihiro503, @todesking ...
RT (28): @Mrk1869, @takehiro0740, @sasex3, @nihonhanako, @fu_ryukei, @mazda_six_wgn, @yoshihiro503, @k_somemo ...

mrubyが人気 → mrubyの開発が盛んに → rubyを上回る性能 → rubyの中身をmrubyで入れ替え → 「俺、rubyがmrubyになる前から触ってたわー。」 #地獄のルビ沢
FAV(12): @gengorou_game, @viperbjpn, @zerobase, @ne_sachirou, @murasaki8823, @hiroshiyui, @asip2k25, @numpad0 ...
RT (41): @gengorou_game, @u1, @jacopen, @slm_sum, @atsu_kaya, @mizlogisan, @coddledegg, @snjx ...

「vim はカスタマイズしない様に気をつけてる。」「vim は vi として使ってる。」って人は、我慢してるだけなんだ!本当は羨ましいんだ!vimrcを一日中弄っていたいんだ!そんな事気にせずこっちの世界に飛び込んでくればいいんだ!そして共に奏でよう!崩壊へのエチテュードを!
FAV(22): @MomoVD, @koiwakawa, @ne_sachirou, @fks_sdk, @ndxbn, @ymnttt, @bleuscr, @mihyaeru21 ...
RT (30): @luyikei, @guitarrapc, @fks_sdk, @ndxbn, @sig_P241, @ymnttt, @virusVer001, @bleuscr ...

今すぐフォローすべき眼鏡っ娘エンジニア http://bit.ly/kgJWyE
FAV(11): @pmakino, @kuririso, @T0SHI3, @mainyaa, @kenmoto0716, @taki345, @sans_helvetica, @clworld ...
RT (40): @tetsuo6666, @N_YAMAMURA, @sayama_yuki, @shmorimo, @_iro, @ATA911, @ukstudio, @tomesode ...
どうでしょう。結構 jQuery に似ていると思いませんか? Each や Map を使ってDOMノードを文字列配列に変えられるあたりかなり便利ですね。
これを goquery を使わず行おうと思うとこの量のコードでは済みませんし、ちょっと嫌になってきますね。今後もスクレイピングを行う際にはぜひ goquery を使って行きたいと思います。
Posted at by