2010年9月2日 星期四

ChromeExtension: WebMomcat

WebMomcat 是 Momcat 的加強版, 增加了遠端監控的功能

啟動遠端功能:
1. 按 "Remote Config"

2.輸入一組新的帳號密碼

3. 按 "Enable Remote", 如果有顯示"啟動遠端功能成功", 就代表執行成功

4.http://webmomcat.appspot.com/ 並且輸入剛才的帳號密碼, 就可以開始監控


2010年8月27日 星期五

ChromeExtension: Momcat

最近在研究 HTML5 的新功能, 所以做了一些練習,
順便寫了一個 Google Chrome Extension: Momcat

這邊就介紹一下 Momcat 可以幹麻吧

用途: 監控你的小孩去過哪些網站

使用方法:
1. 開啟監控: 在瀏覽器列輸入暗號 blacksheepwall 就會開啟監控視窗

2. 在無痕式視窗要做監控的話, 必須先到 chrome://extensions/ 點選 [Allow in incognito]

3. 遠端監控功能: 請使用這個版本 WebMomcat


開發的過程中發現, HTML5 真的有很多好用的功能:

1. 超好用的 Local Storage:
以前 WEB 上相關的設定參數, 都可以暫存在 Cookie, 如: 查詢一次要顯示 50 筆資料...etc
不過, 一但 User 清除了 Cookie, 那這些重要的資訊設定, 就都不見了, 所以勢必需要再找一台 Server 來存放這些相關的資訊, 重新同步 Cookie 資料.
但是有些工具式的 WEB, 並不希望 User 作 Login 的動作, 所以根本無法保留這些參數設定, 只能要求 User 重新設定. 這時候 Local Storage 就派上用場囉~
而且 Cookie 在每次 Request 時, 都會一併附在 Request 封包裡面, 如果 Cookie 儲存的資料量太大的時候, 更會造成 Network/Server 的負擔

2. 神奇的WebSocket:
基本上就是走持續性的 TCP/IP Socket, 不過必須走 WebSocket Protocol, 所以 Web Server 也必須支援才行. 這次我試用 Jetty7, 用起來還蠻簡單的, 不過手邊的幾台 Server 都擋了這個 Protocol. 所以暫時就先不用了.

3. CSS3
這就不多說囉, 不用用 plugin, 就可以美美的, 當然很不錯啦 ^O^

2010年7月25日 星期日

Appengine程式碼分享

1. AppEngine整合Spring+JPA  文章 下載程式碼
2. AppEngine整合Struts2+Spring+JPA 文章 下載程式碼

AppEngine整合Struts2+Spring+JPA

STEP 1. 事前準備
1. 請先參考AppEngine整合Spring+JPA
2. 本範例是用Struts2.1.8, 建議是用一樣的版本, 比較不會有問題,下載之後把下面這些JAR檔, 放到Lib裡
  • commons-fileupload-1.2.1.jar
  • commons-io-1.3.2.jar
  • freemarker-2.3.15.jar
  • ognl-2.7.3.jar
  • struts2-core-2.1.8.1.jar
  • struts2-spring-plugin-2.1.8.1.jar
  • xwork-core-2.1.6.jar

STEP 2.因為GAE安全的設定比較嚴謹, 所以必須修改安全設定, 這裡是依照官網的討論用Listener的方式去修改
gae.InitListener

package gae;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import ognl.OgnlRuntime;

public class InitListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {
    public void contextInitialized(ServletContextEvent arg0) {
        OgnlRuntime.setSecurityManager(null); 
    }
    public void contextDestroyed(ServletContextEvent arg0) {}
    public void sessionCreated(HttpSessionEvent arg0) {}
    public void sessionDestroyed(HttpSessionEvent arg0) {}
    public void attributeAdded(HttpSessionBindingEvent arg0) {}
    public void attributeRemoved(HttpSessionBindingEvent arg0) {}
    public void attributeReplaced(HttpSessionBindingEvent arg0) {}
}


STEP 3. 修改 Action 及相關的設定
1. 修改 Action: fattom.riddle.TestAction

package fattom.riddle;

import java.util.List;
import fattom.riddle.dao.UserDao;
import fattom.riddle.entity.User;

public class TestAction{
    private UserDao userDao;
    private String name;
    private String action;
private List users;

    public String execute() throws Exception {
        if (name != null) {
            User tmpUser = new User();
            tmpUser.setName(name);
            userDao.persist(tmpUser);
        }

        users = userDao.findAll();

        if (action != null && "delete".equals(action)) {
            for (Object user : users) {
                userDao.remove((User)user);
            }
        }
       
        return "success";
    }

    public void setUserDao(UserDao userDao) {this.userDao = userDao;}
    public void setName(String name) {this.name = name;}
    public void setAction(String action) {this.action = action;}
    public List getUsers() {return users;}
}



2. 新增struts設定檔: src/struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="false" />

    <package name="default" namespace="/" extends="struts-default">
        <action name="test" class="fattom.riddle.TestAction" method="execute">
            <result name="success">/WEB-INF/success.jsp</result>
        </action>
    </package>
</struts>


3. 新增Action回應的VIEW: /WEB-INF/success.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
    <title>Hello App Engine</title>
</head>
<body>
    <s:iterator value="users">
        <s:property value="id"/>/<s:property value="name"/><br>
     </s:iterator>
</body>
</html>



4. 修改web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
    <listener>
        <listener-class>gae.InitListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

2010年7月23日 星期五

AppEngine整合Spring+JPA

STEP 1. 事前準備
1. 先準備AppEngine SDK1.3.5版以上
2. 本範例是用Spring 2.5, 建議是用一樣的版本, 比較不會有問題,下載之後把下面這些JAR檔, 放到Lib裡
  • aspectjrt.jar
  • aspectjweaver.jar
  • cglib-nodep-2.1_3.jar
  • commons-logging-1.0.4.jar
  • spring.jar

STEP 2. 建立Entity, DAO, Servlet
1. 建立本範例中的Entity: fattom.riddle.entity.User

package fattom.riddle.entity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}


2.建立DAO: fattom.riddle.dao.UserDao

package fattom.riddle.dao;

import java.util.List;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import fattom.riddle.entity.User;

public class UserDao extends JpaDaoSupport {

    public void persist(Object user) {
        this.getJpaTemplate().persist(user);
    }
 
    public void remove(Object user) {
        User result = this.getJpaTemplate().find(User.class, ((User)user).getId());
        if(result != null)
            this.getJpaTemplate().remove(result);
    }
    @SuppressWarnings("unchecked")
    public void removeAll() {
        List result = this.getJpaTemplate().find("select e from fattom.riddle.entity.User e");
        for(Object user:result) {
            this.getJpaTemplate().remove((User)user);
        }
    }

    @SuppressWarnings("unchecked")
    public List findAll() {
        List result = this.getJpaTemplate().find("select e from fattom.riddle.entity.User e");
        result.size();
        return result;
    }
}


3. 建立Servlet: fattom.riddle.TestAction

package fattom.riddle;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import fattom.riddle.dao.UserDao;
import fattom.riddle.entity.User;

@SuppressWarnings("serial")
public class TestAction extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        PrintWriter out = response.getWriter();
        response.setContentType("text/plain");

        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        UserDao userDao = (UserDao) context.getBean("userDao");

        if (request.getParameter("name") != null) {
            User tmpUser = new User();
            tmpUser.setName(request.getParameter("name"));
            userDao.persist(tmpUser);
        
        }

        List users = userDao.findAll();
        for (Object user : users) {
            out.println(((User)user).getId() + "/" + ((User)user).getName());
        }
    
        if (request.getParameter("action") != null && "delete".equals(request.getParameter("action"))) {
            for (Object user : users) {
                userDao.remove((User)user);
            }
        }

        out.println("Hello, GAE and Spring world");
    }
}


STEP 3. 設定相關XML
1. META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

    <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
        <properties>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" value="true"/>
            <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
    </persistence-unit>

</persistence>


2. WEB-INF/applicationContext.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans default-autowire="byName"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" >
        <property name="persistenceUnitName" value="transactions-optional"/>
    </bean>
  
    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

  <aop:config proxy-target-class="true">
        <aop:advisor pointcut="execution(* fattom.riddle..dao.*.*(..))" advice-ref="txAdvice"/>
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
    <bean id="userDao" class="fattom.riddle.dao.UserDao" scope="singleton">
    </bean>
</beans>



3. WEB-INF/web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>fattom.riddle.TestAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>


最後, 再寫個 index.html 就可以測試看看有沒有成功囉

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Hello App Engine</title>
  </head>

  <body>
    <h1>Hello App Engine!</h1>
<form action="test" method="get">
add new user, name = <input type="text" name="name"></input>
<input type="submit" value="OK"></input>
</form>
<br>
<a href="./test?action=delete">delete all users</a>
</br>
  </body>
</html>

2010年7月5日 星期一

Google Code Jam 2010 參賽心得

這是我第一次參加CodeJam
運氣很好有晉級到Round2, 因為出國玩的關係就沒有繼續比下去了
有一些心得可以跟大家分享一下

1. 資格賽的部分, 時間很充裕, 只要完整回答一整題就可以晉級
    不過每一題都要解兩次, 第一次的輸入值會比較簡單
    第二次通常都需要對演算法作一些加速才能在時間內跑完程式
    而且第二次不像第一次一樣, 程式寫錯了, 可以一直重試,
    第二次的解答只有執行一次的機會, 所以一定要再三確認程式沒有問題才去執行
    很多人都是因為第二次的輸入值太大, 程式跑不完, 而Timeout, 要小心!

2. 正式比賽就是比誰寫的快了, 至少要快速的完整解完第一題, 才有機會晉級
    通常, 第一題是最簡單的, 最難的是第三題,
    所以千萬不要因為後面的分數比較高, 就跳著做,
    也不要把所有題目都看完才決定做哪一題, 那一定來不及

3. 有時候, 正式比賽的第一題會比較簡單, 所以必須趕快去解答第二題或第三題
    因為每個人學的領域都不一樣, 建議可以快速的看完第二題或第三題的題目
    選擇有把握的來做, 先做簡單的解就可以了

另外, 這次比賽有個比較特別的地方, 就是用到了Big Number的處理
因為我本身是用JAVA, 在處理大數的部份就非常簡單
我想以後的考試, 可能也會要大家去使用一些基本的API,
建議大家在選擇用哪一種程式語言的時候, 也要考慮到這個問題


=====


Our sincerest apologies!  An email was sent to you in error that indicated that you hadn't advanced to Round 2.  You DID advance; there is no part of our system that thinks you didn't; and we're very sorry for the confusion!  Here is the email you were supposed to receive:


=====

Subject: Congratulations - You're on to Round 2 of Google Code Jam 2010!
Congratulations!  You've proven you're one of the best 3000 contestants in Google Code Jam 2010!

Having placed in the top 1000 in a Round 1 subround, you're now eligible to compete in Round 2.  Round 2 will last 2 hours and 30 minutes, and will take place on Saturday, June 5, 2010 at 14:00 UTC.  Visit http://code.google.com/codejam/schedule.html to find that time in your own time zone, and good luck!

If you have any questions, please visit our FAQ at http://code.google.com/codejam/faq.html, or email us atprogrammingcontest-feedback@google.com.

Congratulations!
The Code Jam Team

=====

Sorry for the mixup, and congratulations again!
The Code Jam Team

2010年5月11日 星期二

Google Code Jam 2010 Qualification C

Problem C: Theme Park

Question: http://code.google.com/codejam/contest/dashboard?c=433101#s=p2&a=2
Answer: http://code.google.com/codejam/contest/dashboard?c=433101#s=a&a=2

這題是最後一題, 應該也算是最簡單的一題
不過有點Tricky, 想答對Large的難度, 要做點最佳化才有辦法

題目是說, 一般遊客去做雲霄飛車的時候, 都習慣一群一群人一起坐上去, 如果有人做不上去的話, 就會等下一班車. 然後, 每個人坐一次會付1元, 我們要算出雲霄飛車一天可以賺多少錢.

例如:
雲霄飛車有 6 個位置, 每天會開 4 次, 遊客有 4 群人, 每群遊客依序有 1, 4, 2, 1 人, 而這些遊客會整天一直排隊坐雲霄飛車.

所以, 第一次雲霄飛車會載 [1, 4] 人 (因為不能插隊, 所以不會把後面一個人的往前補)
第二次會載 [2, 1, 1] 
第三次會載 [4, 2] 
最後一次會載 [1, 1, 4] 
因此, 最後一共賺了 21

在解法的方面, 應該都大同小異
我是用一個 Array 存了遊客人數 [1, 4, 2, 1]
另外還有一個相對應的快取 Array 存了計算過的結果 [5, 6, 4, 6]



快取Array, 初始為[?, ?, ?, ?] 
第一次載完 [1, 4] 人, 所以是 [5, ?, ?, ?]
第二次由第三群遊客開始, 載完 [2, 1, 1] 人, 所以是 [5, ?, 4, ?]
第三次載完 [4, 2] 人, 所以是 [5, 6, 4, ?]
第四次載完 [1, 1, 4] 人, 所以是 [5, 6, 4, 6]
第五次之後, 就不需要再計算, 而是直接使用快取的結果
速度上來說, 已經足以解決這個問題


官方提供了三種最佳化, 有興趣的人可以在上去看看

Google Code Jam 2010 Qualification B

Problem B: Fair Warning

Question: http://code.google.com/codejam/contest/dashboard?c=433101#s=p1&a=1

Answer: http://code.google.com/codejam/contest/dashboard?c=433101#s=a&a=1


這一題的題目很有趣, 但是解起來就不是那麼有趣了, 因為牽扯到大數的問題.
還好我是用JAVA解題, 內建就有大數的函式庫可以使用

題目是說, 在Jamcode星球上, 有一種預言, 西元前發生的幾件大事件, 會暗示哪一天是世界末日

例如:
西元前26000, 11000, 6000年發生了大事件, 則西元4000年會導致世界末日.
因為西元4000年, 離這三個事件分別是30000, 15000, 10000年, 都是5000的倍數, 並且, 5000是一個最大的因數

以這個例子來看
(26000+4000) % 5000 = (11000+4000) % 5000 
(11000+4000) % 5000 = (6000+4000) % 5000 
(26000-11000) % 5000 = 0
(11000-6000) % 5000 = 0

所以
(a + y) % T = (b + y) % T
(a - b) % T = 0

因此, 所有年份的相差值中, 去取出最大公因數, 就是解答

Google Code Jam 2010 Qualification A

Problem A: Snapper Chain

Question: http://code.google.com/codejam/contest/dashboard?c=433101#s=p0&a=0
Answer: http://code.google.com/codejam/contest/dashboard?c=433101#s=a&a=0

這題蠻有趣的
題目是說, 有一種聲控的延長線
只要你一拍手, 有插電的延長線就會開啟或者關閉

我們以0代表關閉, 1代表開啟
如果有兩條延長線, 由左至右連接
則一開始的情況依序為
[0 0]
再做了一次拍手之後, 則變成
[1 0]
接著為
[0 1]
[1 1]
則使得延長線為通電的狀況

如果有四條延長線, 則為以下的情況
[0 0 0 0]
[1 0 0 0]
[0 1 0 0]
[1 1 0 0]
[0 0 1 0]
[1 0 1 0]
[0 1 1 0]
[1 1 1 0]
[0 0 0 1]
[1 0 0 1]
[0 1 0 1]
[1 1 0 1]
[0 0 1 1]
[1 0 1 1]
[0 1 1 1]
[1 1 1 1]

所以聰明的你
是不是發現, 每16次會通電一次

因此可以歸納出
2的N次方, 會通電一次

這個歸納, 應該比官方的快一點

簡單吧!!


2010年4月29日 星期四

YCSB告訴你雲端有多快

Ref: http://research.yahoo.com/files/ycsb.pdf

現在提供雲端運算的服務越來越多了, 有:
    - Apache Hadoop+HBase
    - Apache Cassandra (from Facebook)
    - Yahoo PNUTS
    - Google BigTable
    - Amazon SimpleDB
    - Microsoft Azure

傳統的關聯性資料庫, 大多有相同的規範. 但是, 雲端服務大多都有自己的設計理念, 自己的架構, 甚至大多都捨棄了SQL語法. 所以要對這些不同的雲端服務作公平的比較是非常困難的.

Yahoo提供了一個Framework: YCSB(Yahoo! Cloud Serving Benchmark) 來解決這個問題 .(http://wiki.github.com/brianfrankcooper/YCSB/)

雖然雲端的設計理念有很多不一樣
不過主要的設計方向還是一致的, 都是為了:
1. 提供非常大的使用量
2. 提供彈性的方式, 增加雲端服務的數量, 以提供更多的存取量
3. 容錯性, 可以應付所有可能發生的硬體問題, 網路問題

當然, 魚與熊掌不能兼得, 在同樣的設計方向裡面,
每個雲端服務都有他的預設情境, 所以我們必須對以下的情況做抉擇.

- Read vs Write:
為了Write, Update快速, 大多都會使用在磁碟空間中有連續性的Log架構, 去存放資料差異的Update Log, 所以要去Read經過多次Update的資料, 我們就必須要在Log中取得多筆資料之後, 才能組成一筆我們要的資料.

- 同步 vs 非同步:
因為這些架構, 為了容錯機制, 都會複製多筆資料, 在這種情況下, 修改一筆資料時, 其他的複製資料, 是不是也要做同步呢?

- Row-Based vs Column-Based:
提供Column-Based的架構, 每個Column-Family是存放在不同的檔案中, 所以撈取一整筆資料會比較慢, 但是只抓取某些Column會比Row-Based快很多. 此外, 也提供了比較有彈性的資料結構

- 快速 vs 可靠:
在做Write的時候, 大多的架構只會先暫存在記憶體中, 但是這種情況下如果發生硬體異常, 會導致該筆資料毀損, 所以到底是要為了快速還是可靠呢?

比較特別的是HBase, 雖然他選擇了快速的這個陣營, 但是因為HDFS的複製性, 他預設會複製三份資料在不同的電腦, 所以在作Write的動作時, 也會寫到三台電腦的記憶體中, 除非這三台電腦同時發生異常, 否則資料毀損的機會是很小的.


YCSB由幾個層次去對雲端服務作比較:
Tier 1—Performance :
逐漸增加Loading, 去看效能反應

Tier 2—Scaling:
當增加雲端服務的機器數量時, YCSB也等比增加Loading, 去比較效能反應是不是可以維持不變.
也會測量當雲端服務增加機器數量時, 是否會對效能造成負擔

Tier 3—Availability
當發生硬體異常或者網路問題時, 會對效能造成多大的負擔, 目前YCSB還沒辦法自動模擬這種情況.

Tier 4—Replication
各個雲端服務的資料複製數量是可以自己調整的, 這個參數會造成效能上的變化, 所以也是要作比較的. 不同機房之間的複製性, 也是非常重要的效能指標. 目前YCSB也尚為實作.


在實際評比的時候, YCSB為了公平性,  所以將所有雲端服務資料複製性的參數都調整為1, 也就是使得大家都不做資料複製.
並且提供這幾種資料分布性: Uniform, Zipfian, Latest去比較
也實作了這五種情況:Update heavy, Read heavy, Read only, Read latest, Short ranges 去比較

在架構上YCSB 是以延伸為目的, 所以我們可以自己繼承Workload去實作我們想要做的運算, 也可以實作DB Interface去測量其他的Database

看來起YCSB似乎是很公平的, 其實不然. 我覺得至少有以下的兩個情況要做修改:
1. 資料複製性對於大多數的雲端服務來說,  是一個非常重要的特性. 對於HBase來說, 少了資料複製性, 就等於少了Loading Balance, 這是多麼的重要!

2. 目前YCSB提供的DB Interface一次都是抓取一整個row的資料, 這並不符合現實的應用. 所以對於Column也必須做到, Distribution的探討, 才能客觀的反映出現實應用的效能.

2010年4月20日 星期二

HTML5 = jQuery + Google Gears + Video Player...?

還不了解 HTML5 的時候
覺得 HTML 幹麻要推出新版本
過去的包袱實在太多了

不過看過下面這篇介紹之後, 發現 HTML5 真的很厲害
http://apirocks.com/html5/html5.html

以下幾點是我覺得還蠻重要的
1. 提供了類似 jQuery 的 Selector
2. 提供了 Client 端的 Storage/Database
3. WebGL!!
4. 影音播放功能

尤其是第二點在過去是一個很困擾的問題
想要再 Client 端暫存大量的資料是很困難的
如果把資料存在 Cookie 會使得每次做 request 的時候都一大包, 造成彼此的負擔
就算用 JavaScript 的解法, 也只能生存在 Page 的生命週期

不過
對於 Web Developer 來說
最大的惡夢就在於瀏覽器的相容性
目前各大瀏覽器對於 HTML5 支援度都還不一致
HTML5 會不會是下一個惡夢呢?

這是目前各大瀏覽器的支援度:
http://html5readiness.com/

看起來還是各自為政阿
所以, 以後 jQuery 大概會再一次推出 jQuery5 來整合我們的開發環境吧...