关于用DELPHI开发服务器软件中的一些经验(100分)

  • 主题发起人 主题发起人 element
  • 开始时间 开始时间
不是我鸡蛋里挑骨头,我认为这个方面大家可以多交流,专门讨论控件使用不应该成
大富翁的主流。
 
我用意你的观点。
 
总之我的观点是服务器程序开发是能开的内存最好一次都开上,循环使用,尽量避免
用string和动态分配内存,能缓冲的资源尽量缓冲。
 
张无已说的尽量少用字符串(String)我想应该说的是尽量少用String进行连接运算,比如大量的String + String,因为String是自管理内存的数据类型,本质是动态数组,每次使用一个新String时其实就会另外分配一次空间,只是其在引用为0自动释放而已,大量的字符串连接会产生大量的内存分配/释放操作,象String+String我认为至少要分配三次内存.就极可能象
张无已说的产生大量内存碎片.
但我非常喜欢String的另类用法,从String的结构来看,它前面包含了引用计数和长度字段,
用来分配内存和操作内存数据是很适合的,我经常这样使用.
SetLength(S,1024);
然后就可以方便地以各种方式操作S了,包括以指针方式访问,以数组方式访问,以String,pchar指针等,如
pbyte(Integer(S)+100)^ = $F3;
Pbytearray(s) := $F3;
S[100] := #31;
MemoryStream.WriteBuffer(Pointer(S)^,1024);
可以说是方便之极,要写入的数据根本不一定限于字符串.

优点,String内部应该也是用GetMem分配内存,而String可以方便地分配内存和操作数据,万一忘记SetLength(S,0),字符串也可以自己释放内存(使用对象的地方就实现接口,以接口操作对象也有一定自动回收能力).使用的要点是是一次性分配足够长度.避免出现重新分配大小,另外尽量少用字符串连接运算等.

 
to lynu:
这里讨论的是服务器软件的编码,不是做个人软件,所以很多因素考虑的比较仔细。
DELPHI对string类型的一些操作进行了类似操作符号重载的控制,
比如 str:string;
setlength(str,12);
str._addref; //编译器内部做了处理
try
finally
str._Release//减少引用记数,
end;
这么来看,在服务器的代码里多了很多垃圾代码,影响服务器性能,所以string在Client部分是没有什么的,但是在服务器在大规模并发的时候消耗的时间可不是单用户时的那么小的消耗。同理,对于动态数组也不适合在服务器的编码理出现。
 
呵呵,当然道理是这样的了,象画一个点0.001s与0.0001s感觉没分别,画一个屏的点差别就是很大的数字了,这个当然大家都知道.
举例说,有一段代码需要在多个地方调用,多数时候大家都会写一个公用函数,但函数调用时的入栈出栈也是需要执行一些指令的,特别是调用次数很大的情况,是很不菲的成本.究竟要不要写一个公用函数,我觉得就不是简单的结论了.
再如象OOP中的类,肯定会有额外的代码,以及"多余"的内存占用,起码vcl组件是基本上不要用的,属性包括published的事件,不但RTTI占用资源,使用的效率也会有问题...
个人觉得有些多余的代码也是没有办法的,如果一定要过于追求这个,那最后肯定会得出只
能用汇编的结论.因为用高级语言,或多或少就会产生一些"多余"的代码,我认为如何把握,最终还是要根据实际情况分析效益与代价.
我们用delphi,主要原因肯定包括delphi的快速高效开发,非常好用的VCL组件框架等,但这些肯定也一样有代价.但是我们继续在用,就是因为这个代价换来的效益值.如果不值的时候,我想我们就会用一个"值"的方案.
 
lynu:
大家在这讨论服务器软件,不是讨论普通软件的编码,所以你上面的东西基本都是没用的
都是空谈,在服务器的编码里不太适合用动态分配的数据类型,不管你说多大的帽子,找出
N多理由还是不适合。就想搞算法方面的开发的时候没用人用oop方式,你看acm比赛谁用
C++的开发方式,不适合就是不适合。我们做的就是精量减少在性能方面的消耗,不是走极端,就像你说的用汇编,即使只要编译器优化的好,少用一些消耗性能比较高的编码方式
经过优化出来的代码不一定比纯汇编的代码效率低。你上面所说的我上面早就说过了,只
适合写Client程序。
 
说了这么多,谁能贡献一些网络编程的基础教程啊?
在书店的教程都是教你怎么用组件的。

来自:张无忌, 时间:2003-12-9 13:10:00, ID:2343321
不是我鸡蛋里挑骨头,我认为这个方面大家可以多交流,专门讨论控件使用不应该成
大富翁的主流。

这个是同意的,可是大部分人对这个方面还是不懂,关键是各位大侠能带领
小弟们入门才对,这样dfw才能越来越好,越来越吸引人
 
张无已水平很高,delphibbs上大家都是知道了,没有人怀疑.我个人也是很佩服的.
但是,比如这位用DXSock做服务器开发的楼主,他就未必一定需要自己从最底层开始写个框架完成TCP/IP通讯服务器,因为DXSock可以满足他的需求.自己从头写当然可以获得一些性能的提升,但代价就不知多少了.
其实我用String的理由我前面说过了,我个人喜欢用String来分配和操作内存,也尽量在服务器端使用接口,因为我做的系统都不大(大的也不用Delphi来写服务器),而我一直就非常喜欢Java特有的拉圾回收机制,以为是服务器端开发中很有用的.虽然Delphi没有这种机制(或者需要自己实现,我想可能有可能用特殊线程来实现,但我想没有多少人愿意这样做,起码到现在,没有看到这样的框架),但使用动态数组和接口部分达到一些目的.
我跑题了,不说了.另外我个人还提醒一下,做比较大一点的系统,好象用Java方案的比较多.Java超级吃内存的东东,还需要虚拟机,很多用Java做的系统速度也比较慢.但用的系统就是多,为什么?因为有很多现成的框架和产品供我们使用,这就是权衡成本与效益后的结果.
[:D][:D][:D]不要扔砖头,其实我一直也在研究适合中小分布式Internet应用的系统框架,因为我个人十分看好这类应用以后的前景.不过我就从不想什么都自己从头写.
 
TO :lynu
这里是讨论DELPHI开发,呵呵,不是讨论JAVA开发的,拿JAVA做例子不太适合哦
而且DELPHI没有成熟的框架做这个方面的开发,所以在这个方面开发的时候当然
要尽量避免使用一些比较影响性能的东西东西。而不是把DELPHI当JAVA用,什么
方便用什么,我以前用string当缓冲,在500多个并发连接大压力测试的时候,时
间不长,就出内存异常了,Delphi的动态内存管理是不能和JAVA的,你看GetMem.inc
就知道了,写的太简单了,根本不能和Java的复杂的垃圾回收机制做比较,两者
差别太大所以在服务器里进行自己的内存管理是很有必要的。
 
张sir,高手!还有搂住叶可以,当然还有许多,你们是我的偶像!谢谢你们的东西让我学习。
 
欢迎继续讨论,我来听课[:D]
 
看大家讨论得热闹,也发个帖子来凑凑数![:D]
很同意张无忌的说法,写服务器类程序的时候能不用vcl就不用(不是说TButton之类),一些关键业务的处理还是从底层开始写为好。
说个我们项目中碰到的例子:
一个全省性的大项目,基于分布式C/S构架,各地的数据通过专网实时传输到业务处理中心,传输本身的业务很简单,就是把各地数据库中的记录打包,然后通过socket传到中心,再插库。以前服务端的插库都是用BDE(oracle数据库),小数据量的时候还可以接收,但随着客户端的增多,数据量的增大,问题越来越明显:插库速度越来越慢,经常报内存读写错等等。
这次程序升级,我们把服务端做了这样的改造:
1、所有客户端传输过来的数据先存在本地的一个文件队列中,再从文件队列中取值进行插库,这样就大大增加了数据吞吐量。
2、扔掉BDE,直接使用oci插库,这个方法极大地提高了效率,原来BDE插库的峰值速率大概是50r/s左右,现在达到了200r/s左右(30多个字段的表,有唯一性索引),最重要的是稳定性极大的提高,运行到现在没有出现过内存访问错。
3、去掉所有动态内存分配的东西,队列服务器中(包括插库)没有一句new、getmem之类的语句,连string几乎都没有,全部采用array.

另外说个题外话,就是“通用”和“效率”的矛盾,我个人感觉在写服务器类的程序时不要考虑通用性,不要为了所谓的升级维护方便去增加一些没用的东西,也尽量少用COM这些东西,因为我觉得COM这个东西效率不高,而且稳定性也值得怀疑,关键代码中最好连类都不要去用。还有就是服务器类的程序也不必考虑界面好看不好看的问题,最好是什么界面也没有。

 
softdog,鼓掌!说得精彩!
lynu的string另类用法也很有意思。
无忌兄,你也详细点吧 [:D]
 
>>我个人喜欢用String来分配和操作内存,也尽量在服务器端使用接口
实际上Delphi的字符串String类型比C_String有更高的效率,
而且很"傻瓜", 使用方便,
在多线程中当作共享变量也没有问题的,
但是,还是要同步对它的访问,否则,结果是不可预料的

张无忌说的使用字符串出错, 我觉得是使用的方法不对,
而不应该在证实Delphi的字符串的稳定性有问题之前,就把责任归于它的身上
 
后退
顶部