刘睿
2005年7月19日
2.4 使用CICS分配共享内存的问题 CICS域的启动程序的问题 锁定的问题
3.1 EasyCICS对结果集每行4000字节的限制可否修改?
最近到一个CICS/TXSeries和EasyCICS的用户那里工作了两天,看了一下他们的代码,得到以下结果:
· 没有明显的严重编程问题
· 一些做法不够精巧,有进一步提高性能的可行性
于是我们进行了一些有益的讨论。我写这篇文章,应该对其他的EasyCICS初学者和用户也有一些帮助。
注:本文不包括任何与客户业务相关的信息和代码。
我发现这里使用结果集分段传输大数据块。这样的方法可行,但是效率低,编程也比较麻烦。可以采用EasyCICS提供的函数。实验表明,可以大大提高效率,而且非常容易做。
注意EasyCICS的OLE程序中经常使用的byte数组,在Power Builder中的对应类型是blob。该blob与char数组的转换方式必须选择为ANSI。
示例程序请参见“demo.zip”。
我发现这里使用RsClose比较乱。虽然不会造成什么大的影响,还是提示如下:
在读和写结果集完成后使用RsClose是正确的。当然真正需要的地方是在读超过32K的结果集时,如果没读完,就不想再读了,请最好使用RsClose。其作用是把服务器TSQ中混存的数据清除。不然服务器就会把它保留直到超时(默认20天,最少5天)。其它情况下不用RsClose不会有任何影响。
当然即使没用RsClose而遗留了一些垃圾数据在TSQ里,也有清除的办法。详细请参阅http://www.lrsolution.com/easycics.html。
RsClose要在BeginWrite之前调用。
我发现这里程序中使用malloc等,如果忘记free,就造成内存损失。
可以使用CicsMallocLocal函数(实际是宏定义)来分配CICS内存,当程序结束时,这些内存会自动被释放。当然也可以使用CicsFree函数释放内存。
注意分配的内存将在Task Private Pool中获取,所以要注意适当提高RD: MaxTaskPrivatePool。注意每个cicsas都会分配一块RD: MaxTaskPrivatePool指定大小的内存。
我发现这里每次从数据库读取数据字典,造成效率比较低。推荐把常用的共享数据放在CICS的共享内存。
要分配CICS的共享内存,可以使用CicsMallocShared函数(实际是宏定义),可以使用CicsFree函数释放内存。共享内存的指针可以被所有CICS程序使用。
注意分配的内存将在Task Shared Pool中获取,所以要注意适当提高RD: MaxTSHPool。
一种通用的做法是做启动程序,启动程序加载数据字典,并复制到共享内存中。并把共享内存的指针存放于CWA中。存取CWA的函数分别是SaveToCwa和LoadFromCwa。
如果在运行过程中要修改共享内存,应该使用CicsLockId以及CicsLockIdTest等函数串行化访问请求。具体的做法是:写共享内存时使用CicsLockId,读共享内存时使用CicsLockIdTest,这样就可以保证独占写与共享读。
示例程序请参见“demo.zip”中的“cwa”。
服务程序调用服务程序要使用CallProgram,没有任何问题。注意事项如下:
1. 如果有必要,请使用SetCurrentCA来切换通信区。
2. 任何结果集的操作不能交叉进行,必要时请使用数组变量。
3. 服务程序调用服务程序,客户方的结果集长度不得超过32K,服务器方可以传递超过32K的数据。且不支持上载和下载数据块。必要时可以利用TSQ等传递数据。
可以修改,但是要保证ROW_SIZE+WARN_SIZE<=32000
当然最好不要修改。
无论是编译还是执行,一般不会有什么问题。我见过40-50M的CICS程序跑得很好。如果有必要,修改AIX的/etc/security/limits文件的操作系统限制。
但是CICS程序太大了,调试起来会比较麻烦。
还有一点,就是系统每次加载如此巨大的程序,会造成效率比较低。解决的办法,除了提高硬件的吞吐率之外,就是把程序设置成驻留内存的。所需的工作是设置PD: Resident为true,并且提高RD:ProgramCacheSize。
把程序设置成驻留内存的,对程序的要求进一步提高。主要体现在以下方面:
· 全局和静态变量的声明和赋初值最好不要在一起。也就是说,在函数中赋初值,而不是在声明时。
· 避免同时加载的程序存在符号冲突。
Power Builder v10以后,就不必使用SetValue(“_LANG”, “1”)了。这样可以大大提高效率。
另外EasyCICS的OLE程序中经常使用的byte数组,在Power Builder中的对应类型是blob。注意该blob与char数组的转换方式必须选择为ANSI。
原则上要先设置键值,再设置结果集。如果设置结果集,可能客户机一开始读不到键值。但如果该键值很小(比如100字节以下),可以使用SetValueA函数。
压力大的Region需要比较大的Region Pool和Task Shared Pool。典型的值是Region Pool为50M,Task Shared Pool为15M。
如果不是用CICS内存,可以不提高Task Private Pool,默认为1M。注意总内存使用量是Task Private Pool乘以cicsas总数。
如果使用了CICS本地内存,相应地增加Task Private Pool;如果使用了CICS共享内存,相应地增加Task Shared Pool
通过CSTD交易的第2选项,可以观察这些Pool的使用情况。
CICS Universal Client或CICS Transaction Gateway的内容是必须的,但是一般只须保留.dll文件,CTG.INI文件,cclclnt.exe文件。
EasyCICS的文件只需要EcOLE.dll。选择自注册即可。手工注册的方法如下:
Regsvr32 EcOLE.dll
注意如果CICS Universal Client或CICS Transaction Gateway的共享库不在PATH环境变量或者当前目录,注册就会失败。
EasyCICS的OLE组件有一个RestartWindow方法。修改了CTG.INI文件后,如果用户不方便或不会使用cicscli命令,可以使用RestartWindow方法。
当然可以。注意使用类似以下的命令行选项:
Windows平台:
cicstcl -lCPP <ccs文件>
AIC平台:
cicstcl -lIBMCPP <ccs文件>
注意把程序加入PD时,在PathName属性不要写后缀名。