[PHP] optimization for shortening the API calls

最近為了降低API calls,所以在Shark內加入了一個Method可以讓使用者自行依自己的需要來延遲整個程式的執行:

http://gist.github.com/309735.js?file=gistfile1.php

參數是所需延遲的秒數,0就是不延遲。

雖然這裡沒有什麼技術上的難度,講白點就是丟給sleep()去跑而已,但是我想討論的是它所造成的影響。先看一下下面的統計圖:



2/14和2/15是平常的情況,所謂的平常就是用無窮迴圈去跑Bot,只算「登入」和「基本檢查」這幾個動作,而已,就會拉高整個呼叫API的情況,非常的跨張,這就是為什麼北極冰山快融化完的關係,因為大家只要寄個信給Plurk官方就可以突破原先50000次的限制,要怎麼用就怎麼用,非常爽快。

但是再看看2/18和2/19的時候,這是我讓Shark加入了延遲的動作,我記得是設3秒鐘,夠誇張吧,直接下降到23000的次數了,你連寫信去Plurk的動作都省下來了,還有27000次讓你做別的事情,這樣不是很開心嗎!? (大約下降了78%..),真是從小處著手,就有很大的改變呢…(忘了說,使用者很難感受到機器人回覆plurks的時間差,一樣很快)

所以麻煩大家不要一直用「while(true)」或是「for(;;)」這樣子的東西,要用的話至少也要加個中止條件或是延遲,不僅可以減少系統資源的開銷,還可以保護北極熊不會因此死光…

[News] Chatroulette’s Creator, Andrey Ternovskiy

From New York Times

這個網站最近在PTT的幾個大版都很常被討論到,我也自己下去玩了一下,先不討論裡面各種情色的問題,在這邊我想討論一下這個網站。

其實在他的個人讀白就有說到,原本對這個網站的構想起源是因為他常常和朋友用Skype用視訊,但是久而久之也就覺得有點無聊,所以想要加上了幾個元素,我覺得這個元素就是最重要的部分,一個是「隨機」、一個是「匿名」,這都是一般類似網站或是程式所沒有的元素,我覺得也是這兩個元素讓他大紅大紫。

先來看一下「隨機」這個元素好了,我一進去他的這個網站就覺得,這怎麼可以這麼新奇??真的,寫程式的人誰不會用「Random」,但是從來沒有看人可以把「Random」以這種方式來應用,他這個動作讓每個使用者都能夠有「自主
權」,怎麼說呢? 在那個網站是以隨機的方式來配對一組使用者,所以如果你不滿意這個結果,你可以按個按鈕就換人了,一來簡單,二來多了一點賭博的刺激感,因為誰不想要看到正妹和帥哥咧!?

再來就是「匿名」,大家可能會說,阿哪個聊天室不是匿名的咧,是呀,但是你現在在這個網站上面就只有兩個身份,一個就是「You」(對你自己來說),另外一個就是「Stranger」(對別人來說),這樣子的做法真的很特別,以前你可能還要打個什麼「乂煞氣a小子乂」這樣不會太蠢嗎,這種慾情故縱的做法,反而多增添了一點神秘感,讓人多了一點瑕想。

OK,說了這麼多,快去「Chatroulette(聊天輪盤)」玩玩看吧。

這邊是「New York Times」的原文,而以下是我對該篇文章的作者讀白所做的翻譯(藍色的部分是我覺得很重要的地方):

「一開始,我並沒有任何商業的目標,我只是因為好玩才創造了這個計畫,而我才剛完成這個網站。因為我是一個青少年,所以我對於其他青少年在網路上想要看到的東西有一定的感覺。我很喜歡和朋友在Skype上用麥克風和網路攝影機聊天,但是最後我們覺得有點膩了,所以我因此想要創造一個我和我朋友隨機互通的小網站。

要建這個網站對我來說並不容易,儘管我從11歲就開始寫程式了(一切都幸虧我爸很早就帶我到網路上去玩,而我大部分的知識都是從網路上來的)。

我原本並沒有幫我的網站到處廣告,但是不知道怎麼了,朋友們開始互相談論這個網站,也因為如此所以這個消息就開始散播了。這就是為何同時在線人數開始從10個人變成50個人,再從50個人變成100個人,並持續上升。每一次當使用者上升的時候,因為我的軟硬體都沒辦法應付這樣子的成長,所以我就要開始改寫我的程式碼。而我從來沒想過,應付大量使用者的這個負擔,會是這個計畫最困難的部分。

隨著使用者人數的增加,頻寬和主機所需支付的費用就開始增加,但我很高興我的親戚幫我個大忙,「投資」了一些錢在我的點子上。

但是那並不是一筆很大的金額,所以我沒有辦法去買新的伺服器,我只能開始盡我所能的最佳化我的程式碼。我必需說,有很多人都一直在程式方面幫了我很大的忙,因此我很感謝他們。目前我仍然是一個人在寫整個程式,我也想要分享一些工作給其他的人,但是因為我是住在莫斯科而不是美國,而大部分有興趣的人都住在離我很遠的地方,所以我還是得自己處理所有的事情,但是我並不擔心。

我很享受我所做的事情,它對我就像是一個遊戲一樣,我都會一直發現新的事情並解決有趣的問題。

現在『Chatroulette』使用了七部位於德國法蘭克福的高階伺服器,而流量是7GB/s,我用了各種不同的科技來讓使用的頻寬最小化,但是很多的頻寬還是消耗掉了。雖然帳單上寫的金額讓我很驚訝,但是我並不擔心。

我很高興人們對我的計畫有很大的興趣,而且我曾收過一些很有趣的奉獻讓我的計畫可以存活並改進。

我讓我網站上的廣告維持最少的數目,因為很多網站都充斥著一堆廣告,會分散你的注意力讓你不知道你原本想做什麼,而我個人也很喜歡極簡主義,這就是為什麼我只放四個廣告連結在網站下面,而有趣的是,光靠這四個連結,就能夠包下我所有的花費呢。

我覺得我可以不用放一大堆廣告就可以維持網站盈運真的是太棒了,也許是因為『Google AdSense』把連結秀在不同的視訊下吧,我並不認為這是一件壞事反而覺得很好,因為我認為只有對我網站沒有興趣或是感到膩了的人才會點那些連結,想要去探索看看有沒有什麼新的服務。

我察覺到『Chatroulette』在美國很紅,這是一件很有趣的事情,雖然我從來沒有去過美國。不過我大部分的使用者都是從那邊來,因此我還蠻想去美國看看說。

我真的想過如果『Chatroulette』能夠成為一個美國的公司會比較好,不過只是個想法而已。

我一直想要把『Chatroulette』變成一個全球化的東西,這就是為什麼我選擇德國放置主機,因為它是在俄國和美國的中間,而且它也是不同歐洲骨幹網路的中心,所以我覺得這裡是最好的地方,可以把世界上的人連結在一起。

然而,我也開始計劃要放置主機在不同的國家,這樣我就可以多加一些有趣且奇怪(好的方面)的特色,讓整個網站更充滿樂趣。

而現在真正阻礙我增加新的特色的原因是因為我還不確定『Chatroulette』到底是什麼樣的一個東西。

每個人都發掘出他們自己的方法來使用這個網站,有的人覺得它是一個遊戲,有人覺得它是一個未知的世界,還有的人認為它是一個交友的服務。

我覺得這個簡單的點子真的是很酷,而且對於很多人來說是有用的。雖然有的人不是以很好的方法來使用這個網站(我很反對這樣的方法),而其他人則是用它做出我難以想像的事情,他們用它來唱歌給陌生人聽,廣播他們自己的音樂。兩組不同的年輕人可以透過它來辦個聯合派對,以我看來這些都是些很棒的玩法。我很高興我做了這樣的一個計畫。

有自己的夢想最美,不是嗎?和大家共勉之。

[RoR] ActionMailer + Gmail +SMTP_tls = Amazing !

哦耶,今天一個下午在尋找和PHPmailer一樣的東西,讓我可以在RoR上面做到「註冊完自動回覆」的功能,中間參考了很多個站的教學,但是都一直實做不出來寄信的效果,就覺得很XX,結果皇天不負苦心人,我在一個國外的網站找到了實做方法也測試成功。

先註明一下環境:「Ruby 1.8.6」、「Rails 2.3.5」(後面有「Ruby 1.8.7」的做法)。

OK~GO,一開始先來去「ROOT/vendor/plugins/」,用下面這個指令把相關的資料抓回來,此時你的plugins下就會多出一個action_mailer_tls的資料夾了。
http://gist.github.com/306718.js?file=gistfile1.sh

再修改你的「ROOT/config/environment.rb」,把以下這段Code插在end之後,
http://gist.github.com/306694.js?file=gistfile1.rb

OK,大功告成,原本要用什麼sendmail還是什麼mail server才可以做到的事情現在單靠Gmail就可以做到,算是比較符合小型開發者的需求。那環境用好了,接下來就依官方教學設定自己的ActionMailer了。

一開始先產生我們的Model,
http://gist.github.com/306699.js?file=gistfile1.rb

好,原本的Model內容應該是空的,來加入一些我們的基本設定(官網的詳細介紹):
http://gist.github.com/306705.js?file=gistfile1.rb

現在Model做好了,要再為該Model下的Action做一個View(這邊很重要),我原本以為這個View可以不用做,結果我錯了,因為官方教學有寫到,這個就是信件的內容,所以如果你不產生這個View,就會出問題(之前就是敗在這),

在我的例子中,我的路徑是「ROOT/app/views/eat_me_mail/send_mail.html.erb」,這裡面就是你想寫的話啦,要寫什麼就隨便個人了,這邊就不多說明,最後就是和Controller合併起來。

這邊先引用一下官方的說明「You never instantiate your mailer class. Rather, your delivery instance methods are automatically wrapped in class methods that start with the word deliver_ followed by the name of the mailer method that you would like to deliver」,它的意思是說我們要在Method前面加上deliver_才能呼叫,在這大家就依自己的工作需求,呼叫自己的Method就可以傳送出去了,而下面是我的例子:
http://gist.github.com/306711.js?file=gistfile1.rb

到這邊,整個過程都已經結束了,如果你在讀取該Controller下的Action時有產生短暫延遲,就可以再去server看一下是不是有類似以下的訊息,如果都有的話,那就成功啦,耶斯!
http://gist.github.com/306715.js?file=gistfile1.txt

最後附上一張測試成功圖,我們下次見:D~


〈補充一下Ruby1.8.7的作法〉

因為工作上的關係,所以自己和伺服器的版本不同,所以在移植的時候出了很大的問題,雖然程式都沒有報錯,但是會發現信寄不出去,這真是一個很該死的問題,所以我又上網到處找資料,發現了原本的tls是給Ruby1.8.6版本用的,所以在1.8.7時就不能再用這個做法,所以要改用另外一個寶石。

http://gist.github.com/310748.js?file=gistfile1.sh

然後修改「ROOT/config/environment.rb」這個檔案的內容如下,
http://gist.github.com/310749.js?file=gistfile1.rb

OK,這樣就可以了,大概就是這樣啦:D~

[RoR] Rocks

好吧,我真的想說,RoR的Migrate和Scaffold這兩個東西實在是令我太吃驚了,我覺得大家應該都是衝著幾個好用的東西來玩RoR吧,先說說Migrate,它整合不同資料庫的語法,只要用RoR的專用寫法就可以通吃各大資料庫的格式,光是這點就很屌了(雖然我都是用MySqlXD),還有更屌的就是它加入了類似版本控制的功能,只要你「爽」,你要怎樣搞你的資料庫都可以!!

大家一定會說,這有什麼了不起的,我直接進資料庫改就好了,有什麼大不了的,哦不,那個鎖碎的動作現在都不用了,只要用Migrate的升級、降級,你要怎樣呈現你的資料庫都隨便你,什麼時候要新增或是刪除資料表也可以,要像玩仙境傳說Online一樣會回溯寶物都可以啦,這真的是太酷了!!

而Scaffold來建造CRUD的基本架構真的是很快(要改的多麼華麗就看個人了),以前都要寫個半死,現在只要幾個指令敲一下就通通跑出來了,省下很多不必要的時間,把這些時間拿去做一些比較深入的分析或是實作都比較划算,真的是很好用。

雖然現在還沒有玩的很透徹(我直接看官方API看了好幾天= =,因為台灣都沒有Rails 2.0以上的書,真是太該死了,就當練習吧! ),但是它基本好用的地方我已經了解到了,就差語法和API的呼叫就能夠比較上手了,加油!!

RoR Rocks => RRR

[RoR] 幹

為了這個東西,我不知道死了多少腦細胞,

一開始為了yml的問題,我不知道搞了多久,最後發現是Vim設定上沒有設好,導致RoR一直出錯,再來就是因為64bit和32bit的問題,因為「the Ruby interpreter bundled in XCode 3.0 is in fact only compiled as a 32-bit i386 executable」,很好,我用我的64bit版本的Mysql,就因為這樣死在這邊,GOOD。

最後把Mysql換回32bit,好棒,RoR終於可以讀Mysql的資料了耶~我的所有資料庫資料也因此全部消失了,耶~中間也花了好幾個禮拜的時間搞書和安裝設定一大堆相容性的問題,版本的差異也是個大問題,時間都不用錢的,超棒。

結論,為了這個RoR,我覺得,「得不償失」,幹。

[PHP] Shark – 整合性 plurk bot

圖 from here

這是我最近一直在做的東西,也許是因為之前「JaceJu」的那堂課讓我對物件導向的模式有點嚮往,所以就試著用用看物件導向的概念在這次的專案下,先來介紹一下這個玩具吧:

一開始我是看到朋友們一直在討論plurk bot這個玩具,所以就想說來做個什麼(其實我就是一個很怪的人,我很多做出來的小玩具都是因為看到人家的討論串才開始做的,而這次也不例外XD),因此就想打造一個整合性的plurk bot,而不是只為了特定功能而實作的東西。我想可能也是受到Hax4理念的刺激,為了製作出讓人家覺得有趣又好玩的東西,所以我們必需把最麻煩的部分都實現並封裝起來,就算使用者不是一個程式設計師(我也不是XD),也能夠輕易的上手,這就是我的想法。

實作的部分,因為我是在PHP下做的,所以就沿用官方認可的php-plurk-api,用他們已經實作好的API去和官方做溝通,這真的是省事很多,這樣我就不用自己刻一個爛爛的介面來用了,也提昇了穩定度。因此整個Shark class是直接繼承它的類別,再設計新的骨架在其之上,一來我可以開心的使用API,連第三層的使用者也能輕易的使用(繼承真的是很神,更神的是所有在plur-api下的Method都是protected的,大家都可以開心用XD),所以這樣一來我沒有破壞到它原始的架構,反而再多建了一些我想做的東西讓大家玩,這樣真酷!

講這麼多,快點上我在Github上的Shark專案把相關的核心抓下來玩玩看吧,忘了說,我本意是想讓大家都可以輕易做像是「小籤籤」的plurk bot,可以自動回覆一些特定資訊,而一些設定的細節就麻煩去看我寫好的說明啦,如果對這個專案有什麼建議的話,麻煩直接回信到我的信箱並在主旨打「About: Shark」,我就會盡快回覆你的。

感謝你的觀看XD。

δ 目前Shark有改版的資料並徵求有志之士來寫好玩的規則,請看站內的另一篇文
δ 整個專案是相容於php_plurk_api 1.4,但是目前最新是1.4.2版,這點要注意一下。

[Ruby] 8th word

不知道自己還會持續寫多久,雖然自己內心有千百個不願意學Ruby(就是單純不想而已,那個Fu不對),不過我還是會繼續加油的。就當作翻譯書吧XD…

現在要再延續上次講的equality。如果還有點印象的話,應該是談到「==」operator吧,既然有正就有反,當然有「!= (Not equal)」啦,書上說,只要原先的「==」operator有被定義的話,那麼這個operator就是把它的值做invert的動作,true←→false那個值互換,所以這在Ruby1.9之前,Ruby會自動把這個operator給你使用for free!!(前提是你有定義好其「==」的動作),而在Ruby1.9之後,類別可以自己定義自己的「!=」operator來達到自己想要的效果。

有時候很該死的就是會出現很多相似的Method,這真的是很煩,因為要了解他們之間那極度細微的差異,不過也不能怪誰,因為那是別人規範好的= =…

3.8.5.3 The eql? method

「eql?」是一個不做type conversion的Method,來看一下他和「==」的差別:

http://gist.github.com/293535.js?file=gistfile1.rb

原來如此呀,恩恩…

3.8.5.5 The =~ operator

這就酷了,看到這個就想起RE的日子,YES,這就是用在做Pattern matching的operator,被定義在String和Regexp的類別下,不過書上也說了這其實和equality沒有什麼太大的關係,只不是有個「=」就把它放在這邊XD,所以只要記得這是拿來做Regular Expression用的就好了,來個小例子,其他深入的後面再談:

http://gist.github.com/293540.js?file=gistfile1.rb

3.8.6 Object Order

這邊有一個好玩的東西叫做物件的排序,哇靠這是啥?我原本也不知道它想幹嘛,不過看一下書後就了解許多了。通常每個類別都會定義「==」來了解equality,而有些類別,還會定義「排序」。什麼意思咧,假設有BC兩個都是A類別的實體,我們可以定義說它那兩個實體是「相等」,還是B比C小。原本我看到這都傻眼了,這是什麼鳥,完全看不懂呀,但是它下面提到了「Number」這個類別就是一個很明顯的例子,整個一下子就通了!!!

怎麼說呢?因為萬物皆OO的Ruby,其實「數字(123)」個別都是一個物件呀,而我們的數字可以比大小,就代表在某些類別下是可以比大小的,因此在某一方面來說就是做了一個排序的動作,這樣子是不是就很好了解了!?

所以如果我們要在Ruby做「排序」這件事情的話,就要使用「」這個operator。「AB」代表說,如果AB就會回傳1。來看個例子:

http://gist.github.com/293542.js?file=gistfile1.rb

但是因為這個Operator不太直覺,所以類別都會再include「Comparable」模組來做混入(mixin),而它定義了這幾個operator如下:

http://gist.github.com/293543.js?file=gistfile1.rb

下面這個是我在說明內找到的一個還蠻容易看懂的範例,可以參考一下他是怎麼做到的:

http://gist.github.com/293545.js?file=gistfile1.rb

另外有一點雖然前面提過了,但是還是要注意一下,那就是Comparable模組沒有定義「!=」,不過Ruby會自動幫我們先做「==」的動作再把結果Invert,所以就免擔心啦。

最後要是書上提到的一個NaN的情況(0/0的時候),而比較的結果就請看一下Code啦:

http://gist.github.com/293547.js?file=gistfile1.rb

這邊來了一個問題,為什麼「nan.euqal?(nan)」的結果是True??沒錯,因為他們兩個都是指向同一個object,所以結果為真,這邊要注意一下!!

BTW,通常「==」會被覆寫掉,但是「Aobj.equal?(Bobj)」是不應該在子類別被覆寫的,這是說明上面特別強調的一點,還要再注意一下!!

就是這樣,這篇就先到這啦,我要來去玩了XD~

[ZeroJudge] p001 Minesweeper

最近又開始覺得很無聊,所以要回去寫題目來練習,剛好就拿ZJ2的Minesweeper來小試一下,

點我看題目

這個題目就是要實作簡單版的採地雷(概念上),所以還蠻有趣的XD。

P.S. 我發現我之前寫ACM的文章都是用code tag包起來,但是只要沒有相對應的Css來搭配就真的是什麼都顯示不出來,有夠給他難看的…我晚點再來把他們都放上gist!

http://gist.github.com/292438.js?file=gistfile1.hpp

[Ruby] 7th place

3.8.4 Object Class and Object Type

在這一大堆的Object下,要找到其所屬的類別還真的是有點麻煩,特別是我們又不知道有哪些類別的時候= =,所以還好萬物階OO的Ruby有提供了幾個Method來用,如果先前有留心例子的話應該都有看過了,不過沒關係,再看一下吧:

http://gist.github.com/292409.js?file=gistfile1.rb

酷哦,有看到的就賺到了,因為這邊除了Object#class這個Method外,還提到了Class#superclass這個Method,可以用串接的方式一直串下去,找到階層架構下最項層的Class直到nil。

但是在Ruby1.9下就有點不一樣了,Object在階層架構下不再是Root的角色(如上例):

http://gist.github.com/292412.js?file=gistfile1.rb

True,Object上面還有一個叫做BasicObject的parent class,再上去才是nil,這和Ruby1.8有點不一樣,可能要注意一下。這在後面的7.3還會有更詳細的說明,就先丟者吧XD

所以要判斷一個Object的類別就可以這樣做啦:

http://gist.github.com/292414.js?file=gistfile1.rb

當然也還有另一個選擇:

http://gist.github.com/292418.js?file=gistfile1.rb

當然,如果要再進階一點,你還可以這樣玩:

http://gist.github.com/292422.js?file=gistfile1.rb

大概了解了一下那些函式的玩法,這邊又提到一個「===」運算子可以代替「is_a?」這個Method,所以上面有用到該Method的都可以改成「===」來玩,在這邊有說到,不要了解該Object的類別,我們只要知道有哪些Method可以用就好了(暫時),要不然我們應該會陷入鬼影追追追的Loop吧XD。

另外如果我們想要知道該Object有沒有那個Method的話,可以這樣子測試:

http://gist.github.com/292427.js?file=gistfile1.rb

3.8.5 Object Equality

講完了一堆霧沙沙的Method,也只有等哪天真的要測試的時候會比較有用,不過就先記下來自己研究吧XD(懶人),在這邊要來討論一下比較Object的一些相同性。

3.8.5.1 The equal? method

這個「equal?」的Method是被定義在Object這個類別下,用來測試兩個值是不是參考到同一個Object用的,對於兩個不同的Object的話,就會回傳False,來看VCR:

http://gist.github.com/292433.js?file=gistfile1.rb

OH,MY,這個真是個經典的例子,如果在前面幾章的地方,我們有討論到字面上去宣告一個Object會產生的情形,就是每一個值都會參考到不同的Object,而這邊就是再次使用了這個例子來做說明,讓我們知道雖然兩個Object都叫做「Ruby」,但是其實是代表不同的「Ruby」,所以B、C都參考到了同一個「Ruby」,而A則參考到了另外一個,也就是為什麼一個euqal?的結果為False,另一個卻是True的原因了。

不過我們也可以用「==」來做到相同的事,只要A.object_id == b.object_id就可以啦,因為先前提到的,每個Object都會被授與一個Unique的Object Id,不知道大家還記不記得XD,還好我還沒忘記咧,差點就要被你們唬爛過去了QQ。

好啦,先玩到這邊,晚點再來寫別的內容,大家快去吃東西吧XD。