在普遍认知中,软件开发实践是一项充满不确定性的工作,这是由于编码工作占据了其绝大部分的工作,而编码本身就是具有极大不确定性的。同样,计算机科学被视作一门门槛低,基于经验,而无理论意义的纯工程类学科。这种观念不仅为广泛非本专业内人士所共持,即便本门师生,从业人员也偶有赞同。本文试图通过一次对SEDA服务器架构的编程实践的学习与研究,找寻一种科学的解决问题思路。在本次实践中,笔者将强调数学在软件开发中的重要地位,同时指出在核心算法的制定工作阶段,数学是其最重要的工作,而非经验性的设计模式套用。
关键词:SEDA,多线程,并发,量化分析
Staged Event Driven Architecture (SEDA) 中文译为阶段事件驱动架构,也称为阶段式服务器模型,是加州大学伯克利分校研究的一套优秀的高性能互联网服务器架构模型。这是一类软件架构模型,它将复杂的、事件驱动的应用分解为一系列通过队列连接的阶段。该模型避免了基于线程的并发模型所带来的高负载问题,同时将事件与线程调度从应用逻辑中解耦。通过对每个队列实施准入控制,使服务得以状态良好地加载。当需求大于服务能力时,能够防止资源过度使用。其设计目标是:支持大规模并发处理、简化系统开发、支持处理监测、支持系统资源管理。
在本次软件实践中,笔者期望得到一个具有可用性的SEDA服务架构的实现方案,并试图将数学方法的使用贯穿于整个过程之中。
笔者将在编程工作开展之前,对量化分析等数学方法进行引入而进行基础的概念介绍。
在现代哲学、数学、逻辑学、语言学中,命题是指一个判断(陈述)的语义(实际表达的概念),这个概念是可以被定义并观察的现象。命题不是指判断(陈述)本身,而是指所表达的语义。当相异判断(陈述)具有相同语义的时候,他们表达相同的命题。
更为简单的定义中,命题是一个或真或假的陈述语句,但不能又真又假。
1. 华盛顿是美国的首都。
2. 多伦多是加拿大的首都。
3. 1+1=2。
4. 2+2=3。
这这些例子中,1和3为真命题,2和4为假命题。
1. 几点了?
2. 仔细读这个。
3. x+1=2。
4. x+y=2。
语句1和2不是命题,因为它们不是陈述语句。语句3和4不是命题,因为它们真假性无从判断。
显然地,并非所有的命题都能被称之为科学理论。所谓科学理论实质上是一个哲学中的约定,在这个约定(波普尔的两个约定)中,科学理论被定义如下:
1. 科学理论是一个严格的普遍陈述。
2. 科学理论要是有一个或几个理论被证伪,整个理论也就被证伪。
除此之外,可证伪性是一个科学理论的必要属性。可证伪性是由经验得来的主张的必要属性,却不是充分属性。可证伪性可表述如下:
如果一个主张是可证伪的,则至少在理论上存在一种观测的方法(即使实际上没有进行这项观测也无妨),来表明这个主张不符合重言式的标准(即这个主张不总是真的)。对某种描述进行观测的逻辑前提是它描述的事物是存在的。
例如“所有的天鹅全都是白色的”这个主张可以被“一个黑色天鹅”的观测证伪,虽然这个观测并不一定会发生。一个可证伪的命题必须定义某些被禁止的情形。例如,在这个例子中,“所有的天鹅全都是白色的”这个主张禁止了“黑色天鹅”的存在。由于理论上可能存在“观测到黑色天鹅”这个反例,“所有的天鹅全都是白色的”这个主张是可证伪的。 再比如假设现在有一个人宣称“我说的话一直都是对的”,那么我们考察他以前说过的话,如果有自相矛盾的地方,那么这句话肯定是个假命题。然而,即使这个人过去一直贯彻一种想法,在他自己的言论中没有自相矛盾之处,也不能作为足够的证据证明这句话是个真命题。
任意一个科学理论都应该是经验上可证伪的,而任何一个非科学的理论都是不能用逻辑证明的。同时,一个科学理论不应该具备全部的可能性。如:
1. 明天以后的某个时间,有可能下雨,有可能不下雨。
2. 1+1=2。
以下将带来计算机程序与算法的基本定义。
计算机程序或者软件程序(通常简称程序)是指一组指示计算机每一步动作的指令,通常用某种程序设计语言编写,运行于某种目标体系结构上。
在数学和计算机科学之中,算法(Algorithm)为一个计算的具体步骤,常用于计算、数据处理和自动推理。精确而言,算法是一个表示为有限长列表的有效方法。算法应包含清晰定义的指令用于计算函数 。
大体上,程序与算法之间的区别有以下几点:
1. 一个程序不一定满足有穷性。例操作系统,只要整个系统不遭破坏,它将永远不会停止,即使没有作业需要处理,它仍处于动态等待中。因此,操作系统不是一个算法。
2. 程序中的指令必须是机器可执行的,而算法中的指令则无此限制。
3. 算法代表了对问题的解,而程序则是算法在计算机上的特定的实现。一个算法若用程序设计语言来描述,则它就是一个程序。
在日常的软件开发实践中,我们交付的一个软件/系统,可能涵盖若干文件及程序,究其根本,即承诺所供给的工具是对特定用户的特定问题的通解,或者说是一组特定的算法。进而言之,我们在认定所提交软件的同时,可视作提出了如下一个科学理论:
?p∈P={(x1, x2, ..., xn) | x1∈C1, x2∈C2, ..., xn∈Cn},
?r=algorithm(p) 使得
r∈R={(y1, y2, ..., ym) | y1∈B1, y2∈B2, ..., ym∈Bm},
显而易见,这是一个科学理论,因为他是容易证伪的,只需要:
?r=algorithm(p) 使得
r?R={(y1, y2, ..., ym) | y1∈B1, y2∈B2, ..., ym∈Bm},
同时我们可以知道的是,当n→∞时,p→∞(甚至p可能是n的高阶无穷大),也就是指任取有限组的p作为输出并验证结果r,仅仅能证明
r∈R‘={(y1, y2, ..., ym) | y1∈B1, y2∈B2, ..., ym∈Bm},其中R‘是R的某个有限大小的子集。因而为了证明algorithm(p)正确性我们只能通过逻辑工作完成,而不能通过反复测试实现的。
简而言之,算法作为软件的灵魂部分,应该是某种科学理论,可被经验证伪而非证实的,要证明其正确性只能从逻辑入手。
注:期望通过多次随机测试并评测其结果的正确率在直至本文现阶段是行不通的,一个简单的原因是,我们期望随机测试能带来正确性证明本质上是在做某种抽样检验的工作,但因为我们样本空间是无穷大的,因此有限次的测试永远没有办法得出样本结果对整体而言的置信度。这就好比在常规的抽样检验中,总量是1000的样本,抽取100个进行检验所得结果总是比10个更有可信度。然而在当前讨论范畴中就像从10000000个样本中评价对其中1个或2个进行检测哪个更可信,是无意义的。
又,从逻辑学上而言,这种工作本质上是进行归纳并假设的行为,然而归纳是某种认识论,不能成为假设成立的前提,这个工作依然缺乏逻辑证明的部分。
在这个例子中,我们将试图探讨冒泡算法及归并算法的性能优劣(此处特指其时间复杂度的比较),算法本身的工作本文将不作赘述。
为此我们将定义如下:
An是指一个含有n个整数的有序集合{a1, a2, a3, ..., an}。
?An={a1, a2, a3, ..., an}
?function(An) 使得:
A‘n={a‘1, a‘2, a‘3, ..., a‘n}, 其中a‘1≤a‘2≤a‘3≤...≤a‘n。
特殊地,我们取An为已逆排序的长度为n的序列,及恰好a‘1≥a‘2≥a‘3≥...≥a‘n。在这种情况下我们可以轻易地得知,前者进行了n2次操作,而后者仅仅做了nlgn次操作,我们是否可以认为冒泡排序比归并排序慢呢?
又特殊地,取An为已正向排序的长度为n的序列,我们可以轻易地得知,前者事实上仅仅做了一系列的比较,而并未进行实质的操作,耗费的可以视作某个常数量k的时间,而后者则依然进行了nlgn次操作,我们又是否可以认为冒泡排序比归并排序快呢?
尽管两次测试的结果大相径庭,但两者本质上是逻辑上对等的两次互相独立的假设检验。虽然我们知道归并排序的时间复杂度确实更低,也就是第一个场景的结论是与之符合的,但事实上这两个场景的结论却都是不可信的,因为他们都试图用一次特殊的假设检验,来论证一般规律。
在绝大多数算法适用的场合下,测试都是一种试图将有限的个例推广到无限的可能性的尝试,而这既是数学上错误,又是哲学上不能等价的:当我们尝试使用测试来对算法进行证实的时候,本质上并不是一个严密的逻辑形式推理,而是一种概率推理。然而在绝大多数现有的测试过程中,这些工作本身又是不符合概率论的基本要求的,其结论本身也就不具有可信度了。
(未完待续)
原文地址:http://www.cnblogs.com/xyshorkrina/p/3756150.html