随笔-341  评论-2670  文章-0  trackbacks-0
    Lazy Compiler使用Syngram动态创建语法分析器的代码实在是太慢了,debug竟然需要8秒钟来处理91条比较长的文法。于是我打开了Visual Studio 2008的Performance Wizard查看运行时消耗的资源,结果发现竟然都消耗在自己那个array类的operator[]里面了。那一段代码是用来检查文法的左递归引用关系是否出现环的。结果就把用到的四个array全部换成bool*了,当时只是为了创建二维数组方便使用了array类。

    过后,debug的时间立刻降为2秒钟不到,于是我又打开Performance Wizard看了一次,这次消耗的瓶颈终于转移到一个合理的地方了。

    结果:array竟然比指针慢了无穷多倍,得找个时候重新写一次。不过这段代码好象是去年写的,也没经过什么性能测试,也难怪发现不了问题。在此帖上代码,等Lazy Script写完了重新审查一下自己的那套模板库(NTL,Non-standard Template Library,娃哈哈)。
  1     enum VLE_ArrayCommander
  2     {
  3         vacNewArray
  4     };
  5 
  6     template<VLE_ArrayCommander _Commander , VInt _Dims>
  7     class VL_ArrayDimension : public VL_Base
  8     {
  9     public:
 10         VInt    Dims[_Dims+1];
 11 
 12         VL_ArrayDimension()
 13         {
 14             for(VInt i=0;i<_Dims;i++)
 15             {
 16                 Dims[i]=0;
 17             }
 18         }
 19 
 20         VL_ArrayDimension(VInt Dim , VInt* PrevDims)
 21         {
 22             Dims[0]=Dim;
 23             memcpy(Dims+1,PrevDims,sizeof(VInt)*(_Dims-1));
 24         }
 25 
 26         VL_ArrayDimension<_Commander , _Dims+1> operator [](VInt Dim)
 27         {
 28             return VL_ArrayDimension<_Commander , _Dims+1>(Dim,Dims);
 29         }
 30 
 31         VInt GetSize()
 32         {
 33             VInt Size=1;
 34             for(VInt i=0;i<_Dims;i++)
 35             {
 36                 Size*=Dims[i];
 37             }
 38             return Size;
 39         }
 40     };
 41 
 42     extern VL_ArrayDimension<vacNewArray , 0> NewArray;
 43 
 44     template<typename _Type>
 45     class VL_ArrayInfo : public VL_Base
 46     {
 47     public:
 48         _Type*    Elements;
 49         VInt*    Dims;
 50         VInt    RefCount;
 51         VInt    Size;
 52 
 53         VL_ArrayInfo(VInt aDims)
 54         {
 55             Dims=new VInt[aDims];
 56         }
 57 
 58         ~VL_ArrayInfo()
 59         {
 60             delete[] Dims;
 61         }
 62     };
 63 
 64     template<typename _Type , VInt _Dims>
 65     class VL_Array : public VL_Base
 66     {
 67     protected:
 68 
 69     public:
 70 
 71         template<VInt _RefDims>
 72         class VL_ArrayReference : public VL_Base
 73         {
 74             friend class VL_Array;
 75         protected:
 76             VL_ArrayInfo<_Type>*    FInfo;
 77             _Type*                    FElements;
 78             VInt                    FSubSize;
 79         public:
 80 
 81             VL_ArrayReference(_Type* Elements , VL_ArrayInfo<_Type>* Info , VInt Dim)
 82             {
 83                 FInfo=Info;
 84                 FSubSize=FInfo->Size/FInfo->Dims[_RefDims];
 85                 FElements=Elements+Dim*FSubSize;
 86             }
 87 
 88             VL_ArrayReference(VL_ArrayInfo<_Type>* Info , _Type* Elements , VInt SubSize)
 89             {
 90                 FInfo=Info;
 91                 FElements=Elements;
 92                 FSubSize=SubSize;
 93             }
 94 
 95             VL_ArrayReference<_RefDims-1> operator [](VInt Dim)
 96             {
 97                 VInt SubSize=FSubSize/FInfo->Dims[_RefDims-1];
 98                 return VL_ArrayReference<_RefDims-1>(FInfo,FElements+Dim*SubSize,SubSize);
 99             }
100 
101             operator VL_Array<_Type , _RefDims>()
102             {
103                 return VL_Array<_Type , _Dims-1>(FInfo,FElements);
104             }
105 
106             VL_Array<_Type , _RefDims> Reference()
107             {
108                 return VL_Array<_Type , _Dims-1>(FInfo,FElements);
109             }
110 
111             VL_Array<_Type , _RefDims> Clone()
112             {
113                 return VL_Array<_Type , _Dims-1>(FInfo,FElements).Clone();
114             }
115 
116             void Copy(VL_Array<_Type , _RefDims>& Array)
117             {
118                 VL_ArrayInfo<_Type>* ArrayInfo=Array.GetInfo();
119                 VInt Count=FInfo->Dims[_RefDims-1];
120                 if(Count>ArrayInfo->Dims[_RefDims-1])
121                 {
122                     Count=ArrayInfo->Dims[_RefDims-1];
123                 }
124                 for(VInt i=0;i<Count;i++)
125                 {
126                     operator [](i).Copy(Array[i].Reference());
127                 }
128             }
129 
130             VInt GetCount()
131             {
132                 return FInfo->Dims[_RefDims-1];
133             }
134         };
135 
136         template<>
137         class VL_ArrayReference<1> : public VL_Base
138         {
139         protected:
140             VL_ArrayInfo<_Type>*    FInfo;
141             _Type*                    FElements;
142         public:
143 
144             VL_ArrayReference(_Type* Elements , VL_ArrayInfo<_Type>* Info , VInt Dim)
145             {
146                 FInfo=Info;
147                 FElements=Elements+Dim*FInfo->Size/FInfo->Dims[1];
148             }
149 
150             VL_ArrayReference(VL_ArrayInfo<_Type>* Info , _Type* Elements , VInt SubSize)
151             {
152                 FInfo=Info;
153                 FElements=Elements;
154             }
155 
156             _Type& operator [](VInt Dim)
157             {
158                 return FElements[Dim];
159             }
160 
161             operator VL_Array<_Type , 1>()
162             {
163                 return VL_Array<_Type , 1>(FInfo,FElements);
164             }
165 
166             VL_Array<_Type , 1> Reference()
167             {
168                 return VL_Array<_Type , 1>(FInfo,FElements);
169             }
170 
171             VL_Array<_Type , 1> Clone()
172             {
173                 return VL_Array<_Type , 1>(FInfo,FElements).Clone();
174             }
175 
176             void Copy(VL_Array<_Type , 1>& Array)
177             {
178                 VL_ArrayInfo<_Type>* ArrayInfo=Array.GetInfo();
179                 _Type* ArrayElements=Array.GetElements();
180                 VInt Count=FInfo->Dims[0];
181                 if(Count>ArrayInfo->Dims[0])
182                 {
183                     Count=ArrayInfo->Dims[0];
184                 }
185                 for(VInt i=0;i<Count;i++)
186                 {
187                     FElements[i]=ArrayElements[i];
188                 }
189             }
190 
191             VInt GetCount()
192             {
193                 return FInfo->Dims[0];
194             }
195         };
196 
197     protected:
198         VL_ArrayInfo<_Type>*    FInfo;
199         _Type*                    FElements;
200 
201         void Create(VInt Size)
202         {
203             FInfo=new VL_ArrayInfo<_Type>(_Dims);
204             FInfo->Elements=new _Type[Size];
205             FInfo->RefCount=1;
206             FInfo->Size=Size;
207             if(Size==0)
208             {
209                 for(VInt i=0;i<_Dims;i++)
210                 {
211                     FInfo->Dims[i]=0;
212                 }
213             }
214             FElements=FInfo->Elements;
215         }
216 
217         void Inc()
218         {
219             FInfo->RefCount++;
220         }
221 
222         void Dec()
223         {
224             if(!--FInfo->RefCount)
225             {
226                 delete[] FInfo->Elements;
227                 delete FInfo;
228                 FInfo=0;
229                 FElements=0;
230             }
231         }
232 
233         VL_Array(VInt Size)
234         {
235             Create(Size);
236         }
237 
238     public:
239 
240         VL_Array()
241         {
242             Create(0);
243         }
244 
245         VL_Array(VL_ArrayInfo<_Type>* Info , _Type* Elements)
246         {
247             FInfo=Info;
248             FElements=Elements;
249             Inc();
250         }
251 
252         VL_Array(VL_ArrayDimension<vacNewArray , _Dims>& Dims)
253         {
254             Create(Dims.GetSize());
255             memcpy(FInfo->Dims,Dims.Dims,sizeof(VInt)*_Dims);
256         }
257 
258         ~VL_Array()
259         {
260             Dec();
261         }
262 
263         VL_Array(VL_Array<_Type , _Dims>& Array)
264         {
265             FInfo=Array.FInfo;
266             FElements=Array.FElements;
267             Inc();
268         }
269 
270         VL_Array<_Type , _Dims>& operator =(VL_Array<_Type , _Dims>& Array)
271         {
272             Dec();
273             FInfo=Array.FInfo;
274             FElements=Array.FElements;
275             Inc();
276             return *this;
277         }
278 
279         VL_ArrayReference<_Dims-1> operator [](VInt Dim)
280         {
281             return VL_ArrayReference<_Dims-1>(FElements,FInfo,Dim);
282         }
283 
284         VL_Array<_Type , _Dims> Reference()
285         {
286             return *this;
287         }
288 
289         VL_Array<_Type , _Dims> Clone()
290         {
291             VL_Array<_Type , _Dims> Array(FInfo->Size);
292             for(VInt i=0;i<FInfo->Size;i++)
293             {
294                 Array.FElements[i]=FElements[i];
295             }
296             memcpy(Array.FInfo->Dims,FInfo->Dims,sizeof(VInt)*_Dims);
297             return Array;
298         };
299 
300         void Copy(VL_Array<_Type , _Dims>& Array)
301         {
302             operator =(Array.Clone());
303         }
304 
305         VL_ArrayInfo<_Type>* GetInfo()
306         {
307             return FInfo;
308         }
309 
310         _Type* GetElements()
311         {
312             return FElements;
313         }
314 
315         VInt GetCount()
316         {
317             return FInfo->Dims[_Dims-1];
318         }
319     };
320 
321     template<typename _Type>
322     class VL_Array<_Type , 1> : public VL_Base
323     {
324     protected:
325         VL_ArrayInfo<_Type>*    FInfo;
326         _Type*                    FElements;
327 
328         void Create(VInt Size)
329         {
330             FInfo=new VL_ArrayInfo<_Type>(1);
331             FInfo->Elements=new _Type[Size];
332             FInfo->RefCount=1;
333             FInfo->Size=Size;
334             FInfo->Dims[0]=0;
335             FElements=FInfo->Elements;
336         }
337 
338         void Inc()
339         {
340             FInfo->RefCount++;
341         }
342 
343         void Dec()
344         {
345             if(!--FInfo->RefCount)
346             {
347                 delete[] FInfo->Elements;
348                 delete FInfo;
349                 FInfo=0;
350                 FElements=0;
351             }
352         }
353 
354         VL_Array(VInt Size)
355         {
356             Create(Size);
357         }
358 
359     public:
360 
361         VL_Array()
362         {
363             Create(0);
364         }
365 
366         VL_Array(VL_ArrayInfo<_Type>* Info , _Type* Elements)
367         {
368             FInfo=Info;
369             FElements=Elements;
370             Inc();
371         }
372 
373         VL_Array(VL_ArrayDimension<vacNewArray , 1>& Dims)
374         {
375             Create(Dims.GetSize());
376             FInfo->Dims[0]=Dims.Dims[0];
377         }
378 
379         ~VL_Array()
380         {
381             Dec();
382         }
383 
384         VL_Array(VL_Array<_Type , 1>& Array)
385         {
386             FInfo=Array.FInfo;
387             FElements=Array.FElements;
388             Inc();
389         }
390 
391         VL_Array<_Type , 1>& operator =(VL_Array<_Type , 1>& Array)
392         {
393             Dec();
394             FInfo=Array.FInfo;
395             FElements=Array.FElements;
396             Inc();
397             return *this;
398         }
399 
400         _Type& operator [](VInt Dim)
401         {
402             return FInfo->Elements[Dim];
403         }
404 
405         VL_Array<_Type , 1> Reference()
406         {
407             return *this;
408         }
409 
410         VL_Array<_Type , 1> Clone()
411         {
412             VL_Array<_Type , 1> Array(FInfo->Size);
413             for(VInt i=0;i<FInfo->Size;i++)
414             {
415                 Array.FInfo->Elements[i]=FInfo->Elements[i];
416             }
417             return Array;
418         };
419 
420         void Copy(VL_Array<_Type , 1>& Array)
421         {
422             operator =(Array.Clone());
423         }
424 
425         VL_ArrayInfo<_Type>* GetInfo()
426         {
427             return FInfo;
428         }
429 
430         _Type* GetElements()
431         {
432             return FElements;
433         }
434 
435         VInt GetCount()
436         {
437             return FInfo->Dims[0];
438         }
439     };
posted on 2008-04-27 19:53 陈梓瀚(vczh) 阅读(2602) 评论(6)  编辑 收藏 引用 所属分类: C++

评论:
# re: 今天发现自己的array类太慢 2008-04-27 20:06 | 空明流转
Release的照理没那么慢。  回复  更多评论
  
# re: 今天发现自己的array类太慢 2008-04-27 23:35 | 陈梓瀚(vczh)
release只少了1/3,debug对array::operator[]加了太多东西了……  回复  更多评论
  
# re: 今天发现自己的array类太慢 2008-06-02 00:20 | suxiaojack
还是C的void*实现的任意类型的模板比较爽。速度最快。不同类型,不过是元素大小不同而已。  回复  更多评论
  
# re: 今天发现自己的array类太慢 2008-06-02 10:00 | 陈梓瀚(vczh)
void*的话为了把你需要的大于sizeof(void*)的东西放进去,你将不得不malloc/free很多次,除非你有对象池,否则将在这里吃掉大量性能。  回复  更多评论
  
# re: 今天发现自己的array类太慢 2008-07-24 09:24 | jetricy
也难怪,虽然用了内联,但是这个operator[]的指令数数10倍于寻址运算了.
另外记得inline优化要在release中才有,N次寻址加上2次压栈退栈,检查栈操作,也就难怪了.  回复  更多评论
  
# re: 今天发现自己的array类太慢 2009-08-03 16:47 | zdhsoft
你的数组copy存在bug,当自己copy自己的时候,会出现!  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理