Parallet - My Dynamic Language - 介绍

Parallet - My Dynamic Language - 介绍

简介:

    Parallet是笔者自创的一种新的编程语言. 主要是基于JavaScript和C#的语法, 可以说是JS和C#的混合体.

    Parallet的存在意义在于三点:
        1    -    异步与并行的直接支持, 在Parallet里, 函数默认是异步的, 上万个异步函数并行地执行时只消耗极少的线程. 
        2    -    沙箱环境, Host通过给Parallet代码提供有限的API, 可以保护Host不怕恶意代码的入侵, 适合做开放平台或游戏插件.
        3    -    副本模式, 也可以叫微进程模式. 一个程序里, 是可以执行多个完全隔离的Parallet代码. 并且一次编译多次使用.

背景:

    由于对各种语言的不满, 笔者一直都很想构建自己需要的语言.

    在几年前, 网络上刮起了异步与并行编程的风气. 当时笔者用C#尝试去编写完全异步的一个小应用, 过程非常艰辛, 虽然得到了不少经验, 但是也明白到异步编程真的很难很难, 程序员即使能勉强表达自己的逻辑, 也很容易出现各种BUG, 有一些还是致命的, 例如在异步编程里, 要捕捉和处理异常, 是非常艰辛的事情, 需要编写大量的额外代码, 一个不小心, 线程挂了, 后果极为严重. 结果就是, 用于逻辑的代码, 才那么几行, 其他的代码都为了异步努力去了.

    IPhone和IPad出来后, 网络又刮起了移动平台编程的新风气. 面对市场的迅速变化, 笔者也不甘落后, 所以最后还是去研究了一下.  结果Objective-C的编程方式让笔者打了退堂鼓, SDK还没下载, 就已经不想继续下去了. 毕竟像Objective-C这种声称自己是OOP的但是又不带垃圾回收的语言, 笔者真的接受不了. 还不如用C++, 起码不用学Objective-C那些和C没有什么关系的语法.

    在3个星期前, 面对这些困境, 笔者突然想到, 如果有一种语言, 能够统一各种平台语言, 那岂不是一件美事? 大家可能立刻会说了, Java和.Net不就是在干那些事了? 非也.. 笔者不是要创造出一种新的平台, 而是要创造出新的语言. 无论是写.Net的程序, 还是Java的程序, 甚至是IPhone的程序, 只需要携带一个小编译器加小类库, 用同一种胶水语言来编写程序, 甚至轻松地达到跨平台的效果(那则需要跨平台的Proxy/Bridge框架), 那岂不是一件很愉快的事?

    想着想着, 笔者的灵感就越来越多, 加上过去对异步函数的一些想法, 笔者最后决定要开发一种新的语言 : Parallet

特色:

    Parallet同时支持强类型与弱类型变量. 例如string str定义了字符串变量, 而var obj则定义了未知类型的变量. 

    强类型变量, 无论是在解释执行还是生成IL或机器码后执行, 都是严格引用具体类型的成员, 属于编译时的绑定. 例如 str.Substring(3,2) 这样的执行, Substring在编译的时候就已经确定下来, 不可改变. 这种方式对性能的提升有较大的效果.

    对于弱类型var obj=str;obj.Substring(3,2), 这个Substring则是需要在运行的时候, 才去询问obj是否有那个方法,然后再执行它, 这一般称作后期绑定或动态绑定. 由于存在动态绑定, 所以Parallet不打算支持interface. 写惯脚本的人会懂的.

    Parallet支持class, 开发者可以定义属于自己的强类型. 支持单一继承, 支持多态, virtual/override可用到属性与方法上.

    Parallet支持Closure , 写惯JS,明白C#的lambda的人会知道这个特点是非常方便的. (听说Java到现在还不肯支持Closure..)

    Parallet支持Closure下的class , 这到底是甚么回事? 简单来说就是 function GetX(a){ class X{function GetArg(){ return a;}} return new X()}, 以后笔者会详细说明的.

重点:

    默认为异步函数, 是Parallet的一个很重要的特征. 要理解异步函数, 首先就要明白普通的函数, 发生阻塞时的弊端.
    (由于防止编程术语的混淆,  在这里, 异步函数就是指Parallet的异步函数, 而其他函数以后称作为普通函数, 而不称作同步函数)

    一般语言写一个函数: function MyLogic(){ Thread.Sleep(5000);return true; } , 这个函数执行的时候, 会挂起线程5秒. 当系统的并发数是很少的时候, 这根本就不是问题, 线程可以随便浪费的. 但是当编写一个并发数量超大的应用时, 由于一个线程默认分配1M的内存作为stack, 2G的内存一下子就会被2000条线程吃光了. 在笔者的Win7x64加4G内存的情况下,申请3千多条线程就会直接抛出内存不足的错误. 所以, 可以说, 线程资源还是非常昂贵的, 所以才有了线程池, 和异步编程的概念. 

    异步编程, 最主要的思想是, 通过注册一个回调函数,或者是事件, 把当前线程的逻辑退出掉, 然后等待函数的执行, 恢复相关的数据, 然后继续执行逻辑. 在需要的时候, 再一次传递delegate, 然后完整地退出线程, 等待delegate的被执行. DotNet的BeginXxx方式, 就是通过传递delegate来实现这个异步效果. 而JavaScript的异步编程则依赖于事件或setTimeout的方式. 而传统的Win32窗口消息队列, 其实也是异步编程的原型.

    通过编写异步的代码, 任何函数被调用时, 都不会阻塞线程, 这样就可以避免越来越多的线程处于挂起的状态而导致系统变慢甚至崩溃了. 大多数写过socket服务器程序的人, 都应该深有感触.

    异步函数, 就是在语法上, 自动帮开发者实现了这种线程的退出与重新进入的机制. 开发者不需要主动传递delegate了..

    例如上述函数, 在Parallet是这样写的 function MyLogic(){ Parallet.Sleep(5000);return true; } , MyLogic摇身一变, 成为了异步函数. 注意的是, Parallet里不存在Thread.Sleep, 因为要睡眠的, 是Parallet的异步函数, 而不是这个异步函数所在的线程.  当Parallet.Sleep 被调用时, MyLogic, 以及调用MyLogic的函数, 都会立刻停止. 执行MyLogic的线程, 立刻可以释放掉, 或者去执行其他逻辑. 当Sleep结束后, MyLogic与它的调用者, 会重新放到一个队列里, 等待被执行. 一旦被执行时, CPU又回到了Sleep之后, 然后MyLogic会返回true, 继续执行MyLogic调用者的其他部分.

    异步函数有一些特点 : 
        1    -    异步函数可直接调用普通函数 , 普通函数若是发生阻塞, 则异步函数也会被阻塞, 这有违异步函数的设计. 所以, Parallet的内部类库里, 所有普通函数是不允许阻塞的, 凡是需要阻塞的函数, 必须设计为异步函数.
        2    -    普通函数调用异步函数, 要么用阻塞的方式等待异步函数结束, 要么就是用传统的回发方式去进行传统异步编程. 这实际上就相当于BeginXxx的情况了.

    基于上述的2个特点, 在Parallet里, 只调用普通函数的函数, 都可以被编译成普通函数, 用于提高性能. 而有任何不确定的情况下, 函数都会被编译成异步函数, 所以, 在Parallet里, 是不存在普通函数调用异步函数的情况. 这就实现了, 任何异步函数的调用链, 都可以随时停止, 释放线程, 和被恢复执行, 并且保持函数调用链以及他们的参数状态等等.

   关于异步函数的细节, 笔者明天或后天会单独写一篇文章来说明它的实现原理的.

   以下是一个Hello World的单线程例子, 用于说明这个Parallet的原理:
    (echo是测试程序自己添加的扩展函数. 任何Host都可以往Parallet里添加自定义函数与类型)

Parallet.Start(function()
{
	echo("Hello\n");
	Parallet.Sleep(0);
	echo("World\n");
})

echo("111111\n");
Parallet.Sleep(0);
echo("222222\n");
Parallet.Sleep(0);
echo("333333\n");

输出:
111111
Hello
222222
World
333333

    在这个例子里, Parallet.Start启动了一个并行的函数调用. 但目标的函数并不会立刻执行, 它必须等其他处于同一线程下的函数被挂起或者是完全退出后, 才会被执行, 而且还需要排队. (另外, Parallet支持多线程, 以后会提到)

   Parallet.Sleep(0)充当这种挂起函数的目的 (最外层代码也可看做是处于一个函数内) . 当111111输出后, 外面的代码被挂起, 然后新的函数便开始执行, 输出Hello , 然后新的函数也被挂起, 于是外面的代码继续执行, 如此循环.

    这种方式, 就是Parallet对异步与并行编程的核心思想. 就这么简单的逻辑, 可以完全地改变编码的风格, 轻松地应付各种情况. 以后笔者会写更多的文章去描述各种常见与有意思的技巧.


总结:

    好了, 写到这里, Parallet的主要特点, 都已经提到了, 其他的特点与细节, 以后会在这个博客里慢慢补充上. 

    Parallet的信息也公布到http://www.parallet.net/上去, 和博客不同的就是, parallet.net上不会有详细的记录, 它主要显示最新的资料.

FAQ:
  1. 当前进度 - 实现了 基础语法,Sandbox/副本,解释执行,异步/并行/多线程,Class/强类型,Function/Class/Closure
  2. 下一目标 - 弱类型上的动态绑定, 动态编译/静态编译, 各种类库
  3. 长远目标 - 建立某些应用框架(Web,Mail..) , 在C++,Java,JScript甚至它自己上实现Parallet
  4. 性能? 目前只实现了解释执行, 比VBScript快,比JScript(IE8)慢一点,  是LUA(解释执行)的1/5,
        chromeJS(编译执行)的1/70, C#的1/140, 相信编译版本出来后, 能提高100倍速度.
        不过要注意的是, 作为一种胶水语言, 影响最终性能的最主要的还是它调用的类库.
    在睡觉前, 说说一些可能有人感兴趣的问题  :  这个东西到底开不开源 ? 暂时只能说 , 极有可能在笔者30岁时(年底)开源..

   在本博客的文章的发表顺序地计划是, 应该是根据笔者这段时间的思考顺序来逐一描述它的实现方式.

    如果你坚持阅读到这一句话, 那么感谢你对这个项目的兴趣. 希望大家以后一起探讨这个有意思的项目.

posted @ 2011-06-16 01:12  Parallet  阅读(1768)  评论(15编辑  收藏  举报