Monday, November 05, 2012

Java System Call problem -- in Linux

我們在Java裡面要做execution external command的時候通常會用到Runtime.getRuntime().exec("<你要執行的外部指令>"); 這個算是比較常見的做法,但是他有一些隱含的問題

Process p = Runtime.getRuntime().exec("ps -al");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
//然後讀取InputStream做分析…

這是通解,不過這有個很大的問題。事實上, Runtime.getRuntime().exec在Linux實作上似乎是採取fork()的方式。眾所皆知的是,fork的實作方法是duplicate parent PID的資源。這在小規模下其實不成問題,問題在於…當java memory佔用量很大的時候…

比方說,以我們這個case,2G。所以每call一次system call都會造成系統嚴重occupied。

目前我們是採用jni的方式,把system call轉移到c的部分去做。因為它是一個獨立的pid,所以不會因此而產生巨大的paging(這拷貝動作的paging實在很驚人)。這算是在java底下system call的小小(?)陷阱...

Sunday, May 27, 2012

Bohemian like you

昨天聽演奏會聽到一首老歌,叫做"Bohemian",馬上就讓我想到這首歌了 =P 這首歌我記得最早最早以前我剛聽到的時候,把它看成了"Behemoth like you"「如你一般的末日巨獸(或者貝希摩斯,如果你是個FF迷的話)」



原來某人體內的怪獸已經那麼大了(遠目)

我非常喜歡這首歌清淡平淡的味道。Why can't I just simply like you?





Bohemian like you
Dandy Warhols

You got a great car. 
Yeah, what's wrong with it today? 
I used to have one too, 
Maybe I'll come and have a look. 
I really love your hairdo, yeah. 
I'm glad you like mine too, 
See we're looking pretty cool. 
Getcha! 

So what do you do? 
Oh yeah, I wait tables too. 
No I haven't heard your band 
Cause you guys are pretty new. 
But if you dig on Vegan food. 
Well come over to my work 
I'll have them cook you something that you'll really love. 

Cause I like you, 
Yeah I like you. 
And I'm feeling so Bohemian like you, 
Yeah I like you, 
Yeah I like you, 
And I feel wahoo, wahoo, wahoo! 

Wait. Who's that guy just hanging at your pad? 
He's lookin' kinda bummed. 
Yeah you broke up that's too bad. 
I guess it's fair if he always pays the rent 
And he doesn't get all bent 
About sleepin' on the couch when I'm there. 

Cause I like you, 
Yeah I like you. 
And I'm feeling so Bohemian like you. 
Yeah I like you. 
Yeah I like you 
And I feel wahoo, wahoo, wahoo! 

I'm getting wise 
And I feel so bohemian like you. 
It's you that I want so please, 
Just a casual, casual easy thing. 
Is it? It is for me 

And I like you 
Yeah I like you 
And I like you, I like you, I like you, 
Yeah I like you. 
And I feel wahoo, wahoo, wahoo!

Sunday, May 20, 2012

Epicurean


其實我對很多美食主義者有意見。或者說,自稱是美食主義者的人有意見。

我尤其難以理解為什麼某些自稱美食主義者的會說「因為吃過了XXX店的OOO,所以其他的OOO我再也難以下嚥了」,這種跟許多壓根不懂咖啡的人硬說「市面上大多數咖啡簡直是黑苦的液體,根本不能喝」在自稱是咖啡鑑賞大師的人一樣等級。

先不談這些老兄大姐到底懂不懂咖啡,舌頭夠不夠天賦靈敏。事實上,假設真的是一個好的美食主義者,擁有如此有天賦的味蕾,那為什麼僅能嚐得出別人的缺點,卻無法分辨出它口中「不入流的貨色」有哪些特點,有哪些是別人沒有的味道呢?我不否認,你要我說屎有什麼別人沒有的香氣,我真的說不出口,不過要是有人覺得世界上如此多的廚坊(請注意,還沒夠格到稱為廚房),都只能作出這些人口中的屎,只有最高級的米其林餐廳做出來的鵝肝醬,這些人才能描述他有多香氣澎湃多美味...

我覺得這些人還是不要自稱美食家比較好,這種人我一般稱之為滿口屎味。

咖啡也是。我曾經喝過初學者手沖出過熱焦氣滿口的單品,也喝過真正的高手火候十足,賽風下水剛剛好時間的醇品。每滴咖啡,都有一定的特殊香氣,都有其他人做不出來的神奇口感。

噢我還不敢自稱咖啡達人,只是味覺靈敏了點。

Epicurean還有一個意思,就是享樂主義者。有篇很有趣的文章,我曾經分享給大家過。看看,是不是跟美食主義果然是該共用同一個單字呢? :)

同學,你其實可以不用周遊世界

可以不用去追求別人描述的所有人性解脫,再回來說台北空氣多汙濁,生活多繁忙,多世俗。當連路邊小店的特殊風味都沒辦法品味,當連附近的小山小水都沒有仔細觀察,那,你有什麼自信那麼可以自稱一個Epicurean? 還是只是一種自以為Epicurean的自High以及自以為的超脫感?

Tuesday, May 15, 2012

Roxette - She doesn't live here anymore

http://www.youtube.com/watch?v=LNcEQOVumYA


She Doesn't Live Here Anymore

Lyrics:Per Gessle Music:Per Gessle&Mats M.P.Persson

We grew up together, we've been here forever.
Barefoot in the summer, cold in stormy weather.
She taught me all there is, like magic and love,
lots of forgotten words.

But now, she doesn't live here anymore.
She's off and she's gone, she doesn't live here anymore.
I'm sorry that's all there is to it,
I'm sorry that's all.

She dressed just like a painter,
a female street Picasso and I,
I will remember the heaven in her laughter.

And the scent of her sweet perfume
when we made love under an August moon

But now, she doesn't live here anymore.
She's off and she's gone, she doesn't live here anymore.
I'm sorry that's all there is to it,
I'm sorry that's all.

But now, she doesn't live here anymore.
She's off and she's gone, she doesn't live here anymore
She's gone since long, so long, she doesn't live here anymore.
She took off and left home, she doesn't live here anymore.
I'm sorry that's all there is to it, I'm sorry that's all.
That's all.









我們曾經在一起成長,我們曾經決定永遠在這裡

夏天赤腳踩在沙灘上,冬天擁抱在暴風雪中

她教會了我一切,如魔幻般的愛情,無法用言語表達的感覺
但是,她再也不在這裡了
她就這樣像是消失在大氣一班,再也不在這裡了
我覺得很抱歉,真的,我非常的遺憾

她曾經穿得像個油漆工,跟我像是街頭藝人般的手拉著手
我永遠會記得她有如天堂般的笑容
我似乎想起了她熟悉的香氣 想起了我們在八月的滿月下纏綿

但是,她再也不在這裡了
她就如同大氣一樣的消失了,再也不存在於這裡
我感到很抱歉,我真的很遺憾。

她再也不在這裡了
她如同熄滅的燭火一樣消失在這裡
她已經好久,好久,再也沒有回到這裡
她就這樣捲起了衣衫,如同出遠門一樣,離開了這裡
我對她很抱歉,我很遺憾,就這樣吧。

Thursday, March 15, 2012

Java socket程式 -- 絕對避免println() / PrintStream!

我先簡要的說一下原因,internet protocol用來分隔的是CRLF(\r\n) 以及CRLFCRLF(後者用以區隔header跟content)。PrintWriter的println(以及所有stream family的println, 比方說PrintStream)所傳出的分隔都是依系統而變(也就是,很不幸,這個函數並不是跨平台)

珍惜生命 遠離println / printstream(全文完)

--------
基本上Client來說,看到這裡應該就夠了,下面是比較詳細的說明。換行(也就是println會幫你做的事情)會幫你插入一個換行符號,而這個換行符號在各個系統都不一樣,所以基本上各個系統輸出都不同。比方說Windows就是CRLF(難得反而windows是正統的) 而unix系的含OSX絕大多數都是CR。

這是java少數幾個無法跨平台的地方,你可以想像一下同樣一串碼

out.println("This is SPARTA!");

其實在Windows底下是輸出
This is SPARTA!\r\n
而Unix系卻是
This is SPARTA!\r

這個println如果是輸出到螢幕上的話,沒差,大家看起來都一樣
阿輸出到socket就有差了,後者readline會根本讀不到

那當然照慣例就要問了:那要怎麼辦?
簡單,out.print("This is SPARTA!\r\n");

當然,也別忘了out.flush();

請銘記在心,寫Java Socket程式絕對要遠離任何println/printstream,看到他請當瘟神一樣離開他

ok,接下來談談server對應的部分。事實上當你寫server的時候,很多時候你是沒得選擇的。根據我自己的經驗,會犯下這種錯誤的coder其實比率是相當高的,只是絕大多數都是在windows下作業跟跑server,有時候是一些3rd party,server來講你很難做些什麼。畢竟code不是你寫的,你也沒source code,你更沒辦法把寫client的人抓過來狗幹一頓(我個人是稱為「友善的爭論」XD)

既然改不了client,那我們只好改server,讓server吃得下這些錯誤的東西

在談讓server怎麼吃這些東西而不至於拉肚子以前,我先講個瘟腥小故事。

IE7以前的世界,事實上browser是非常「友善」的,友善到一些明明是錯的東西他照樣吃。比方說有<p>沒</p>,或者<body><p> ....... </body></p>照吃不誤。這樣其實大家寫code都很開心,問題是每個browser都用不一樣的方法去解譯它,所以造成了同一組code的效果不見得一樣。

這造成了html界的大混亂,也間接導致了嚴格規範的xhtml誕生。(不過這東西始終沒有來的及正式長大,就被html 5.0取代了)

請注意,我們現在做的事情就跟以前「友善的」server一樣,是不對的,但是這是一種沒辦法中的辦法

說穿了很簡單,我們改用一個字元一個字元的去讀它(沒buffer想必這會很耗力)。我們讀取到\r的時候,我們會打開一個flag, 然後將\r後面多寫一個\n,下一個如果是\n的時候我們就把flag關閉並且跳過這個\n,不是的話關閉flag繼續。

具體的code大約是這樣(我個人是用filterinputstream處理這種東西)

boolean LRFlag = false;
while(char input = in.read()) {
if(input == '\r') {
LRFlag = true;
out.write(input);
out.write('\n');
continue;
}

if(input == '\n' && flag == true) {
flag = false;
continue;
}

flag = false;
out.write(input);
}


繼承fliterinputstream在read裡面插入這一段(也有一種寫法是override skip(),方法大同小異,我是比較喜歡override skip()就是,不過這比較少為人知)

hope it helps