火星日记 ~ 第一千四百一十天 ~ 中秋节快乐

Lee.MaRS 发表于 2009-10-03 19:06:57

话说我这个草拔得的确很不专业, 错过了很多值得纪念一下的日子.

比如2009.9.14, 也就是我加入公司快满第二个月的时候, 第一次加班加到了第二天凌晨3:30.

打车回去到小区门口的时候, 连车门都摸了好半天才打开.

师傅说困糊涂了吧, 我笑笑, 恩.

车开走之后, 整个世界就只剩下寂静.

不自觉地抬头望天, 才发现满天繁星, 在黑夜中是那样的璀璨.

北京的秋天来得很早, 深夜的风已然带些一丁点刺骨的寒意.

我下意识地把手环在胸前, 却只能感受到自己的温度.

多么希望能有你陪在我身边.

==================我是里世界和表世界的分隔符=====================

话说我到了北京之后一直过得很沉沦, 连中秋是哪天也没搞清楚.

一直以为是10.8, 结果今天收到祝中秋快乐的短信才发现还没买月饼...

还好我们部门已经发了一大盒=_=, 不然和在大学里面就没区别了.

最后祝大家中秋节快乐~
收藏: QQ书签 del.icio.us 订阅: Google 抓虾

火星日记 ~ 第一千三百六十二天 ~ 入职一个月

Lee.MaRS 发表于 2009-08-16 23:02:58

总体来说情况良好,请大家放心……
收藏: QQ书签 del.icio.us 订阅: Google 抓虾

火星日记 ~ 第一千三百二十七天 ~ 回归

Lee.MaRS 发表于 2009-07-12 00:28:06

从2009/3/31到2009/7/12, 过去了103天.

这103天, 经历了太多的事情.

生活如峰回路转般变化着.

总结一下, 大概就是.

我大学毕业了, 离开了生活了近5年的地方.

我拿到了新的offer, 成了北漂一族.

大致就这样吧.

btw: 其实本篇的主要目的, 是回来拔个草, 呵呵..
收藏: QQ书签 del.icio.us 订阅: Google 抓虾

火星日记 ~ 第一千二百二十四天 ~ 半年的终结符

Lee.MaRS 发表于 2009-03-31 18:56:03

从2008.9到2009.3, 整整7个月的时间.

经历波澜起伏.

经历漫长等待.

终于等到了.

幻想的破灭.

赶在这三月的最后一天.

丝毫不用怀疑这可能是个April Fool的玩笑.

Reject @ Google, SET

Farewell, Google.
收藏: QQ书签 del.icio.us 订阅: Google 抓虾

火星日记 ~ 第一千一百三十四天 ~ Happy new year!

Lee.MaRS 发表于 2008-12-31 22:58:31

让霉运连连的2008年赶紧滚蛋,迎接好运不断的2009年!

祝大家新年快乐,心想事成!

Python源码剖析读书笔记可能还会暂停一段时间,因为这项工作实在是非常耗费时间的一件事情,而我现在无法集中精力,静下来把笔记写上来。

不过这项工作还会继续下去,我现在也还在继续阅读这本书,在书上乱涂乱画。

希望大家在新的一年,还能把我的Blog留在你们的Google Reader里面。:-)
收藏: QQ书签 del.icio.us 订阅: Google 抓虾

火星日记 ~ 第一千一百三十四天 ~ 人生第二封拒信

Lee.MaRS 发表于 2008-12-31 22:22:09

有人和我说过,其实今年百度和微软还是比较好进的。

我和这两家今年都是各有两次机会,也就是说,一共有四次机会摆在我的眼前。

可惜我都没能拿到offer。

第一次是内推面百度。

详情之前我也提到过一些。

总体来说,那次面试面得相当失败。

技术的问题答得一塌糊涂。

一些文化上的问题也冲突严重。

自然是直接被拒了。

第二次是面M$ STBC。

也许是没有经过内推的原因,我接到的是HR电面。

我那一口结巴的英语被HR直接教育了。

然后做Open Problem,SDET职位的。

大概是HR觉得我没有什么资质吧。

收到了人生的第一封拒信。

第三次还是面M$,换了另外一个组。

这次是直接面试。

面试的情况应该还行,考的题目都非常trivial。

就是这样trivial的题目,当时还是让我做得挺难受的。

我自己都不知道该如何解释为什么会这么难受。

然后被电面,问到了一些数据库的简单的东西。

我关系数据库基本上就没有用过,MySQL什么的基本算是不懂。

然后就算电面跪了。

最后没有收到offer,只是问我有没有兴趣去实习,时间是三个月。

我想了一下,拒绝了。

第四次是Baidu。

先是在线笔试。

题目应该算不上很难,但是感觉是挺开放式的题目。

时间也挺紧的。

最后还是通过了在线笔试。

后来接到了电面。

虽然我很想针对面试官提的那些问题吐槽,但这些其实不是最重要的。

对于这次电面,我只后悔一件事情。

就是我在电面的时候由于某种鬼使神差的因素,上网查资料了。

然后也不知道为什么,面试官知道了。

最后,从内部人士那里听说,面试官以这个理由拒了我。

如果是别人的错还好说。

自己犯错误就觉得非常可惜了。

于是,我在2008年的最后一天,收到了来自Baidu的拒信。

=================================================我是拒信的分隔线=================================================

您好!

 

    感谢您应聘电子商务事业部职位,通过笔试、面试,我们招聘小组对您进行了仔细的评估与讨论,您体现出的学术背景与实证研究的态度给我们留下了深刻印象。但是,鉴于对此职位的全面考虑,我们认为您目前暂时不适合该职位的工作,对此我们深表遗憾。这个决定对我们来说并不容易,希望您能理解,并对自己的竞争力保持信心。今后如有合适的职位,我们会和您联系。

 

    再次感谢您对百度一直以来的关注与信任,以及对我们工作的支持,祝您找到更合适的职位和发展空间!

 

谢谢!

百度电子商务事业部

=================================================我是拒信的分隔线=================================================

可以说Baidu毫无人性,在2008年的最后一天发拒信,不让人家过个欢乐的新年。

也可以说Baidu做了件好事,至少不让我把霉运带入2009年。

我和Baidu,和M$,注定是没有缘分的。

收藏: QQ书签 del.icio.us 订阅: Google 抓虾

火星日记 ~ 第一千一百二十八天 ~ Merry Christmas

Lee.MaRS 发表于 2008-12-25 02:20:29

转眼间圣诞节就到了.

圣诞夜没闲着, 参加合唱团的走穴活动去了.

四首歌, 唱了两次, 然后就搞定了...

收入两张大红纸...

唱得如何?

恩... 感觉唱得相当的囧...

不过现场的客人看上去根本不在乎你唱什么...

于是我也无所谓了...

反正明年就没我的份了 -.=b

上台唱的时候大家都很矜持.

反倒是在休息的时候唱得很high.

一堆人在那里拼命唱我不会的曲子, 郁...

害得我只好一个人在那里默默地看书...

圣诞夜看别人来吃天价自助餐, 其实心情有一点奇怪的.

zhouye小朋友说以后有钱了也要来这里吃, 再带个小MM...

我就囧住了...

我以后大概没什么机会来吃这种天价自助餐吧...

一是穷...

二是以我的勤俭持家的性格来看应该也不会做这样的事情...

最后离开酒店了以后, 一堆人在路口等着过马路时吃错药了开始唱 Ezekiel Saw The Wheel...

引来无数人侧目...

于是我们开始大声自称是交大的...

回来的时候坐在出租车上, 想想以后要是工作了, 一天的收入还没有一个晚上这样随便唱唱的收入多...

继续囧...
收藏: QQ书签 del.icio.us 订阅: Google 抓虾

Python源码剖析学习 - Chap3 - Python中的字符串对象 - Part2

Lee.MaRS 发表于 2008-12-14 20:06:00

本文是《Python源码剖析——深度探索动态语言核心技术》一书的摘录和读书笔记. 希
望对Python有爱的筒子都能购买一本, 支持这本国内难得一见的好书.

转载本文, 请注明作者leemars. 欢迎大家访问作者的博客
http://leemars.ycool.com

[创建PyStringObject对象]
Python提供了两条路径, 从C的原生字符串创建PyStringObject对象. 这两条路径分别是
PyString_FromString和PyString_FromStringAndSize.

先来看PyString_FromString:

[Objects/stringobject.c]
PyObject *
PyString_FromString(const char *str)
{
    register size_t size;
    register PyStringObject *op;

    assert(str != NULL);
    size = strlen(str);
    if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) { /* 1 */
        PyErr_SetString(PyExc_OverflowError,
            "string is too long for a Python string"); /* 2 */
        return NULL;
    }
    if (size == 0 && (op = nullstring) != NULL) {
#ifdef COUNT_ALLOCS
        null_strings++;
#endif
        Py_INCREF(op); /* 3 */
        return (PyObject *)op;
    }
    if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
#ifdef COUNT_ALLOCS
        one_strings++;
#endif
        Py_INCREF(op); /* 4 */
        return (PyObject *)op;
    }

    /* Inline PyObject_NewVar */
    op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
    if (op == NULL)
        return PyErr_NoMemory(); /* 5 */
    PyObject_INIT_VAR(op, &PyString_Type, size);
    op->ob_shash = -1;
    op->ob_sstate = SSTATE_NOT_INTERNED;
    Py_MEMCPY(op->ob_sval, str, size+1); /* 6 */
    /* share short strings */
    if (size == 0) {
        PyObject *t = (PyObject *)op;
        PyString_InternInPlace(&t);
        op = (PyStringObject *)t;
        nullstring = op;
        Py_INCREF(op);
    } else if (size == 1) {
        PyObject *t = (PyObject *)op;
        PyString_InternInPlace(&t);
        op = (PyStringObject *)t;
        characters[*str & UCHAR_MAX] = op;
        Py_INCREF(op);
    }
    return (PyObject *) op;
}

代码还是比较长的. 下面简单说明一下, 顺便提一些Python2.6的变化, 标号对应代码中
注释处:

1. 判断字符串的长度加上PyStringObject本身的大小(即整个变长对象PyStringObject
的实际大小)后, 是否超过系统限制的最大大小. 书上的Python旧版代码中仅判断
size > PY_SSIZE_T_MAX, 也就是没有考虑对象自身的大小, 是不完善的.

2. 当需要分配的内存超过系统限制的上限时, 抛出异常PyExc_OverflowError, 即溢出.
书上的Python旧版代码没有抛出异常.

3. 对于长度为0的空串(即"", 而非NULL), 若nullstring已经被初始化, 则返回
nullstring. 这是intern机制的一部分. 书上的Python旧版代码没有对nullstring增加
引用计数.

4. 对于长度为1的字符串, 若字符表中该字符对象已经初始化, 则返回该字符对象. 这是
intern机制的一部分. 书上的Python旧版代码没有对该字符对象增加引用计数.

5. 若申请内存空间失败, 则调用PyErr_NoMemory()处理. 书上的Python旧版代码中没
这一部分.

6. 使用Py_MEMCPY代替直接使用memcpy. 贴一下Py_MEMCPY的代码:

[Include/pyport.h]
/* Py_MEMCPY can be used instead of memcpy in cases where the copied blocks
* are often very short.  While most platforms have highly optimized code for
* large transfers, the setup costs for memcpy are often quite high.  MEMCPY
* solves this by doing short copies "in line".
*/

#if defined(_MSC_VER)
#define Py_MEMCPY(target, source, length) do {              \
        size_t i_, n_ = (length);                           \
        char *t_ = (void*) (target);                        \
        const char *s_ = (void*) (source);                  \
        if (n_ >= 16)                                       \
            memcpy(t_, s_, n_);                             \
        else                                                \
            for (i_ = 0; i_ < n_; i_++)                     \
                t_[i_] = s_[i_];                            \
    } while (0)
#else
#define Py_MEMCPY memcpy
#endif

看注释应该就明白了, Py_MEMCPY是为跨平台优化而提供的一个宏. 因为在有些平台上,
调用mempcy的代价比较高, 所以对于小数据量的拷贝就原地展开成循环. 那Python觉得
哪些平台需要这样的优化呢? 看到_MSC_VER了吧, 这个是M$的C编译器特有的宏, 看来,
需要特别优化的就是Windows下了.

书上贴出的Python代码可能出于简化的考虑, 与实际的Python2.5的代码有所出入, 故再
次强调上述几点描述的差异乃是对比Python2.6与书上的代码.

我们不妨也来一次简化, 把所有的异常处理以及intern机制相关内容去掉, 看看这段代
码的核心是什么:

PyObject *
PyString_FromString(const char *str)
{
    register size_t size;
    register PyStringObject *op;

    size = strlen(str);
    /* Inline PyObject_NewVar */
    op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
    PyObject_INIT_VAR(op, &PyString_Type, size);
    op->ob_shash = -1;
    op->ob_sstate = SSTATE_NOT_INTERNED;
    Py_MEMCPY(op->ob_sval, str, size+1);
    return (PyObject *) op;
}

是不是变得非常清爽呢? 依次说来就是:
1. 求str的长度
2. 为变长对象PyStringObject申请内存, 地址赋给op.
3. 用宏PyObject_INIT_VAR, 初始化op的头部(包括ob_refcnt, ob_type, ob_size)
4. 将op->ob_shash初始化为-1(未计算)
5. 将op->ob_sstate初始化为SSTATE_NOT_INTERNED(未interned)
6. 将str复制到ob_sval
7. 返回op

之前我们还提到过PyString_FromStringFromSize, 它与PyString_FromString有什么不
同呢? 我们把代码单独摘出来, 用diff比较一下代码:

% diff -uN PyString_FromString.c PyString_FromStringAndSize.c
--- PyString_FromString.c   2008-12-14 17:03:53.945677523 +0800
+++ PyString_FromStringAndSize.c    2008-12-14 17:04:25.054637950 +0800
@@ -1,14 +1,10 @@
PyObject *
-PyString_FromString(const char *str)
+PyString_FromStringAndSize(const char *str, Py_ssize_t size)
{
-   register size_t size;
    register PyStringObject *op;
-
-   assert(str != NULL);
-   size = strlen(str);
-   if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
-       PyErr_SetString(PyExc_OverflowError,
-           "string is too long for a Python string");
+   if (size < 0) {
+       PyErr_SetString(PyExc_SystemError,
+           "Negative size passed to PyString_FromStringAndSize");
        return NULL;
    }
    if (size == 0 && (op = nullstring) != NULL) {
@@ -18,7 +14,9 @@
        Py_INCREF(op);
        return (PyObject *)op;
    }
-   if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
+   if (size == 1 && str != NULL &&
+       (op = characters[*str & UCHAR_MAX]) != NULL)
+   {
#ifdef COUNT_ALLOCS
        one_strings++;
#endif
@@ -26,6 +24,11 @@
        return (PyObject *)op;
    }

+   if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
+       PyErr_SetString(PyExc_OverflowError, "string is too large");
+       return NULL;
+   }
+
    /* Inline PyObject_NewVar */
    op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
    if (op == NULL)
@@ -33,7 +36,9 @@
    PyObject_INIT_VAR(op, &PyString_Type, size);
    op->ob_shash = -1;
    op->ob_sstate = SSTATE_NOT_INTERNED;
-   Py_MEMCPY(op->ob_sval, str, size+1);
+   if (str != NULL)
+       Py_MEMCPY(op->ob_sval, str, size);
+   op->ob_sval[size] = '\ 0';
    /* share short strings */
    if (size == 0) {
        PyObject *t = (PyObject *)op;
@@ -41,7 +46,7 @@
        op = (PyStringObject *)t;
        nullstring = op;
        Py_INCREF(op);
-   } else if (size == 1) {
+   } else if (size == 1 && str != NULL) {
        PyObject *t = (PyObject *)op;
        PyString_InternInPlace(&t);
        op = (PyStringObject *)t;

我们把PyString_FromString称为A, PyString_FromStringAndSize称为B. 从diff的结果
分析, 我们可以知道:
1. A用assert假设str不为NULL; B接受str为NULL的情况.
2. A的用strlen计算size, size必然非负; B对于传入的size为负数的情况, 抛出异常,
类型为PyExc_SystemError.
3. A对于字符串str, 要求以'\ 0'结尾, 而且中间不能包含'\ 0'; B对于字符串str, 并不
要求以'\ 0'结尾, 且允许字符串中间包含'\ 0', 但要求字符串必须至少含有size个字符.

看看简化之后的代码:

PyObject *
PyString_FromStringAndSize(const char *str, Py_ssize_t size)
{
    register PyStringObject *op;

    /* Inline PyObject_NewVar */
    op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
    PyObject_INIT_VAR(op, &PyString_Type, size);
    op->ob_shash = -1;
    op->ob_sstate = SSTATE_NOT_INTERNED;
    if (str != NULL)
        Py_MEMCPY(op->ob_sval, str, size);
    op->ob_sval[size] = '\ 0';
    return (PyObject *) op;
}

不过就是size不需要自己计算, 改为传入了而已. 不过这一小小的变化, 却导致这两个
函数可以接受的字符串性质的不同.

[注]该死的Ycool, 代码大概有问题, 会把\ 0(中间空格去掉)替换成#CONTENT#....
关键词(Tag): python python源码剖析
收藏: QQ书签 del.icio.us 订阅: Google 抓虾