首页 新闻 会员 周边 捐助

C#怎么快速初始化一个49W的数组

0
悬赏园豆:100 [待解决问题]

怎么快速初始化一个49W的数组

代码如下:

publc class TCellinfo

{

  public byte chFlag;

  public List<object> ObjList; 

}

 

下面是我现在写的代码,但是这样占用内存太高了,求高手给出高效率的方法。

public TCellinfo[] CellArray;

public TCellinfo CellInfo;

CellArray= new TCellinfo[700*700];//或者更大的数字

 for (int nW = 0; nW < m_nWidth; nW++)
{
               for (int nH = 0; nH < m_nHeight; nH++)
          {
                        CellInfo= new TCellinfo();
                        CellArray[nW * m_nHeight + nH] = CellInfo;
                 }
}

问题补充:

昨天把TCellinfo改成结构体,内存明显下降很多。。(约200M),继续求大神们赐教!

茶语咖啡的主页 茶语咖啡 | 初学一级 | 园豆:97
提问于:2012-09-07 21:56
< >
分享
所有回答(10)
0

我想关键不在这几句代码。。。你看下有没有必要必须初始化这么大的数组。

不过初始化49W长度的数组应该不会慢,看你这也没放什么东西进去,也不会占用多少内存啊。

向往-SONG | 园豆:4853 (老鸟四级) | 2012-09-07 22:34

必须初始化这么大的数组。

现在分配内存之后,然后加载文件,内存狂飙到800M。。实在让人受不了

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-07 22:38

@茶语咖啡: 

里面都放了什么,这么大。。。你这800M的内容时刻都要用到吗?应该不会吧,可以稍微转换下思路。

支持(0) 反对(0) 向往-SONG | 园豆:4853 (老鸟四级) | 2012-09-07 22:47

@向往-SONG: 

几百个文件

时刻都需要用到

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-07 22:52
0

是你加载文件到内存里来,当然内存狂飙,分批加载,没办法。我一般用linq 初始化

var CellArray1 = Enumerable.Repeat<TCellinfo>(new TCellinfo(), 700 * 7000).ToArray();

Qlin | 园豆:2403 (老鸟四级) | 2012-09-07 22:50
1

这跟数组没关系,49w的数组占不了多少内存,关键你这个数组里存的都是文件,文件吃内存。我看你说几百个文件,时刻都用到,怎么可能呢?你任何时刻,都要同时用这几百个文件?这种情况肯定无法做到都加在到内存中的,等需要用到文件的时候再去读文件,才是正确的做法。

水牛刀刀 | 园豆:6350 (大侠五级) | 2012-09-07 23:12

这是一个游戏场景服务器。。时刻都在检查玩家在地图上的动作。。。

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-07 23:20

@茶语咖啡: 那800m对于服务器来说也没什么啊,咋就吃不消了呢

支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-09-07 23:21

@水牛刀刀: 就是想优化这段代码。。。

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-08 00:14

@茶语咖啡: 那你的玩家的动作应该用事件抛出来呀,遍历什么的效率总会有瓶颈啊

支持(0) 反对(0) Dream2zz | 园豆:96 (初学一级) | 2012-09-08 07:53

@梦 境: 这段代码只需要初始化一次,玩家的地图动作是根据玩家所在地图坐标+范围来判断事件的...只是这里一直new TCellinfo();--这里确实有点消耗内存..

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-08 08:29

@茶语咖啡: new TCellinfo() 光这句只耗了几个byte的内存。

支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-09-08 12:07
0

     for (int nH = 0; nH < m_nHeight; nH++)
          {
                        CellInfo= new TCellinfo();

把这遍历 换成 获得行数据数组,然后看看有没有addRange这样的操作,也许速度会快一点~

Dream2zz | 园豆:96 (初学一级) | 2012-09-08 07:51

如果是这样的话,这里还是一样会new TCellinfo();--43W次.

昨天我把TCellinfo改成结构体,内存明显下降很多.

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-08 08:30

@茶语咖啡: 我是指  CellInfo[]  cis = CellHelper.Factory.GetArray();

去掉一层遍历

支持(0) 反对(0) Dream2zz | 园豆:96 (初学一级) | 2012-09-08 09:04

@茶语咖啡: 再就是,试试并行

支持(0) 反对(0) Dream2zz | 园豆:96 (初学一级) | 2012-09-08 09:10

@茶语咖啡: 

数据并行(任务并行库)
http://msdn.microsoft.com/zh-cn/library/dd537608

支持(0) 反对(0) Dream2zz | 园豆:96 (初学一级) | 2012-09-08 09:14
0

试试unsafe代码呢?直接用指针进行操作,文件根本不用全放到内存,不要忘记还有个文件内存映射的WIN32 API可用。

看这个连接:
http://www.soaspx.com/dotnet/csharp/csharp_20120605_9244.html
.Net 4.0中引入了System.IO.MemoryMappedFiles

BinSys | 园豆:290 (菜鸟二级) | 2012-09-08 13:56
0

你可以构建一个锯齿数组,你两个for循环在一起肯定很慢,如下是解决方案:

 1   public class TCellinfo
 2         {
 3             public byte chFlag;
 4 
 5             public List<object> ObjList;
 6 
 7             public override string ToString()
 8             {
 9                 return "a";
10             }
11         }
12 
13   class Program
14     {
15         /// <summary>
16         /// 返回一个length*length的锯齿数组
17         /// </summary>
18         public static TCellinfo[][] CreateArray(int length)
19         {
20             TCellinfo[][] jarray = new TCellinfo[length][];
21             TCellinfo[] array = new TCellinfo[length];
22 
23             for (int i = 0; i < length; i++)
24             {
25                 array[i] = new TCellinfo();
26             }
27 
28             for (int i = 0; i < length; i++)
29             {
30                 jarray[i] = array;
31             }
32             return jarray;
33         }
34 
35         /// <summary>
36         /// 遍历锯齿数组
37         /// </summary>
38         public static void IterateArray(TCellinfo[][] tcs)
39         {
40             for (int i = 0; i < tcs.Length; i++)
41             {
42                 Console.Write((i + 1).ToString() + "    ");
43 
44                 for (int j = 0; j < tcs[i].Length; j++)
45                 {
46                     Console.Write("{0,8}", tcs[i][j].ToString());
47                 }
48                 Console.WriteLine();
49             }
50         }
51 
52         static void Main(string[] args)
53         {
54             Console.WriteLine("{0,4} {1,8} {2,8} {3,8} {4,8} {5,8}", "Num", "1", "2", "3", "4", "5");
55             IterateArray(CreateArray(5));
56         }
57     }
下面是运行结果:
Num 1 2 3 4 5

1 a a a a a
2 a a a a a
3 a a a a a
4 a a a a a
5 a a a a a

静女 | 园豆:27 (初学一级) | 2012-09-08 14:47
0

(1)如果你确实确实需要把这么多信息同时放在内存里,那你的服务器就应该有这个性能的支撑能力。

(2)你应该转换思路,用可接受的时间成本来节省内存。

(3)你确定700*700这么多个元素每个元素里都包含有内容的链表吗?他们中有多少比例链表是空的?如果是这样,你这样大量分配对象是不太合理的。你可以把700*700个杂乱的小链表拼合成一个链表。这样就可以避免大量分配小对象。

(4)如果你对内存和效率有很高很精确的要求,请重新考虑你选择.net是否合适。

hoodlum1980 | 园豆:573 (小虾三级) | 2012-09-09 08:00

服务器性能绝对够了,我的目的是看能不能优化下这个方法,对于服务器来说800M内存并不算什么。

700*700是根据游戏地图宽高计算出来的。。

支持(0) 反对(0) 茶语咖啡 | 园豆:97 (初学一级) | 2012-09-10 09:05

@茶语咖啡: 如果你只是对着这几行代码发呆,内心里根本不愿意或想不到去改变思路,转变观念,那又谈何优化呢。

支持(0) 反对(0) hoodlum1980 | 园豆:573 (小虾三级) | 2012-09-10 15:10
0

既然需要这样的大的操作,那你就应该首先想到的是提高内存。

chenping2008 | 园豆:9836 (大侠五级) | 2012-09-09 10:09
0

改变为结构体后, 整体内存的使用情况下降是必须的,因为结构体不包含组成class的那个8 bytes.

另外,就像楼上说的,我认为你没必要一次性开那么大的数组~这是需求问题,不是技术问题.

Kevin.Jee | 园豆:202 (菜鸟二级) | 2012-09-09 21:10
0

不要分配这么多小对象,CLR对对象处理的开销很大。

你可以分配大块内容,然后自己管理,比如: byte[] chFlag = new byte[700*700],

链表也可以这么处理,但要复杂一些

五星 | 园豆:125 (初学一级) | 2012-09-10 20:42
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册