网页功能: 加入收藏 设为首页 网站搜索  
C语言基本功教程系列(5) - 文件, Socket 和 其它
发表日期:2007-03-28作者:[转贴] 出处:  

 这个系列的最后一章了,基本上这篇里边拿不准的,或者记得不太清楚的,以及很确定的结论,都在网上或者书里找到了依据。如果大家不同意文章里的论点,拿砖头拍我或者拍原作者都可以。

今天的主题是文件访问,Socket,和其他一些值得注意的内容。文件和Socket比较类似,都是在说IO访问,不过在操作系统级别上的实现有很大不同。 IO访问无论从什么角度讲,都是计算机系统里最慢的操作。特别是在游戏制作中,动不动就几百兆的动态或者静态数据,贴图纹理,和各种音响音乐等。要一次性把这些所有的数据读到内存中是不大可能的,所以在游戏进行过程中要不短的从硬盘或者光驱里读文件。 如何能够最小化这个瓶颈, 是值得注意的问题。先从文件说起吧。

===================文件==================
C语言里,正常的文件操作一般是3步。
fp = fopen(XXXX,XXX);
读写操作....
fclose(fp);

首先要注意的是,fopen里边要用binary mode打开文件,不要用ASCII mode. 很多人在处理文本类型的文件时候,喜欢用 ASCII mode,然后用fgets一行一行的读。实际上ASCII mode无论如何操作,都是非常慢的,而且fgets函数更加的慢 [1]。所以即使是文本文件,也要用binary mode打开,一次读入一大块近来,慢慢处理。

其次需要注意的是,每一次读取文件的时候,硬盘都会对磁头进行重新定位和寻址。 这点会根据操作系统的不同而不同,总的来说windows XP要比  windows2000好点,但是也只是在系统文件方面 [2]。 因此每次读取的内容越多,平均效率就越高。同时操作系统提供磁盘缓存,当你写如磁盘的时候,只要不用fflush和fclose,数据在短时间内还是在内存中的,如果这时候再读出来写如的内容,也非常快。读写文件的时候不要用C++的流。写文件一次最好写不小于4k的数据, 而且最好对文件结构有效的安排,进行连续的访问(不要频繁使用fseek)[3]. 这些都有助于提高文件的访问速度。

最后,如上文中提到的,每次使用fclose和 fflush的时候,都会强迫文件从缓存中写如到磁盘里。这个过程极其缓慢而且耗费时间,所以不在必要的时候,不要使用fclose和fflush. 如果一个文件读写完毕,而你又不确定是否短时间内会用到它,那就不要用fclose.你可以专门写一个类,管理这写文件的指针。对于经常会进行操作的文件,比如大地图的texture文件等,fopen一次就ok了,直到游戏结束再fclose


===================SOCKET==================
SOCKET虽然也是IO访问,要比文件快多了。但是在recv的时候,还是一次读的越多越好。这样效率更高。下面说一些SOCKET编程的技巧。

1.  使用异步socket (asynchronous IO). 在网络程序设计中,又2种处理方式,第一种是对每一个连接请求,都使用一个线程或者进程,第2种是使用一个线程同时使用异步IO. 第一种方式虽然程序设计上简单,但是创立进程的时候一般会有一些时间用在建立context上,进程间的转换和 mutex等也需要浪费很多CPU资源,总体来说不如异步 IO 有效率 [4]。 

2. 如果必须要使用多线程,可以考虑事先就创建好该线程,然后在需要的时候,把socket发过去就行了[4]。

3. 在处理 UDP协议的时候,需要注意的是,UDP和TCP不一样。UDP没有control flow,如果接收端的buffer满掉了,再来的UDP包都会被drop掉。所以在处理UDP协议的时候,一般需要专门一个线程读UDP包,防止过多的数据包丢失。

4.  最后,网络数据包多大合适? 这个很难说。对于UDP来说,小包是不划算的. 我们通常用的Ethernet(也就是LAN),在第2层 Data link layer,最大的frame size 是1500 bytes,刨除最20 Bytes(最少)的IP头,8 bytes的 UDP头,所有最大的UDP包可以包含 1472个bytes。要是考虑IP包有可能会有附加头信息,一般1400就比较合适。但是如果有些老版本 router不地道,对你的UDP包分片的话,就比较惨了。能保证不分片的UDP包大小是513个byte左右 [5],不过毕竟现在这种老的 Router很少了,1400字节大小的UDP包还是比较安全的。对于TCP来说,因为是stream protocol,不用考虑包的大小。但是TCP 有个缺点,就是如果你一次发送很多很多数据,那么TCP的速度会一会快,一会慢(见[4]中的关于video streaming的介绍)。所以,需要程序调节,匀速发送数据。

====================其他===================
其他一些程序设计上的东西,很多可以参见 [6]

1. 能用UINT的地方就用UINT,因为很多是UINT最快,而且UINT的除法要比int快。
2. 尽量避免类型转换,如果最后要转成float,开始的时候就用float比较好。
3. 不要用double
4. 能用乘法就不要用除法。 比如   3/2 可以换成  3 * 0.5
5. struct的大小尽量是2的倍数,如果不是就调整下,加pad。因为可以在level1 cache里放整数个。
6. 全局变量少用,如果要用,加上static
7. 局部变量也是越少越少。这样register的效率更高
8. 能用switch的地方,就不要用if,因为switch是直接生成跳转表,速度快很多
9. 互相关联的代码之间不要空行,功能不同的代码之间最好空上1行区分开
10. 用const static 代替 #define 定义常量
11. 统一你的代码风格,始终使用同样的命名规则

===================最后==================
生成高效率代码永远是从使用更好更合适的算法开始,但是编译的时候不要忘记打开你的优化开关。希望这个系列给大家带来了一些有用的东西。下个系列见 88


1. http://www.abarnett.demon.co.uk/tutorial.html
2.http://www.microsoft.com/technet/prodtechnol/winxppro/evaluate/xpperf.mspx
3. http://stevezero.com/eecs/cs162_fa03/IOOptimization.pdf
4. David L. Stevens, "TCP/IP Client-Server Programming And Application" Volume 3, Chapter16
5. Andrew S. Tanenbaum "Computer Networks" Chapter 4
6. http://www.agner.org/optimize/optimizing_cpp.pdf

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 C语言基本功教程系列(5) - 文件, Socket 和 其它
本类热点文章
  脚本系统的实现
  C++基本功和 Design Pattern系列(2) Ty..
  C++基本功和 Design Pattern系列(1) - ..
  斜45度游戏开发(提高篇)
  睱酵笴栏祘Α砞璸?? - [秈顶絞]
  斜45度游戏开发(二)
  第一次写技术文献。Collision AI
  斜视角游戏中遮挡的判断
  C语言基本功教程系列(5) - 文件, Socke..
  用rand()和srand()产生伪随机数的方法总..
  C++基本功和 Design Pattern系列(3) co..
  C语言基本功教程系列(1)
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00428