1。首先通讯层跟业务层是分开的
2。数据传输使用XML字符创的并接
3。业务对象对XML进行分析执行任务问题是由于我使用了delphi的string 类型,据说string会产生大量的内存碎片会导致服务挂掉,经测试果真是。
如果不使用string作为XML字符并接,就是解析XML各个节点的属性和节点值来做业务上的分析,好像很难避免在应用服务上不使用string类型。不知道大家是如何解决这样的问题。 因为一开始我就选定XML字符串作为传输了,现在要更改工作量好大,
但是就可以尽量少用string,但遇到解析XML就还是必须使用string来的快。估计应用服务器能运行1-2各月左右,就会挂了。
并且没有报任何错误,就是死在那里。当你重启服务时报线程虚拟内存不错或者只能接收就是发送不了数据。不知道各位遇到过这样的没有,或者有什么办法不用string类型。
2。数据传输使用XML字符创的并接
3。业务对象对XML进行分析执行任务问题是由于我使用了delphi的string 类型,据说string会产生大量的内存碎片会导致服务挂掉,经测试果真是。
如果不使用string作为XML字符并接,就是解析XML各个节点的属性和节点值来做业务上的分析,好像很难避免在应用服务上不使用string类型。不知道大家是如何解决这样的问题。 因为一开始我就选定XML字符串作为传输了,现在要更改工作量好大,
但是就可以尽量少用string,但遇到解析XML就还是必须使用string来的快。估计应用服务器能运行1-2各月左右,就会挂了。
并且没有报任何错误,就是死在那里。当你重启服务时报线程虚拟内存不错或者只能接收就是发送不了数据。不知道各位遇到过这样的没有,或者有什么办法不用string类型。
type
TStrBuf = record
s: pchar;
len: Integer;
buflen: Integer;
end;procedure InitStr(var s: TStrBuf);
procedure UnInitStr(var s: TStrBuf);
procedure WriteStr(var s: TStrBuf; const s; len: ineger);
如果真是如此那么就没有那么多文章说到string在服务器上存在的问题了! 或者wr960204
有什么方法使用这个string。我找了好多string在服务器上都说存在一些奇怪的问题。首先你的应用服务器是自己写的还是第三方的。
不过,可能问题还是在多线程的处理上吧
服 务端与客户端绝对是两码事。在客户端我们提倡 Create/New 和 Free/Dispose,随用随申请,不用即释放。但在服务端要尽量避免这样做。在客户端可以随时使用 string 类型,但在服务端也必须尽量避免使用 string 。string使用起来异常方便,但我们看看编译后的代码恐怕就会只冒冷汗:原来编译器为string的方便做了那么多额外的工作。客户端要为客户解决内 存,但服务端能“浪费”则“浪费”。2、内存管理。
不得不再次佩服一下某大牛说的话:“玩服务器就是玩内存”。
内存管理不当就会造成内存泄漏和内存碎片。对于客户端而言,内存碎片几乎不算是问题。内存泄漏那么一点点也可以接受。但对于 24 * 7 的服务器而言,这却绝对致命,其重要性甚至超过了 IOCP 本身。
关于内存泄漏,只要记得保证申请和释放动作的对称性即可,外加一系列的测试工具,基本就可以把这个问题解决。
其次就是内存碎片。内存碎片问题的重要性绝不亚于内存泄漏。造成碎片的原因也是防不胜防。简单的如每次的 New 和 Dispose ,Create 和 Free ,隐晦一点的如 string 类型的操作。
解决办法:
首 先对于Create和Free,尽量少用。换句话说,尽量少用封装。适当的封装是可以的,只要封装的层次不是太深。Delphi 提供了 VCL 源码,我们可以看看即使是直接继承 TObject 那也会多做多少工作!对于频繁调用的函数,不要采用虚拟函数。这些晚绑定的函数,想调用就得查找 VMT,很费时间。对于类的普通函数,由于进行了早绑定,这个和其他非类的常规一样,不会降低效率。其次,相应的,尽量使用结构和函数来代替类。对于结 构,New 和 Dispose 也要尽量少用。要集中的使用来避免内存碎片。我们应该一次性把所预料的内存都申请完,服务器就得有服务器的样,放着那么多内存干什么。早晚都得申请,为什 么在服务端启动的时候不一次性申请完,在服务端关闭的时候一次性释放掉?既避免了内存碎片又避免了以后的再申请操作,一举两得,何乐而不为?要知道内存分 配和释放是非常昂贵的操作。不论是从时间上还是从稳定性上而言。再具体些,怎么保存这些申请到的内存?怎么保证在必要的时候可以很方便的再申请或及时的释 放一些内存?我采用的是链表。在每次为一个数据结构申请内存的时候,先查看这个链表是否为空,如果不为空,就从这个链表中取出一个内存块,不需要真正调用 函数申请。如果为空,再动态分配。使用完成后,把这个数据结构不释放,而是再把它插入到链表中去,以便下一次使用。再次,不用 string 用什么?用数组!用字符数组!就像C中的字符数组一样。就是这么简单~这是前人的文章,还有好多人家是经过测试才得出的结论的。但是 wr960204 (武稀松) 做到没有问题,我觉得他有办法。 呵呵。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2342105
引用次数 (4byte) + 长度(4byte) + 字符数组, 其实一个S: string; s 就是一个指向
字符数组的指针。 其实我的应用服务基本都是使用内存池的,不过就是业务对象是create 和 free, 现在我也修改放到对象池去了。现在正在测试部过效果好很多了! 之前很有可能就是业务对象create 和 free 引起的问题。等我测试完成之后,在总结一下。谢谢各位!
导致比java都慢了20倍?!Java 30.527 1.00x
C#_outref 44.220 1.45x
F# 47.172 1.55x
C# 48.194 1.58x
JsChrome 237.880 7.79x
LuaJIT 829.777 27.18x
Lua 1,227.656 40.22x
IronPython 2,921.573 95.70x
JsFirefox 3,588.778 117.56x
Python 3,920.556 128.43x
Jython 6,211.550 203.48x
Ruby 77,859.653 2,550.52x
Java Java SE 1.6.0_10 -server 55.63 2.69x(3.56x) 70M+
C++ Embarcadero C++ Builder 2010 -P -6 -pr -ff -Vx -Ve -r 55.77 2.70x(3.57x) 3M+
C++ Borland Turbo C++ Explorer -O2 -Hc -Vx -Ve -x- -RT- -ff -X- -pr -a8 -6 -b- -k- -vi -tWC -tWM- -c 60.00 2.90x(3.84x) 3M+
C++ Borland C++ Builder 6.0 -Hc -P -Vx -Ve -x- -RT- -ff -X- -pr -a8 -6 -b- -k- -vi -tWC -tWM- -c 60.14 2.91x(3.85x) 3M+
Delphi Embarcadero Delphi 2010 默认编译参数 173.77 8.42x(11.1x) 5M+
Delphi FreePascal 2.2.4(Lazarus 0.9.28.2b) 默认编译参数 241.25 11.7x(15.4x) 5M+
Delphi FreePascal 2.4(Lazarus 0.9.28.2b) in Ubuntu 10.04 (32-bit) (VirtualBox 3.2.4, 1CPU, 1GRAM) 默认编译参数 329,19 15.5x(20.5x) 2M+
Delphi Borland Delphi 7 自己实现的对象管理 429.52 20.8x(27.5x) 5M+
Delphi Borland Delphi 7 默认编译参数 553.91 26.8x(35.4x) 4M+