还在路上

December 31st, 2009

又是一年算账的时候,去年的今天写了2009年的一些计划:网络(socket)/桌面(gui)编程;一个精巧的PHP框架;数据挖掘;多一些好朋友。socket/gui编程算是稍稍入门吧;PHP框架(ColaPHP)已经发了4个alpha版本,目前从实际项目中看表现还可以,可能下一个版本就进入beta阶段,beta意味着ColaPHP逐步趋于稳定;数据挖掘前半年做的比较多,进展不算太大;好朋友多了一些,此事甚为欣慰。

2009年技术上主要是代码方面的成长,重构的事情做的比较多,已不太相信过于花哨的玩意。脾气方面,”骄躁”二字少了些。回过头来看2009,不觉太多收获,亦不觉浮度。

2010年想要做的一些事情:学一门新语言;ColaPHP发一个GA版本;数据挖掘,做一个开源的推荐系统;更多的好朋友。

希望春天能在2010年到来。

ColaPHP-0.4-alpha发布

December 23rd, 2009

ColaPHP月度发布计划,基本上每月发一个release,相比较0.3alpha,比较大的修改如下:

  • 增加了动态路由模式,可不用定义URL规则
  • 增加对MySQL Master-Slave支持,可以由单数据库无缝迁移到主从模式
  • 去除框架中Smarty模板的绑定,可以在Controller中自行调用Smarty模板
  • Helper中增加了性能测试模块Benchmark.php
  • 增加对MongoDB的简单绑定Mongo.php
  • 性能进一步提升
  • 大量的代码重构以及bug fix

访问ColaPHP官方网站,下载0.4alpha,不过建议随时跟进我们的svn://colaphp.googlecode.com/svn/trunk/,ColaPHP一直在活跃开发。

ColaPHP 0.4alpha已完成预期目标,所有的函数都控制在20行以内。下一个版本0.5alpha版本开发代号:Practice,ColaPHP已经在一些实际项目中使用,0.5alpha将得到更多的实践优化

招募PHP极客加入ColaPHP,联系fuchaoqun#gmail.com。

Tags: ,

[视频] Music Recommender Systems

November 29th, 2009

上次去beta沙龙的视频,希望没有浪费大家的时间,感谢beta沙龙的组织工作。

Tags: , , , ,

Music Recommender Systems

November 17th, 2009

周末beta沙龙和大家分享的音乐智能推荐PPT,有些内容和上次的PPT差不多,这次主要和大家分享一个完整的数据挖掘流程,同样的,还是工程方面比较多,学术方面这里有很多大牛。

Tags: , , , , ,

从140秒到2秒的优化

November 12th, 2009

从2亿个0~2,000,000,000之间的数字样本中找出不重复的记录总数,首先想到的是bloom filter,转念一想既然全都是数字,bloom filter有点太重,bitarray也许更有效,于是第一个版本出来,部分代码如下:

ba = bitarray(212**4)
cnt = 0
for i in data:
    if (not ba[i]):
        cnt += 1
        ba[i] = True
print cnt

大概需要140s左右,觉得if (not ba[i]):这个比较费,改了第二版:

for i in data:
    ba[i] = True
print ba.count()

速度有所提升,到了120s左右,开始打起多核运算的主意了,山寨了一个map-reduce,首先通过maper把数据按照除4得余分成4份:

def maper(data):
    map_data = (array('I'),array('I'),array('I'),array('I'))
    for i in data:
        m = i % 4
        map_data[m].append(i)
    return map_data

然后起了一个4个进程的woker pool分别计算,最后把结果汇总:

def worker(data):
    counter = bitarray(256**4)
    for i in data:counter[i] = True
    return counter.count()
 
p = Pool(4)
result = p.map(worker, data)

速度提高明显,到了50s左右,这个做法的问题是两次遍历:map的时候一次、reduce的时候又一次,于是开始想办法解决,把文件直接分开运算,不再map,把最后的结果做一下位或再计数:

p = Pool(4)
result = p.map(worker, data)
print (result[0] | result[1] | result[2] | result[3]).count()

到了26s左右,可能Python在进程间交换大数据量效率不是太好,再优化的空间有限,想起之前用Python的科学运算库做过数据挖掘,能不能用那个库试试,于是有了NumPy的版本:

import numpy as np
print len(np.unique(np.fromfile('/path/to/data.dat', np.uint32)))

全部程序就这两行,速度到了12s,让人崩溃,NumPy的底层大多是C的实现,对代码做了一个profile,发现NumPy用了sort,有点浪费,如果我用C实现一部分功能的话效果应该会不错,注意到代码中有for i in data,data中有2亿条,就循环调用了2亿次,尝试把这个调用都封装在C里面,使用C级别的循环,于是用C扩展了一下bitarray包:

static PyObject *
bitarray_fromarray(bitarrayobject *self, PyObject *pyo)
{
    unsigned int *l;
    idx_t n1;
    Py_ssize_t nbytes, nitems, i;
    if (PyObject_AsReadBuffer(pyo, (const void **)&l, &nbytes) != 0)
        return Py_False;
    nitems = nbytes/sizeof(unsigned int);
    for (i=0; i<nitems; i++) {
        *(self->ob_item + l[i] / 8) |= ((char) 1) << (l[i])%8;
    }
    n1 = count(self);
    return PyLong_FromLongLong(n1);
}

直接读取文件buffer到bitarray,python程序就变成了:

from bitarray import bitarray
counter = bitarray(212 ** 4)
fp = open('/path/to/data.datbk', 'rb')
un = counter.fromarray(fp.read())
print un

一共5行代码,速度到了2s内,收工。

Tags: ,

ColaPHP-0.3-alpha发布

November 7th, 2009

开发工作很久以前就基本完成了,一直没来得及整理,今天发布0.3alpha,相比较0.2alpha,比较大的修改如下:

  • Helper中增加了验证码模块Captcha.php、HTTP访问模块Http.php、数据校验模块Validate.php
  • 修订DB模块中result($sql)函数,如果$sql是select语句则返回结果集,如果是insert语句则返回最后插入ID,如果是update或者delete语句,则返回受影响行数(有可能为0行),其他语句则返回query句柄
  • 完善框架的易用性:增加了统一配置文件;可以指定models、views、controllers目录;支持默认模版名称
  • 大量的代码重构以及bug fix

下载0.3alpha,不过建议随时跟进我们的SVN://colaphp.googlecode.com/svn/trunk/,ColaPHP一直在活跃开发。

0.4alpha版本开发代号:20 lines,目标是把所有的函数都控制在20行以内以及代码的持续重构。

继续招募PHP极客加入Cola,联系fuchaoqun#gmail.com。

Tags:

jQuery表单校验

November 2nd, 2009

最近有个项目,用到很多的表单校验,尝试了一下jQuery.validator,甚是顺手,地址:http://plugins.jquery.com/project/validate,基本的用法:

$('#formId').validate({
    debug:true, // 打开debug模式,不会真实提交,适合测试
    rules:{
        uName:"required", // 需要录入
        uNick:{
            required:true
        }, // 需要录入的另一种写法
        uBlog:{
            required:true,
            url:true
        } // 需要输入,且录入的必须是url
    },
    messages:{ // 自定义提示语文字
        uName:"请输入用户名"
    },
    submitHandler:function(form) { // 表单提交,需要jqueyr.form插件
        form.submit();
    }
}

阅读一下文档差不多就会了解,支持的校验格式有:

required:必填字段

email:电子邮件

url:合法的网址

date:日期

dateISO:日期(ISO)

number:数字

digits:整数

creditcard:信用卡号

equalTo:相同的值

accept:拥有合法后缀名的字符串

maxlength:最多长度的字符串

minlength:最少长度的字符串

rangelength:一个长度介于最小值和最大值之间的字符串

range:一个介于最小值和最大值之间的值

max:最大值

min:最小值

相对高阶一点功能:

  • 自定义错误提示信息

    当然,你可以通过定义messages来修改提示信息,但你想偷懒又不想用默认的英文提示,直接引入默认提示文字

    <script src="path/to/localization/messages_cn.js" type="text/javascript"></script>
  • IE6下不工作的bug

    传闻IE6下,jquery.validate.js有乱码,不能正常工作,解决办法:

    <script src="path/to/jquery.validate.js" type="text/javascript" charset="iso-8859-1"></script>
  • 控制错误信息显示位置

    有的时候默认的错误信息显示有问题,比如多个单选框,默认的会把错误信息显示在第一个单选框后面,页面就乱了,解决办法:

    errorPlacement: function(error, element) {
        if (element.is(":radio")) {
            error.appendTo(element.parent().parent("td"));
        else {
            error.appendTo(element.parent());
        }
    }

    当然,还可以重载invalidHandler来实现

  • 依赖校验

    有的时候,一个输入框的校验依赖于其他条件,比如登录的时候可以通过用户名或者邮箱登录,只有当用户选择用邮箱登录时,才对邮箱输入框验证,rules中可以这样写:

    uMail:{
        required:{depends: function(element) {
            return true == $('#isMail').val();
        }},
        email:true
    }

    这样只有用户选择了用邮箱登录才会校验 邮箱项,否则不校验。

Tags: ,

PHP处理Etag、lastModified和Expires

September 5th, 2009

之前看到robbin基于资源的HTTP Cache的实现介绍,想到这是一个很有意思的功能,原理很简单,但很多人都会忽略,于是乎打算集成到ColaPHP框架中来,让浏览器缓存动态内容,对于一些由动态脚本生成、更新不频繁但又会被用户重复访问的页面内容,还是很有意义的。

如果在服务器端设置了Etag、lastModified和Expires之后,下次再访问同一资源的时候,一个典型的HTTP头是这样的:

Host            127.0.0.1
User-Agent        Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 QQDownload/1.7
Accept            text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language        zh-cn,zh;q=0.5
Accept-Encoding        gzip,deflate
Accept-Charset        GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive        300
Connection        keep-alive
If-Modified-Since    Sat, 05 Sep 2009 12:44:56 GMT
If-None-Match        foobar
Cache-Control        max-age=0

关于lastModified、Etag和Expires的工作原理,可以参看http://longrujun.name/index.php/2009/03/04/etag%E5%92%8Cexpires/,简单来说:

lastModified:设定一个最后修改时间,浏览器下次访问的时候,发送一个”If-Modified-Sinc”的头信息,如果内容在这个时间之后没有更新,服务器直接返回一个304 Not Modified而不传输详细内容,可以节省带宽。

Etag:设定一个标记,浏览器下次访问时,发送一个”If-None-Match”的头信息,如果服务器内容还是这个标记没变,也直接返回一个304 Not Modified而不传输详细内容,同样可以节省带宽。

Expires:设定一个过期时间,如果当前请求在这个过期时间之类,则不发送HTTP请求,不仅可以节约服务器带宽,还可以减少服务器HTTP请求数

主要通过header函数来发送,比较简单,直接上代码:

public static function etag($etag, $notModifiedExit = true)
{
    if ($notModifiedExit && isset($_SERVER['HTTP_IF_NONE_MATCH']) && $etag == $_SERVER['HTTP_IF_NONE_MATCH']) {
        self::statusCode('304');
        exit();
    }
    header('Etag: ' . $etag);
}
 
public static function lastModified($modifiedTime, $notModifiedExit = true)
{
    $modifiedTime = date('D, d M Y H:i:s', $modifiedTime) . ' GMT';
    if ($notModifiedExit && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $modifiedTime == $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
        self::statusCode('304');
        exit();
    }
    header("Last-Modified: $modifiedTime");
}
 
public static function expires($seconds = 1800)
{
    $time = date('D, d M Y H:i:s', time() + $seconds) . ' GMT';
    header("Expires: $time");
}

如果你是用ColaPHP,可以直接在controller里面写上:

// 设定最后修改时间,通常是数据库中内容修改时间
$this->helper->response->lastModified(1252154696);
// 设定内容标记,自己可以按照一定的规则来生成,当然也可以用内容最后修改的时间戳
 $this->helper->response->etag('foobar');
// 设定失效时间
$this->response->expires(10);

PS:ColaPHP近期发0.3alpha,主要改进Model和DB设计,加入了一下小功能(比如验证码),以及bugfix。

Tags: , , ,

ColaPHP-0.2-alpha发布

July 28th, 2009

相比较0.1alpha,比较大的修改如下:

  • 增加了Cache处理模块,支持APC、eAccelerator、Memeched、File、Xcache、Dba缓存
  • 增加日志处理模块,支持Echo、File、Null三种类型
  • 去掉了Cola.php中404处理,建议用户在url规则最后的位置加上’/.*/’来处理其他任何没有匹配的请求
  • demo做了一点小的修改,有一个演示不需要定义url规则、跳过Router.php的方法(参见demo/norouter.php)
  • 一些bug的修订

同时欢迎Python.Han, darkredz加入到项目中来,有你们ColaPHP会更精彩。

下载0.2alpha,不过建议随时跟进我们的SVN://colaphp.googlecode.com/svn/trunk/,ColaPHP一直在活跃开发。

继续招募PHP极客加入Cola,联系fuchaoqun#gmail.com。

ColaPHP-0.1-alpha发布

June 19th, 2009

非常简陋的一个PHP框架,只是把架子搭起来了,地址:http://code.google.com/p/colaphp/

现在PHP框架已经很多了,为什么还要去”重复的发明轮子”?

  • 你和我一样不想重新学习一门”框架语言”
  • 你和我一样希望规范的MVC开发
  • 你和我一样希望一个高性能的框架
  • 你和我一样不希望改变已有的PHP开发方式

现在,ColaPHP还很不成熟,暂且当做一个”玩具”试试,有兴趣的可以阅读一下代码,品味好的代码和指出坏味道的代码都是一个好的过程。

文档方面现在还很不全,我希望只用一个Tutorial就能讲明白,以后也不会有别的新的文档(文档越多,表明系统越复杂,学习成本也越高),当然,Tutorial会是一个持续完善的过程。

ColaPHP是写给PHP程序员的一个框架,信奉KISS的同学可以试试

Tags: , ,