有可能是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)
Published on
2010年05月7日 in
杂碎.
Tags: 杯具.
“好久没更新了”~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();
简单粗暴,多好。
Published on
2010年04月15日 in
笔记.
Tags: PL.
好像刚弄明白动态作用域是怎么回事,拿个例子:
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的值。也就是说,同一个函数在不同的环境下调用会有不同的行为。
好吧我正在纳闷为什么会有这种东西存在过…囧
Published on
2010年04月11日 in
笔记.
Tags: GC, VM.
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好像是分代的…缺点是经过多次收集,较老的代会积攒比较多的垃圾。
增量收集
增量收集好像是记住上次遍历到了什么地方,然后每次遍历一点,最后集中收集。
有个三色标记:
白色:未被访问的对象;
灰色:已经被访问过,子对象还未访问;
黑色:已经被访问过,子对象也已被访问;
然后就是性质:
当没有灰色对象时,所有的白色对象都是垃圾;
不会有黑色对象指向白色对象;
每个灰色对象都位于收集器的队列中(作为下次收集的根);
Comment