rails使用paperclip插件上传时遇到500 Internal Server Error

有可能是imageMagick没装利索。找不到imagemagick,显示错误信息的时候试图把上传的文件对象序列化,就505了。

sudo apt-get install imagemagick --fix-missing

使用三方库就得做好不可预料事件的准备哇

关于paperclip的使用,这两篇简介好像不错:
http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails/
http://thewebfellas.com/blog/2008/11/2/goodbye-attachment_fu-hello-paperclip

ps: 又遇到了个没预料的问题,上传validates_attachment_content_type指定的类型之外的文件时候同样会遇到个500 internal server error,未解中。

踩踩数据结构什么的 =“=

发觉算法太弱了 =”=

当年在ACM那里呆了两天就隐身了,可惜那个老师非常非常非常好的(实验室里还有空调 >_<)。总觉得这玩意水太深,掉进去就出不来了....“不成熟的优化乃万恶之源”这话又正好应了惰性心理,心安理得地“出了性能问题再说之前先弄出来再说管算法干嘛”...可现实往往是,不会算法你压根就弄不出来...

先从一棵二叉查找树开始好了。挖坑慢慢填,时间有的是(?)

module BTree where
 
data BTree a b = Empty 
               | BNode {
                    kv :: (a, b), 
                    left :: BTree a b,
                    right :: BTree a b
               } 
               deriving(Show, Eq)
 
insert :: (Ord a) => (a, b) -> BTree a b -> BTree a b
insert (k,v) Empty = BNode (k, v) Empty Empty
insert (k,v) pnode@(BNode (pk, _) lnode rnode) 
    | k == pk   = pnode { kv = (k,v) }
    | k <  pk   = pnode { left  = insert (k,v) lnode }
    | k >  pk   = pnode { right = insert (k,v) rnode }
 
find :: (Ord a) => a -> BTree a b -> Maybe b
find k Empty = Nothing
find k (BNode (pk,pv) lnode rnode)
    | k == pk = Just pv
    | k <= pk = find k lnode
    | k >  pk = find k rnode
find _ _ = Nothing
 
remove :: (Ord a) => a -> BTree a b -> BTree a b
remove k Empty = Empty
remove k pnode@(BNode (pk,pv) lnode rnode) 
    | k == pk = merge lnode rnode
    | k <= pk = pnode { left = remove k lnode }
    | k >  pk = pnode { right = remove k rnode }
 
merge :: (Ord a) => BTree a b -> BTree a b -> BTree a b
merge lnode rnode = fromList $ (toList lnode) ++ (toList rnode)
 
--helper
isEmpty Empty = True 
isEmpty _     = False
 
fromList :: (Ord a) => [(a,b)] -> BTree a b
fromList = foldl (flip insert) Empty 
 
toList :: BTree a b -> [(a,b)]
toList Empty = [] 
toList (BNode (k,v) lnode rnode) = 
    (toList lnode) ++ [(k,v)] ++ (toList rnode)
 
-- for test
root = fromList $ [
    (4, "fleurer"), 
    (10, "ssword"), 
    (100, "ssword"), 
    (2, "xx")]

haskell做数据结构好像别扭的很…不用ST Monad或者IO的话什么都是值还不能引用,像二叉树的旋转什么的就没想出常数时间的办法。像上面那个remove就直接简单粗暴了orz

(邪恶音:用ST Monad不就好了嘛)
(ST Monad都用了还用haskell干嘛 TvT)

blah~

“好久没更新了”~orz又这么开头了。

昨天下午给新人讲东西时候差点着起急来,耐心什么的实在是差了些。同理,这个blog也快不会写了。笔记什么的都有记在在本子上,怨念什么的也都在twi上发泄了个精光。想翻译点东西可是怎么都觉得驴唇不对马嘴,就全部作罢。

完整的橇课,上午看书下午敲代码。再同各种善意的小朋友交流下,要说充实倒确实非比寻常。不过总觉得倦的厉害,简单一个“中午不睡下午崩溃”似乎还说不过去。代码就够傲骄了,人自然更难伺候。写这句话的时候当年推销饮水机的两位童鞋又敲门进来推销凉席,都不容易。

还是说代码吧。敏捷编程什么都领悟不了还扯淡什么人生。一天几十行,我起草一份《蜗牛宣言》好了~

想用rails换掉学校网站正在用的这个aspx系统。都说rails不好维护,可是当前的这aspx系统我已经完全维护无力了,瞅着bug在那里只能对着那两万行的一个类发呆。用rails重写最起码我能维护,能用不能用写出来再说。(敏捷什么的就当笑话听吧)

闲着把寒假时候烂掉的那个堆栈机完善了下,随后发懒两个星期没碰代码,回头想下应该差不多能用了(当然是想当然)。代码改的相当蛋疼,用上了ruby那VALUE式的tagged pointer,没打算oo的也在c里把类型搞成了对象,再就是大量少于十行的小函数。以前只是听说lua的upvalue实现很简洁,看了下发现用在这里不合适,lua的临时变量和求值栈都在同一个栈帧里连续着,只要不是闭包的变量在函数执行完立即回收。而这个堆栈机里的堆栈只是求值栈,临时变量都在一个动态分配的结构体里。这里让栈帧在函数执行完后统统保留,等着GC回收就是。

从淘宝上打印了本《莱昂氏unix源码剖析》,作者好个惜字如金,读起来也很吃力。 前半部分是unix v6的全部源码,仅9000行出头。随便翻下就被雷了,内存管理的malloc和mfree不到百行,而枚举一个进程的子进程什么的就都这样:

for(p = &proc[0]; p < &proc[NPROC]; p++)
if (a->p_pid == p->p_ppid) {
        p->p_ppid = 1;
        if (p->p_stat == SSTOP)
                setrun(p);
}
swtch();

简单粗暴,多好。

动态作用域

好像刚弄明白动态作用域是怎么回事,拿个例子:

var a=0; //global
def f1():
    a=1
def f2():
    var a; //local
    f1()
 
f2()
puts a

若是静态作用域,f2调用f1,f1修改全局变量a的值为1,输出1。这个多自然…
可是动态作用域就…输出0,全局变量a的值没有变化。

f2不是调用了f1么,f1不是改变a的值么…是啊,f2调用的那个f1改变的是f2那个局部变量a的值。也就是说,同一个函数在不同的环境下调用会有不同的行为。

好吧我正在纳闷为什么会有这种东西存在过…囧

各种垃圾收集的随便笔记

GC多好多好就不多说了。没银弹嘛,什么好处什么坏处都了解下就好 TvT

引用计数

“穷人的垃圾收集”。实现简单,可以在对象失去引用时立即收集,不过对付不了循环引用。“立即收集”容易给人一种“高效”的印象,其实正相反,引用计数中的每个mov指令后面都必须跟着几条额外指令,引用的局部性还不好。跟各种GC算法比起来,引用计数的效率是最低的 :(

CPython是引用计数加备用的mark-sweep,(好像如果一开始就使用GC的话就没必要引入那套复杂的内存池机制了?

mark-sweep

从根(寄存器、局部变量和全局变量等)开始,遍历所有可访问的对象并标记之;再遍历所有变量,将所有没mark的对象收集。

C\C++中的GC实现大约是扫描bss段和堆栈什么的,找到全局变量和局部变量。C\C++中你不知道一块数据是指针还是一个纯洁的整数,所以只能用个is point to heap来猜它是不是指针,如果这个整数恰好是一块内存的地址,就只能“保守地”当它是指针mark掉了。保守式的GC中比较有名的就是Boehm的GC(貌似很靠谱!)。

停止-复制

这个需要额外一倍的内存空间。先将一切活动停止,遍历堆中所有可以访问的对象并将其拷贝到另个堆中,并将将原先的指针统统指向新的堆中对应的地址,完毕后继续程序的执行。

停止复制的同时也紧缩了内存,因而不存在内存碎片的问题(malloc/free在整理堆中碎片时候的各种搬运不容小觑),性能上好像要优于mark-sweep。缺点就是对空间浪费比较大(一倍啊一倍~)。

分代收集

遍历所有对象时候的停滞会比较厉害。想办法把停滞缩短到人类察觉不到吧…就有了分代收集和增量收集 TvT

分代收集基于这样的假设:

1.对象越新,生存期越短;
2.对象越老,生存期越长;
3.少有指向新对象的老对象

就把堆分成n块,对应n代的对象(三代就差不多吧)。再加个记忆表什么的记下指向新对象的老对象,以记忆表中的老对象以及活跃的变量等做根,重点照顾最新的这代就行了。

.net那CLR好像是分代的…缺点是经过多次收集,较老的代会积攒比较多的垃圾。

增量收集

增量收集好像是记住上次遍历到了什么地方,然后每次遍历一点,最后集中收集。

有个三色标记:
白色:未被访问的对象;
灰色:已经被访问过,子对象还未访问;
黑色:已经被访问过,子对象也已被访问;

然后就是性质:
当没有灰色对象时,所有的白色对象都是垃圾;
不会有黑色对象指向白色对象;
每个灰色对象都位于收集器的队列中(作为下次收集的根);