[email protected]:~$

  • 通过Razor管理Virtual box虚拟机

    Tags: 云计算

    打算在mac上用虚拟机玩下云。之前工作中用到了Razor,于是萌生了用Razor来管理虚拟机的想法(顺便试验下最近很火的docker)。 为了让开发机尽量保持”干净”,决定用docker来做个razor-server的镜像(docker pull jjy0/razor 可以下载到) 制作镜像还算顺利,没想到在虚拟机的网络配置和IPXE boot上栽了跟头,记录在此引以为戒,同时期望能帮助到他人(没接触过PXE boot或Razor的朋友就此别过!) 用docker启动 razor-server非常简单 docker run -d -p 8080:8080 jjy0/razor start 在本地安装razor-clientgem install razor-client 已经完成了razor的安装! 接下来根据官方教程配置PXE boot VMware Fusion的坑 刚开始我使用的是Vmware Fusion,在一台虚拟机中设置好了razor和DHCP server,却无法被同网络其他机器探测到。 没能找到解决办法,之后使用Vmware自带的DHCP server redirect到razor,发现Vmware自导的dhcpd版本过低(2.x)不支持chain命令,只好作罢 Virtual Box的坑 转战到Virtual Box 我搜索了一番,发现已有前人尝试过比较简单的方法(把dhcp-server假设在host上)。决定使用这种方法 先按照上文链接中得做法建立host-only net 查看现有dhcp serverVBoxManage list dhcpservers 禁用相应网络的dhcp serverVBoxManage modify --netname HostInterfaceNetworking-vboxnet0 --disable 按链接中方法配置dhcp server...

  • 开发编辑器的过程中遇到的一些浏览器差异

    Tags: javascript

    测试新编辑器时发现在firefox下会有很高几率出现一个神奇的bug。 当光标在block元素(blockquote, pre, etc..)中时,按‘下’或‘右’或‘回车’键后,光标会选中block元素中第一段文本。刚开始怀疑是在FF下rangy设置selection的bug,但在注释所有js中keydown的处理事件后,还是会有此bug。 之后百思不得其解,甚至想到用scribe重写编辑器… 在观察scribe的demo在FF下的表现后,终于找出了这个很愚蠢的bug… 在blockquote中我特地的把p标签转换成text + <br>,但实际上在html4中是要求blockquote等块状元素中需要存在p标签(这是来自stackoverflow的一个回答,我没有看html4标准..),所以我特地的去除p标签反而是画蛇添足之举。 在chrome, IE等浏览器下对于<blockquote>test<br></blockquote>这种html没有特殊限制,浏览器的默认行为完全可以正常工作。 但是在firefox下,当光标在test文本末端时,按下回车,本应换行,但是firefox会去寻找当前的p标签(这是html4规范,Firefox依赖了此规范,chrome等则没有),但是我错误的没有把文本放入p标签,所以造成浏览器默认行为出现bug。 正确的标签应该是<blockquote><p>test<br></p></blockquote>这样才符合html规范。 在开发编辑器的过程中,接触到了很多这种浏览器默认行为不一致的问题。 比如firefox下偶尔会对br标签加上type="_moz"的属性。 chrome和safari下拖拽block中元素浏览器会把拖拽的文本放入span并且自动添加很多style属性。 在webkit内核浏览器中block元素里按回车会在下一行自动添加同样的block元素,在FF中则是自动换行。 如果一行中有br,在IE下光标在br之后,其余的浏览器则是在br之前(偶然通过range对象观测到的,在block末尾时IE中的endoffset会多1) 浏览器的很多上层API加上跨平台库已经让人很少能感受到js编程的平台差异,但是在contenteditable中诸如此类html中并无规定的默认行为在不同浏览器上的表现却是千差万别。尤其是号称跨平台的selection库rangy实际上在不同平台上还是会有很多bug与不一致,举例来说最基本的获取range对象,在webkit浏览器上取得range,start和end会优先是textElement,但是在FF上则会得到ElementNode。 html规范毕竟不可能涵盖所有情况,各种标签的嵌套以及不同情况下用户的操作,这些规范之外的情况只能靠具体的实现来决定行为。 就像各种的markdown解析器,在规定之下会输出相同的结果,但若在规定之外,每个parser都会有些许的差别。 看来浏览器距离完美的平台还有不短的距离..

  • javascript学习笔记(二)

    Tags: javascript

    1, 函数中this的四种情况 //1. 函数绑定到对象上时, this为对象 a = {func: function(){ console.log(this)}} a.func() // this是a //2. 没有绑定到对象时,this为全局对象 (function(){ console.log(this) })() //上面的this在浏览器中是window(全局对象) //3. 用new调用时this绑定到新构造的对象 //4. 函数对象的apply方法 (function(){console.log(this)}).apply("hello") //通过apply可以指定function的this值 2, 原型 //javaScript中的原型继承必须通过函数来完成 //function有一个很重要的prototype属性,默认值为{} (function(){}).prototype //=> Object {} //函数的prototype属性是javascript中原型的关键 //用new去调用function时,会以该函数的prototype为原型构建对象(常用此行为来模拟继承) a = {hello: function(){return "world"}} //现在来构建一个链接到a的对象,首先需要一个function A = function(){} A.prototype = a //用new调用A时会构建出以对象a为原型的对象 b =...

  • javascript学习笔记(一)

    Tags: javascript

    以前没怎么用过javascript(仅停留在简单的dom处理与ajax上),身为后端程序员对其印象仅有杂乱 完成简书新richtext编辑器的基本功能后,感到js也没这么不堪,反而基于原型的模型能很轻易的应对反射,动态定义Function/Object等‘元编程任务’ 并且和ruby中的’元编程’不同,在js中这些就是通常编程 “原型”的表达力不弱于OO,并且复杂程度远小于OO。当然在javascript中的实现还是略微杂乱..虽然这门语言很多细节部分的设计让人匪夷所思,但是其核心的原型功能还是兼具了精简与好用这两处优点 遂打算好好学习下js, 并在阅读《JavaScript语言精粹》时把一些知识要点记录下来 本文会以tips的方式罗列从书中获取的知识要点,以及一些我自己的理解和对这门语言的想法 所有内容基于ECMAScript-262 (javascript 1.5) false,js的条件判断中 0, -0, null, false, "", undefined, NaN 均为 false(coffeeScript中的?操作符编译为typeof a !== "undefined" && a !== null;使其行为接近一般语言) Number,js中数字储存为(相当于java中的)double, 所以1/2会等于0.5 基本类型,js中有 Number, Boolean, String, Array, Object, undefined几种类型,Boolean, String, Array, Object都属于Object(因为可以用原型系统, null比较特殊) 对比,js中==仅对比值,===更为严格,要求类型也一致(coffeScript把这两个颠倒了过来,更加接近一般语言的行为) 注释,js中单行注释用//,导致你无法用//来表示一个空的正则,/**/也是 原型继承,js中通过键来获取对象中的值时,如果该对象无此键,则会到对象的原型链中去查找,直到Object的prototype,任何对象都隐含链接到Object.prototype,该值默认是{} 更改对象的键时不会影响到原型 delete操作符,用来删除对象的键(不会影响到原型),这时对象原型的相应键会暴露(如果有的话),再次delete会被忽略并返回true(这代表如果原型上有key,则没办法在对象上删除该键,但是可以赋值为undefined) for..in 语句可以用来遍历对象的所有key hasOwnProperty方法用来判断对象是否有该key(从原型中继承的不算)

  • Yet Another Markdown Parser, 没想到还原度还挺高的

    Tags: Ruby markdown

    最近写了个markdown parser练手, 发现这种有规范的东西非常适合TDD, 照着markdown语法来写spec, 然后一个一个将其通过, 之前从未试过这么彻底的TDD 是写代码写的很爽时顾不上测试 是spec一定要事先定下,如果是创造性的编程, spec没法确定, 在代码和spec间来回改动就失去了TDD的意义 托TDD的福,写好各个语法的parse后跑了下GFM的source页,没想到还原度还挺高的 之后fix了几个小地方,parse的效果已经比较完善了,而且因为TDD 保证了测试的覆盖率(2k行左右的代码估计1k多都是spec),可以放心的修改代码,只要可以pass spec基本就是没问题的 之前一直感觉TDD有点名副其实, 经过这次实践感觉这种编程方式真的能帮助你写出可靠的代码 当然关键还是要事先确定spec, 如果不能确定spec我是绝不会用TDD的方式去开发的, 实际上我把minidown改成支持GFM时就改动了一些spec, 当然相应之前的所有代码也需要修改,相当于白写了一遍测试 benchmark了下各种markdown parser解析14000篇文章的效率 跑在the ruby racer 上的marked大概3.8s可以完成 minidown 大概16s可以完成 maruku报错.. kramdown 大概200+s可以完成…(这货README里写着fast..) 后3种都是pure ruby的markdown parser marked考虑到主要是前端使用,可能没有太多考虑效率,看得出ruby和v8差距还是挺大… 对于后边两个结果到是很惊讶, 没想到minidown在pure ruby的parser里还挺快的..

  • ruby中的lambda为什么是Proc类

    Tags: Ruby

    当然写之前我试着在网上搜了下, 果然没有搜到类似的问题。 lambda为什么不是Function, Method 而是Proc ? 这个问题当然没有标准答案,于是我做了一番推(猜)测 lambda和proc都是Proc类,这样已经可以看出一些端倪,proc既然叫proc当然是Proc类的主角,所以lambda只是Proc的一个附属,因为已经实现了proc,所以就顺手实现了lambda。 proc是用来代表block的(双飞燕中的话是proc更接近block), 如果我们在参数中用&block,我们会得到一个代表block的proc对象, 并且proc和block在各种行为上几乎都是一致的。 再来看下lambda,双飞燕中说lambda更接近method 当然…其实他们的区别是很大的,ruby中method必须bind到一个object上才可以调用,method(消息)必有接收者 而lambda就很异端了,仅仅是一段可执行代码,没有什么可与之对应的(python中的method可以对应为第一个参数为self的lambda) 而与proc的区别仅仅是传参和上下文跳转上更像method,并且在block的压力之下几乎没有任何用处.. “虽然很鸡肋, 但是实现上很简单(把proc稍微改下?) 干脆一起实现了,说不定谁可以用得上” -————————-(我猜测的实现lambda时matz的想法) 于是就同归于Proc类了

  • Celluloid中的任务中断和Condition

    Tags: Ruby

    ######Celluloid有个很神奇的机制(<–示例代码) Celluloid每次任务(方法调用)会用Fiber去包装 当一个FiberTask因为某些代码被中断时,此时Celluloid可以回到线程执行任务的方法 相当于中断的任务已经结束 之后Actor线程继续的从mailbox取任务 ######某些代码! FiberTask会因某些方法被中断,上面的示例代码中中断当前Fiber的是sleep方法,这个方法由Celluloid做了覆盖 sleeper = Sleeper.new(@timers, interval) Celluloid.suspend(:sleeping, sleeper) Celluloid.suspend这行代码就起到中断作用,(知道它会中断当前Fiber即可,实际会根据后边的参数调用一些callback) ######中断了。。如何恢复? def before_suspend(task) @timers.after(@interval) { task.resume } end 这就是参数sleeper的callback,可以看到利用定时器来执行恢复的task 如果Fiber.resume的时候当前正在执行别的FiberTask会怎么办?岂不是会乱掉? after定时器也是通过FiberTask来执行的,所以到时间后我们的block会被传到mailbox中,就像一个新任务被调用一样,完全没有问题! ######某些方法能中断? actor当然不是再任何情况下都可以自己中断..上文sleep方法是之一,另外Celluloid还提供了Condition类来进行中断 Condition类和ConditionVariable行为类似 ######Condition ConditionVariable主要是用来在线程间统一资源的,README很详细 在Celluloid中应该用Celluloid::Condition来完成这件事,他们的行为是差不多的 Celluloid::Condition的好处是会中断当前的FiberTask, 这样Actor可以去执行之后的Task,而不是一直block住,基本原理和之前sleep是差不多的 Condition可以很好用的去做些同步操作,而且不会浪费线程

  • ruby-stdlib-delegate

    Tags: Ruby

    一直对delegate效率抱有疑问(虽然从未做过牛X到需要改进这里效率的项目..) SimpleDelegate使用的果然是method_missing方法 method_missing据说是很慢的。。因为ruby要查询很多层方法 ActiveRecord采用的改进方案是method_missing中去创建方法,这样第二次调用就会命中创建的方法了 不过不到框架的级别应该是不需要在意这些的.. DelegateClass方法会返回一个匿名类,并且作为参数的类的实例方法都会在其中定义一遍 所以没有method_missing,当然用起来不是那么Simple.. delegate库解决了像是equal?, methods, instance_methods等等很多类似的小问题

  • Celluloid中的Atom Mode与锁

    Tags: Ruby

    Celluloid默认是Atom Mode执行的, 这种模式下可以中断当前执行的任务 先执行下一个 Celluloid提供了一个sleep方法,在Actor内部调用sleep时会中断当前Fiber并且用timer异步来恢复 def before_suspend(task) @timers.after(@interval) { task.resume } end 当中断当前的TaskFiber时,Actor即可处理下一个message,被中断的message等待timer去恢复自身 def task(task_type, method_name = nil, &block) if... .... else @task_class.new(task_type, &block).resume#中断fiber时从此处返回 end end 我们在Actor上的每次调用都是一个独立Fiber Actor 线程是一个worker,来运行多个Fiber,个人感觉这里有点矛盾,Celluloid把多线程程序,变成了多Fiber程序,不同的Fiber很有可能并发访问同一个变量 而exclusive就是Celluloid中的Fiber的锁。actor本身就是消除锁的,而现在却又引入了一个新的锁。 不过实际写过Celluloid程序后,感觉还是不要对这个锁太担心的,实际中只有中断时(调用sleep)才会插入新的fiber,而我们在写需要同步执行的代码时 一般的正常人类是不会在其中插入个sleep的,如果必须确定代码的同步 则要把代码写在exclusive块中(一般不需要,exclusive作用是阻止在本块中Fiber的中断) 这种机制虽然带来了少许的复杂性但是 绝大多数情况下我们无需知道这种机制也可正常的运作程序 即使用到exclusive, 也只是很简单的应用 可以更加有效率的利用线程 Celluloid把任务和worker之间隔离开,之后可能会把thread和actor也进行抽象分离,这样增加了灵活性和效率, 不过随之也带来了复杂性, 其中得失还是很难说清的

  • Celluloid::Actor结构与调用过程

    Tags: Ruby

    ruby是面向对象语言,但是Celluloid做到了无需更换代码,仅在类中include Celluloid就可以进行面向Actor编程 class A include Celluloid def foo puts "bar" end end 此时A已经代表一个Actor类 a = A.new a.class #A a.class.ancestors #[A, Celluloid::InstanceMethods, Celluloid, Object, PP::ObjectMixin, Kernel, BasicObject] a.is_a? A #true A === a #true of course! a.is_a? Celluloid #true Celluloid === a #false W..T..F?? wtf? a是A的实例,我们的测试可以通过 但是当我们用Celluloid来测试时a.is_a?和Celluloid.===结果不一致 ###why? 因为a并不是A的实例 a.class #A...