第一篇:(敏捷开发).NET性能优化方面的总结.docx
(敏捷开发).NET性能优化方面的总结
一、SqlDataRead和Dataset的选择
Sqldataread优点:读取数据非常快。如果对返回的数据不需做大量处理的情况下,建议使用SqlDataReader,其性能要比datset好很多。缺点:直到数据读完才可close掉于数据库的连接。(SqlDataReader读数据是快速向前的。SqlDataReader类提供了一种读取从 SQL Server 数据库检索的只进数据流的方法。它使用 SQL Server 的本机网络数据传输格式从数据库连接直接读取数据。DataReader需及时显式的close。可及时的释放对数据的连接。)
Dataset是把数据读出,缓存在内存中。缺点:对内存的占用较高。如果对返回的数据需做大量的处理用Dataset比较好些可以减少对数据库的连接操作。优点:只需连接一次就可close于数据库的连接。一般情况下,读取大量数据,对返回数据不做大量处理用SqlDataReader.对返回数据大量处理用datset比较合适.对SqlDataReader和Dataset的选择取决于程序功能的实现。
二、ExecuteNonQuery和ExecuteScalar 对数据的更新不需要返回结果集,建议使用ExecuteNonQuery。由于不返回结果集可省掉网络数据传输。它仅仅返回受影响的行数。如果只需更新数据用ExecuteNonQuery性能的开销比较小。
ExecuteScalar它只返回结果集中第一行的第一列。使用ExecuteScalar方法从数据库中检索单个值(例如id号)。与使用ExecuteReader方法,返回的数据执行生成单个值所需的操作相比,此操作需要的代码较少。
只需更新数据用ExecuteNonQuery.单个值的查询使用ExecuteScalar。数据绑定的选择
三、数据的绑定DataBinder 一般的绑定方法<%# DataBinder.Eval(Container.DataItem, “字段名”)%>用DataBinder.eval绑定不必关心数据来源(Dataread或dataset)。不必关心数据的类型eval会把这个数据对象转换为一个字符串。在底层绑定做了很多工作,使用了反射性能。正因为使用方便了,但却影响了数据性能。来看下<%# DataBinder.Eval(Container.DataItem, “字段名”)%>。当于dataset绑定时,DataItem其实式一个DataRowView(如果绑定的是一个数据读取器(dataread)它就是一个IdataRecord。)因此直接转换成DataRowView的话,将会给性能带来很大提升。.<%# ctype(Container.DataItem,DataRowView).Row(“字段名”)%> 对数据的绑定建议使用<%# ctype(Container.DataItem,DataRowView).Row(“字段名”)%>。数据量大的时候可提高几百倍的速度。使用时注意2方面:1.需在页面添加<%@ Import namespace=“System.Data”%>.2.注意字段名的大小写(要特别注意)。如果和查询的不一致,在某些情况下会导致比<%# DataBinder.Eval(Container.DataItem, “字段名”)%>还要慢。如果想进一步提高速度,可采用<%# ctype(Container.DataItem,DataRowView).Row(0)%>的方法。不过其可读性不高。以上的是vb.net的写法。在c#中:<@%((DataRowView)Container.DataItem)[“字段名”] %>
一、应用Ado.net的一些思考原则 1.根据数据使用的方式来设计数据访问层 2.缓存数据,避免不必要的操作 3.使用服务帐户进行连接 4.必要时申请,尽早释放 5.关闭可关闭的资源 6.减少往返
7.仅返回需要的数据 8.选择适当的事务类型 9.使用存储过程
二、Connection
数据库连接是一种共享资源,并且打开和关闭的开销较大。Ado.net默认启用了连接池机制,关闭连接不会真的关闭物理连接,而只是把连接放回到连接池中。因为池中共享的连接资源始终是有限的,如果在使用连接后不尽快关闭连接,那么就有可能导致申请连接的线程被阻塞住,影响整个系统的性能表现。
1、在方法中打开和关闭连接 这个原则有几层含义:
1)主要目的是为了做到必要时申请和尽早释放
2)不要在类的构造函数中打开连接、在析构函数中释放连接。因为这将依赖于垃圾回收,而垃圾回收只受内存影响,回收时机不定
3)不要在方法之间传递连接,这往往导致连接保持打开的时间过长 这里强调一下在方法之间传递连接的危害:曾经在压力测试中遇到过一个测试案例,当增大用户数的时候,这个案例要比别 的案例早很久就用掉连接池中的所有连接。经分析,就是因为A方法把一个打开的连接传递到了B方法,而B方法又调用了一个
自行打开和关闭连接的C方法。在A方法的整个运行期间,它至少需要占用两条连接才能够成功工作,并且其中的一条连接占用时间还特别长,所以造成连接池资源紧张,影响了整个系统的可伸缩性!
2、显式关闭连接
Connection对象本身在垃圾回收时可以被关闭,而依赖垃圾回收是很不好的策略。推荐使用using语句显式关闭连接,如下例:
using(SqlConnection conn = newSqlConnection(connString)){ conn.Open();} // Dispose is automatically called on the conn variable here
3、确保连接池启用
Ado.net是为每个不同的连接串建立连接池,因此应该确保连接串不会出现与具体用户相关的信息。另外,要注意连接串是 大小写敏感的。
4、不要缓存连接
例如,把连接缓存到Session或Application中。在启用连接池的情况下,这种做法没有任何意义。
三、Command
1、使用ExecuteScalar和ExecuteNonQuery 如果想返回像Count(*)、Sum(Price)或Avg(Quantity)那样的单值,可以使用ExecuteScalar方法。ExecuteScalar返回第一行第一列的值,将结果集作为标量值返回。因为单独一步就能完成,所以ExecuteScalar不仅简化了代码,还提高了性能。
使用不返回行的SQL语句时,例如修改数据(INSERT、UPDATE或DELETE)或仅返回输出参数或返回值,请使用ExecuteNonQuery。这避免了用于创建空DataReader的任何不必要处理。
2、使用Prepare 当需要重复执行同一SQL语句多次,可考虑使用Prepare方法提升效率。需要注意的是,如果只是执行一次或两次,则完全没有必要。例如: cmd.CommandText = “insert into Table1(Col1, Col2)values(@val1, @val2)”;cmd.Parameters.Add(“@val1”, SqlDbType.Int, 4, “Col1”);cms.Parameters.Add(“@val2”, SqlDbType.NChar, 50, “Col2”);cmd.Parameters[0].Value = 1;cmd.Parameters[1].Value = “XXX”;cmd.Prepare();cmd.ExecuteNonQuery();cmd.Parameters[0].Value = 2;cmd.Parameters[1].Value = “YYY”;cmd.ExecuteNonQuery();cmd.Parameters[0].Value = 3;cmd.Parameters[1].Value = “ZZZ”;cmd.ExecuteNonQuery();
3、使用绑定变量
SQL语句需要先被编译成执行计划,然后再执行。如果使用绑定变量的方式,那么这个执行计划就可以被后续执行的SQL语句所复用。而如果直接把参数合并到了SQL语句中,由于参数值千变万化,执行计划就难以被复用了。例如上面Prepare一节给出的示例,如果把参数值直接写到insert语句中,那么上面的四次调用将需要编译四次执行计划。
为避免这种情况造成性能损失,要求一律使用绑定变量方式。
四、DataReader DataReader最适合于访问只读的单向数据集。与DataSet不同,数据集并不全部在内存中,而是随不断发出的read请求,一旦发现数据缓冲区中的数据均被读取,则从数据源传输一个数据缓冲区大小的数据块过来。另外,DataReader保持连接,DataSet则与连接断开。
1、显式关闭DataReader 与连接类似,也需要显式关闭DataReader。另外,如果与DataReader关联的Connection仅为DataReader服务的话,可考虑使用Command对象的ExecuteReader(CommandBehavior.CloseConnection)方式。这可以保证当DataReader关闭时,同时自动关闭Connection。
2、用索引号访问代替名称索引号访问属性
从Row中访问某列属性,使用索引号的方式比使用名称方式有细微提高。如果会被频繁调用,例如在循环中,那么可考虑此类优化。示例如下:
cmd.CommandText = “select Col1, Col2 from Table1”;SqlDataReaderdr = cmd.ExecuteReader();int col1 = dr.GetOrdinal(“Col1”);int col2 = dr.GetOrdinal(“Col2”);while(dr.Read()){ Console.WriteLine(dr[col1] + “_” + dr[col2]);}
3、使用类型化方法访问属性
从Row中访问某列属性,用GetString、GetInt32这种显式指明类型的方法,其效率较通用的GetValue方法有细微提高,因为不需要做类型转换。
4、使用多数据集
部分场景可以考虑一次返回多数据集来降低网络交互次数,提升效率。示例如下:
cmd.CommandText = “StoredProcedureName”;// The stored procedure returns multiple result sets.SqlDataReaderdr = cmd.ExecuteReader();while(dr.read())// read first result setdr.NextResult();while(dr.read())
五、DataSet
1、利用索引加快查找行的效率
如果需要反复查找行,建议增加索引。有两种方式: 1)设置DataTable的PrimaryKey 适用于按PrimaryKey查找行的情况。注意此时应调用DataTable.Rows.Find方法,一般惯用的Select方法不能利用索引。2)使用DataView 适用于按Non-PrimaryKey查找行的情况。可为DataTable创建一个DataView,并通过SortOrder参数指示建立索引。此后使用Find或FindRows查找行。
一、减少往返行程(Reduce Round Trips)
使用下面的方法可以减少Web服务器和Browser之间的往返行程:
1、为Browser启用缓存
如果呈现的内容是静态的或变化周期较长,应启用Browser缓存,避免发出冗余的http请求。
2、缓冲页面输出
如果可能,则尽量缓冲页面输出,处理结束后再一次传送到客户端,这可以避免频繁传递小块内容所造成的多次网络交互。由于这种方式在页面处理结束之前客户端无法看到页面内容,因此如果一个页面的尺寸较大的话,可考虑使用Response.Flush方法。该方法强制输出迄今为止在缓冲区中的内容,你应当采用合理的算法控制调用Response.Flush方法的次数。
3、使用Server.Transfer重定向请求
使用Server.Transfer方法重定向请求优于Response.Redirect方法。原因是Response.Redirect会向Broswer回送一个响应头,在响应头中指出重定向的URL,之后Brower使用新的URL重新发出请求。而Server.Transfer方法直接是一个简单的服务端调用,完全没有这些开销!需要注意Server.Transfer有局限性:第一,它会跳过安全检查;第二,只适用于在同一Web应用内的页面间跳转。
二、避免阻塞和长时间的作业
如果需要运行阻塞或长时间运行的操作,可以考虑使用异步调用的机制,以便Web服务器能够继续处理其它的请求。
1、使用异步方式调用Web服务和远程对象
只要有可能就要避免在请求的处理过程中对Web服务和远程对象的同步调用,因为它占用的是的ASP.NET 线程池中的工作线程,这将直接影响Web服务器响应其它请求的能力。
2、考虑给不需要返回值的Web方法或远程对象的方法添加OneWay属性
这种模式能让Web Server调用之后就立即返回。可根据实际情况决定是否使用这种方法。
3、使用工作队列
将作业提交到服务器上的工作队列中。客户端通过发送请求来轮询作业的执行结果。
三、使用缓存
缓存能在很大程度上决定ASP.NET应用的最终性能。Asp.net支持页面输出缓存和页面部分缓存,并提供Cache API,供应用程序缓存自己的数据。是否使用缓存可考虑下面的要点:
1、识别创建与访问代价较大的数据
2、评估需要缓存数据的易变性
3、评估数据的使用频次
4、将要缓存数据中易变数据和不变数据分离,只缓存不变数据
5、选择合适的缓存机制(除Asp.net Cache外,Application state和Session state也可以作为缓存使用)
四、多线程
1、避免在请求处理过程中创建线程
在执行请求的过程中创建线程是一种代价较大的操作,会严重影响Web Server的性能。如果后续的操作必须用线程完成,建议通过thread pool来创建/管理线程。
2、不要依赖线程数据槽或线程静态变量
由于执行请求的线程是ASP.NET thread pool中的工作线程,同一个Client的两次请求不一定由相同的线程来处理。
3、避免阻塞处理请求的线程
4、避免异步调用
这和1的情况类似。异步调用会导致创建新的线程,增加服务器的负担。所以,如果没有并发的作业要执行,就不要执行异步调用。
五、系统资源
1、考虑实现资源池以提升性能
2、明确地调用Dispose或Close释放系统资源
3、不要缓存或长时间占用资源池中的资源
4、尽可能晚的申请,尽可能早的释放
六、页面处理
1、尽量减小Page的尺寸
包括缩短控件的名称、CSS的class的名称、去掉无谓空行和空格、禁用不需要的ViewState
2、启用页面输出的缓冲区(Buffer)
如果Buffer的机制被关闭,可以用下面的方法打开。使用程序打开页面输出缓存: Response.BufferOutput = true;使用@Page开关打开页面输出缓冲机制: <%@ Page Buffer = “true” %> 使用Web.config或Machine.config配置文件的
节点:
3、利用Page.IsPostBack优化页面输出
4、通过分离页面的不同的内容,来提高缓存效率和减少呈现的时间
5、优化复杂和代价较大的循环
6、合理利用客户端的计算资源,将一些操作转移到客户端进行
七、ViewState ViewState是Asp.net为服务端控件在页面回传之间跟踪状态信息而设计的一种机制。1.关闭ViewState 如果不需要跟踪页面状态,例如页面不会回传(PostBack)、不需要处理服务端控件事件或者每次页面刷新时都会重新计算控件内容,那么就不需要用ViewState来记录页面状态了。可以对特定的WebControl设置EnableViewState属性,也可以在页面一级设置: <%@ Page EnableViewState=“false” %>
2、在恰当的时间点初始化控件属性
ASP.NET的控件在执行构造函数、初始化的期间设置的属性不会被跟踪变化;而在初始化阶段之后对属性的修改都会被跟踪,并最终记录到IE页面的__VIEWSTATE之中。所以,选择合理的初始化控件属性的执行点,能有效的减小页面尺寸。
3、谨慎选择放到ViewState中的内容
放到ViewState中的内容会被序列化/反序列化,Asp.net为String、Integer、Boolean等基本类型的序列化做了优化,如果Array、ArrayList、HashTable存储的是基本类型效率也较高,但其它类型则需要提供类型转换器(Type Converter),否则将使用代价昂贵的二进制序列化程序。
第二篇:。NET 性能优化方法总结与字符串连接优化
.NET 性能优化方法总结
Ver 1.0
2009-1-20
目录
1.C#语言方面...............................................................................................................4
1.1 垃圾回收.......................................................................................................4
1.1.1 避免不必要的对象创建.....................................................................4 1.1.2 不要使用空析构函数 ★...................................................................4 1.1.3 实现 IDisposable 接口.....................................................................4
1.2 String 操作....................................................................................................5
1.2.1 使用 StringBuilder 做字符串连接...................................................5 1.2.2 避免不必要的调用 ToUpper 或 ToLower 方法...........................5 1.2.3 最快的空串比较方法.........................................................................6
1.3 多线程...........................................................................................................6
1.3.1 线程同步.............................................................................................6 1.3.2 使用 ThreadStatic 替代 NameDataSlot ★.....................................7 1.3.3 多线程编程技巧.................................................................................7
1.4 类型系统.......................................................................................................8
1.4.1 避免无意义的变量初始化动作.........................................................8 1.4.2 ValueType 和 ReferenceType...........................................................8 1.4.3 尽可能使用最合适的类型.................................................................9
1.5 异常处理.....................................................................................................10
1.5.1 不要吃掉异常★...............................................................................10 1.5.2 不要吃掉异常信息★.......................................................................10 1.5.3 避免不必要的抛出异常...................................................................10 1.5.4 避免不必要的重新抛出异常...........................................................10 1.5.5 捕获指定的异常,不要使用通用的System.Exception.................10 1.5.6 要在finally里释放占用的资源......................................................11
1.6 反射.............................................................................................................11
1.6.1 反射分类...........................................................................................12 1.6.2 动态创建对象...................................................................................12 1.6.3 动态方法调用...................................................................................12 1.6.4 推荐的使用原则...............................................................................12
1.7 基本代码技巧.............................................................................................13
1.7.1 循环写法...........................................................................................13 1.7.2 拼装字符串.......................................................................................13 1.7.3 避免两次检索集合元素...................................................................13 1.7.4 避免两次类型转换...........................................................................14 1.7.5为字符串容器声明常量,不要直接把字符封装在双引号“ ”里面。.....................................................................................................................14 1.7.6 用StringBuilder代替使用字符串连接符 “+”...............................14 1.7.7 避免在循环体里声明变量,...........................................................15
1.8 Hashtable......................................................................................................15 1.8.1 Hashtable机理...................................................................................15 1.8.2 使用HashTale代替其他字典集合类型的情形:......................16
1.9 避免使用ArrayList。..............................................................................16 1.10从XML对象读取数据.............................................................................17 1.11 避免使用递归调用和嵌套循环,...........................................................17 1.12 使用适当的Caching策略来提高性能...................................................17
2.Ado.Net....................................................................................................................17
2.1 应用Ado.net的一些思考原则..................................................................18 2.2 Connection...................................................................................................18
2.2.1 在方法中打开和关闭连接...............................................................18 2.2.2 显式关闭连接...................................................................................18 2.2.3 确保连接池启用...............................................................................19 2.2.4 不要缓存连接...................................................................................19
2.3 Command.....................................................................................................19
2.3.1 使用ExecuteScalar和ExecuteNonQuery.......................................19 2.3.2 使用Prepare.....................................................................................19 2.3.3 使用绑定变量 ★.............................................................................19
2.4 DataReader...................................................................................................20
2.4.1 显式关闭DataReader.......................................................................20 2.4.2 用索引号访问代替名称索引号访问属性.......................................20 2.4.3 使用类型化方法访问属性...............................................................20 2.4.4 使用多数据集...................................................................................20
2.5 DataSet.........................................................................................................21
2.5.1 利用索引加快查找行的效率...........................................................21 2.使用DataView......................................................................................21
3.ASP.NET..................................................................................................................21
3.1 减少往返行程(Reduce Round Trips)...................................................21 3.2 避免阻塞和长时间的作业.........................................................................22 3.3 使用缓存.....................................................................................................22 3.4 多线程.........................................................................................................22 3.5 系统资源.....................................................................................................23 3.6 页面处理.....................................................................................................23 3.7 ViewState.....................................................................................................23
4.JScript.......................................................................................................................24
4.1 JScript性能优化的基本原则.....................................................................24 4.2 JScript语言本身的优化.............................................................................24 4.3 DOM相关...................................................................................................27 4.4 其他.............................................................................................................28
1.C#语言方面
1.1 垃圾回收
垃圾回收解放了手工管理对象的工作,提高了程序的健壮性,但副作用就是程序代码可能对于对象创建变得随意。1.1.1 避免不必要的对象创建
由于垃圾回收的代价较高,所以C#程序开发要遵循的一个基本原则就是避免不必要的对象创建。以下列举一些常见的情形。
1.1.1.1 避免循环创建对象 ★
如果对象并不会随每次循环而改变状态,那么在循环中反复创建对象将带来性能损耗。高效的做法是将对象提到循环外面创建。
1.1.1.2 在需要逻辑分支中创建对象
如果对象只在某些逻辑分支中才被用到,那么应只在该逻辑分支中创建对象。
1.1.1.3 使用常量避免创建对象
程序中不应出现如 new Decimal(0)之类的代码,这会导致小对象频繁创建及回收,正确的做法是使用Decimal.Zero常量。我们有设计自己的类时,也可以学习这个设计手法,应用到类似的场景中。
1.1.1.4 使用StringBuilder做字符串连接
1.1.2 不要使用空析构函数 ★
如果类包含析构函数,由创建对象时会在 Finalize 队列中添加对象的引用,以保证当对象无法可达时,仍然可以调用到 Finalize 方法。垃圾回收器在运行期间,会启动一个低优先级的线程处理该队列。相比之下,没有析构函数的对象就没有这些消耗。如果析构函数为空,这个消耗就毫无意义,只会导致性能降低!因此,不要使用空的析构函数。
在实际情况中,许多曾在析构函数中包含处理代码,但后来因为种种原因被注释掉或者删除掉了,只留下一个空壳,此时应注意把析构函数本身注释掉或删除掉。1.1.3 实现 IDisposable 接口
垃圾回收事实上只支持托管内在的回收,对于其他的非托管资源,例如
Window GDI 句柄或数据库连接,在析构函数中释放这些资源有很大问题。原因是垃圾回收依赖于内在紧张的情况,虽然数据库连接可能已濒临耗尽,但如果内存还很充足的话,垃圾回收是不会运行的。
C#的 IDisposable 接口是一种显式释放资源的机制。通过提供 using 语句,还简化了使用方式(编译器自动生成 try...finally 块,并在 finally 块中调用 Dispose 方法)。对于申请非托管资源对象,应为其实现 IDisposable 接口,以保证资源一旦超出 using 语句范围,即得到及时释放。这对于构造健壮且性能优良的程序非常有意义!
为防止对象的 Dispose 方法不被调用的情况发生,一般还要提供析构函数,两者调用一个处理资源释放的公共方法。同时,Dispose 方法应调用
System.GC.SuppressFinalize(this),告诉垃圾回收器无需再处理 Finalize 方法了。
1.2 String 操作
1.2.1 使用 StringBuilder 做字符串连接
String 是不变类,使用 + 操作连接字符串将会导致创建一个新的字符串。如果字符串连接次数不是固定的,例如在一个循环中,则应该使用 StringBuilder 类来做字符串连接工作。因为 StringBuilder 内部有一个 StringBuffer,连接操作不会每次分配新的字符串空间。只有当连接后的字符串超出 Buffer 大小时,才会申请新的 Buffer 空间。典型代码如下:
StringBuilder sb = new StringBuilder(256);for(int i = 0;i < Results.Count;i ++){
sb.Append(Results[i]);}
如果连接次数是固定的并且只有几次,此时应该直接用 + 号连接,保持程序简洁易读。实际上,编译器已经做了优化,会依据加号次数调用不同参数个数的 String.Concat 方法。例如:String str = str1 + str2 + str3 + str4;
会被编译为 String.Concat(str1, str2, str3, str4)。该方法内部会计算总的 String 长度,仅分配一次,并不会如通常想象的那样分配三次。作为一个经验值,当字符串连接操作达到 10 次以上时,则应该使用 StringBuilder。
这里有一个细节应注意:StringBuilder 内部 Buffer 的缺省值为 16,这个值实在太小。按 StringBuilder 的使用场景,Buffer 肯定得重新分配。经验值一般用 256 作为 Buffer 的初值。当然,如果能计算出最终生成字符串长度的话,则应该按这个值来设定 Buffer 的初值。使用 new StringBuilder(256)就将 Buffer 的初始长度设为了256。1.2.2 避免不必要的调用 ToUpper 或 ToLower 方法
String是不变类,调用ToUpper或ToLower方法都会导致创建一个新的字符串。如果被频繁调用,将导致频繁创建字符串对象。这违背了前面讲到的“避免频繁创建对象”这一基本原则。例如,bool.Parse方法本身已经是忽略大小写的,调用时不要调用ToLower方法。
另一个非常普遍的场景是字符串比较。高效的做法是使用 Compare 方法,这个方法可以做大小写忽略的比较,并且不会创建新字符串。
例:
const string C_VALUE = “COMPARE”;
if(String.Compare(sVariable, C_VALUE, true)== 0)
{
Console.Write(“SAME”);
}
还有一种情况是使用 HashTable 的时候,有时候无法保证传递 key 的大小写是否符合预期,往往会把 key 强制转换到大写或小写方法。实际上 HashTable 有不同的构造形式,完全支持采用忽略大小写的 key: new HashTable(StringComparer.OrdinalIgnoreCase)。1.2.3 最快的空串比较方法
将String对象的Length属性与0比较是最快的方法:if(str.Length == 0)
其次是与String.Empty常量或空串比较:if(str == String.Empty)或if(str == “")
注:C#在编译时会将程序集中声明的所有字符串常量放到保留池中(intern pool),相同常量不会重复分配。
1.3 多线程
1.3.1 线程同步
线程同步是编写多线程程序需要首先考虑问题。C#为同步提供了 Monitor、Mutex、AutoResetEvent 和 ManualResetEvent 对象来分别包装 Win32 的临界区、互斥对象和事件对象这几种基础的同步机制。C#还提供了一个lock语句,方便使用,编译器会自动生成适当的 Monitor.Enter 和 Monitor.Exit 调用。
1.3.1.1 同步粒度
同步粒度可以是整个方法,也可以是方法中某一段代码。为方法指定 MethodImplOptions.Synchronized 属性将标记对整个方法同步。例如:
[MethodImpl(MethodImplOptions.Synchronized)] public static SerialManager GetInstance(){
if(instance == null){
instance = new SerialManager();}
return instance;}
通常情况下,应减小同步的范围,使系统获得更好的性能。简单将整个方法标记为同步不是一个好主意,除非能确定方法中的每个代码都需要受同步保护。
1.3.1.2 同步策略
使用 lock 进行同步,同步对象可以选择 Type、this 或为同步目的专门构造的成员变量。
避免锁定Type★
锁定Type对象会影响同一进程中所有AppDomain该类型的所有实例,这不仅可能导致严重的性能问题,还可能导致一些无法预期的行为。这是一个很不好的习惯。即便对于一个只包含static方法的类型,也应额外构造一个static的成员变量,让此成员变量作为锁定对象。
避免锁定 this
锁定 this 会影响该实例的所有方法。假设对象 obj 有 A 和 B 两个方法,其中 A 方法使用 lock(this)对方法中的某段代码设置同步保护。现在,因为某种原因,B 方法也开始使用 lock(this)来设置同步保护了,并且可能为了完全不同的目的。这样,A 方法就被干扰了,其行为可能无法预知。所以,作为一种良好的习惯,建议避免使用 lock(this)这种方式。
使用为同步目的专门构造的成员变量
这是推荐的做法。方式就是 new 一个 object 对象,该对象仅仅用于同步目的。
如果有多个方法都需要同步,并且有不同的目的,那么就可以为些分别建立几个同步成员变量。
1.3.1.4 集合同步
C#为各种集合类型提供了两种方便的同步机制:Synchronized 包装器和 SyncRoot 属性。
// Creates and initializes a new ArrayList ArrayList myAL = new ArrayList();myAL.Add(” The “);myAL.Add(” quick “);myAL.Add(” brown “);myAL.Add(” fox “);
// Creates a synchronized wrapper around the ArrayList ArrayList mySyncdAL = ArrayList.Synchronized(myAL);
调用 Synchronized 方法会返回一个可保证所有操作都是线程安全的相同集合对象。考虑 mySyncdAL[0] = mySyncdAL[0] + ”test“ 这一语句,读和写一共要用到两个锁。一般讲,效率不高。推荐使用 SyncRoot 属性,可以做比较精细的控制。
1.3.2 使用 ThreadStatic 替代 NameDataSlot ★ 存取 NameDataSlot 的 Thread.GetData 和 Thread.SetData 方法需要线程同步,涉及两个锁:一个是 LocalDataStore.SetData 方法需要在 AppDomain 一级加锁,另一个是 ThreadNative.GetDomainLocalStore 方法需要在 Process 一级加锁。如果一些底层的基础服务使用了 NameDataSlot,将导致系统出现严重的伸缩性问题。
规避这个问题的方法是使用 ThreadStatic 变量。示例如下:
public sealed class InvokeContext {
[ThreadStatic]
private static InvokeContext current;
private Hashtable maps = new Hashtable();}
1.3.3 多线程编程技巧
1.3.3.1 使用 Double Check 技术创建对象
internal IDictionary KeyTable { get {
if(this._keyTable == null){
lock(base._lock){
if(this._keyTable == null){
this._keyTable = new Hashtable();} } }
return this._keyTable;} }
创建单例对象是很常见的一种编程情况。一般在 lock 语句后就会直接创建对象了,但这不够安全。因为在 lock 锁定对象之前,可能已经有多个线程进入到了第一个 if 语句中。如果不加第二个 if 语句,则单例对象会被重复创建,新的实例替代掉旧的实例。如果单例对象中已有数据不允许被破坏或者别的什么原因,则应考虑使用 Double Check 技术。
1.4 类型系统 1.4.1 避免无意义的变量初始化动作
CLR保证所有对象在访问前已初始化,其做法是将分配的内存清零。因此,不需要将变量重新初始化为0、false或null。
需要注意的是:方法中的局部变量不是从堆而是从栈上分配,所以C#不会做清零工作。如果使用了未赋值的局部变量,编译期间即会报警。不要因为有这个印象而对所有类的成员变量也做赋值动作,两者的机理完全不同!1.4.2 ValueType 和 ReferenceType
1.4.2.1 以引用方式传递值类型参数
值类型从调用栈分配,引用类型从托管堆分配。当值类型用作方法参数时,默认会进行参数值复制,这抵消了值类型分配效率上的优势。作为一项基本技巧,以引用方式传递值类型参数可以提高性能。
1.4.2.2 为 ValueType 提供 Equals 方法
.net 默认实现的 ValueType.Equals 方法使用了反射技术,依靠反射来获得所有成员变量值做比较,这个效率极低。如果我们编写的值对象其 Equals 方法要被用到(例如将值对象放到 HashTable 中),那么就应该重载 Equals 方法。
public struct Rectangle {
public double Length;public double Breadth;
public override bool Equals(object ob){
if(ob is Rectangle)
return Equels((Rectangle)ob))else
return false;}
private bool Equals(Rectangle rect){
return this.Length == rect.Length && this.Breadth == rect.Breach;} }
1.4.2.3 避免装箱和拆箱
C#可以在值类型和引用类型之间自动转换,方法是装箱和拆箱。装箱需要从堆上分配对象并拷贝值,有一定性能消耗。如果这一过程发生在循环中或是作为底层方法被频繁调用,则应该警惕累计的效应。
一种经常的情形出现在使用集合类型时。例如:
ArrayList al = new ArrayList();for(int i = 0;i < 1000;i ++){ al.Add(i);// Implicitly boxed because Add()takes an object }
int f =(int)al[ 0 ];// The element is unboxed
但是得当心!如果你像使用引用类型那么频繁的使用一个值类型的话,值类型的优势会很快被耗尽。比如,把一个值类型压到一个含有对象类型的群集。这叫做装箱,很耗用处理器周期,尤其是当你的代码在把它作为值(对它进行数学运算)和把它作为引用之间来回运行时。
1.4.3 尽可能使用最合适的类型
• 尽可能使用最合适的类型来描述数据,从而减少类型转换。
• 使用泛型来创建群集和其它的数据结构,这样,在运行时,它们就可以被实例化来存储刚好合适的类型。这节省了装箱/拆箱和类型转换的时间。
• 在C#中使用as,而不是is。关键字is用来查看引用是否可以被作为某个具体的类型,但是并不返回转换到这个类型的引用。所以,通常当你从is获得一个正的结果时,你首先应该cast——有效地执行两次cast。采用as关键词时,如果可用,则返回cast为新类型的引用;否则返回null。你可以查看null然后做你喜欢做的事情。整体来说,As方法要比is方法快50%。
1.5 异常处理
异常也是现代语言的典型特征。与传统检查错误码的方式相比,异常是强制性的(不依赖于是否忘记了编写检查错误码的代码)、强类型的、并带有丰富的异常信息(例如调用栈)。1.5.1 不要吃掉异常★
关于异常处理的最重要原则就是:不要吃掉异常。这个问题与性能无关,但对于编写健壮和易于排错的程序非常重要。这个原则换一种说法,就是不要捕获那些你不能处理的异常。
吃掉异常是极不好的习惯,因为你消除了解决问题的线索。一旦出现错误,定位问题将非常困难。除了这种完全吃掉异常的方式外,只将异常信息写入日志文件但并不做更多处理的做法也同样不妥。1.5.2 不要吃掉异常信息★
有些代码虽然抛出了异常,但却把异常信息吃掉了。
为异常披露详尽的信息是程序员的职责所在。如果不能在保留原始异常信息含义的前提下附加更丰富和更人性化的内容,那么让原始的异常信息直接展示也要强得多。千万不要吃掉异常。1.5.3 避免不必要的抛出异常 抛出异常和捕获异常属于消耗比较大的操作,在可能的情况下,应通过完善程序逻辑避免抛出不必要不必要的异常。与此相关的一个倾向是利用异常来控制处理逻辑。尽管对于极少数的情况,这可能获得更为优雅的解决方案,但通常而言应该避免。1.5.4 避免不必要的重新抛出异常
如果是为了包装异常的目的(即加入更多信息后包装成新异常),那么是合理的。但是有不少代码,捕获异常没有做任何处理就再次抛出,这将无谓地增加一次捕获异常和抛出异常的消耗,对性能有伤害。
1.5.5 捕获指定的异常,不要使用通用的System.Exception.//避免
try
{
}
catch(Exception exc)
{
}
//推荐
try
{
}
catch(System.NullReferenceException exc)
{
}
catch(System.ArgumentOutOfRangeException exc)
{
}
catch(System.InvalidCastException exc)
{
}
1.5.6 要在finally里释放占用的资源
使用Try...catch...finally时,要在finally里释放占用的资源如连接,文件流等,不然在Catch到错误后占用的资源不能释放。
try
{
...}
catch
{...}
finally
{
conntion.close()
}
1.6 反射
反射是一项很基础的技术,它将编译期间的静态绑定转换为延迟到运行期间的动态绑定。在很多场景下(特别是类框架的设计),可以获得灵活易于扩展的架构。但带来的问题是与静态绑定相比,动态绑定会对性能造成较大的伤害。1.6.1 反射分类
type comparison :类型判断,主要包括 is 和 typeof 两个操作符及对象实例上的 GetType 调用。这是最轻型的消耗,可以无需考虑优化问题。注意 typeof 运算符比对象实例上的 GetType 方法要快,只要可能则优先使用 typeof 运算符。
member enumeration : 成员枚举,用于访问反射相关的元数据信息,例如Assembly.GetModule、Module.GetType、Type对象上的IsInterface、IsPublic、GetMethod、GetMethods、GetProperty、GetProperties、GetConstructor调用等。尽管元数据都会被CLR缓存,但部分方法的调用消耗仍非常大,不过这类方法调用频度不会很高,所以总体看性能损失程度中等。
member invocation:成员调用,包括动态创建对象及动态调用对象方法,主要有Activator.CreateInstance、Type.InvokeMember等。1.6.2 动态创建对象
C#主要支持 5 种动态创建对象的方式:
1.Type.InvokeMember
2.ContructorInfo.Invoke
3.Activator.CreateInstance(Type)
4.Activator.CreateInstance(assemblyName, typeName)
5.Assembly.CreateInstance(typeName)
最快的是方式 3,与 Direct Create 的差异在一个数量级之内,约慢 7 倍的水平。其他方式,至少在 40 倍以上,最慢的是方式 4,要慢三个数量级。1.6.3 动态方法调用
方法调用分为编译期的早期绑定和运行期的动态绑定两种,称为Early-Bound Invocation和Late-Bound Invocation。Early-Bound Invocation可细分为Direct-call、Interface-call和Delegate-call。Late-Bound Invocation主要有Type.InvokeMember和MethodBase.Invoke,还可以通过使用LCG(Lightweight Code Generation)技术生成IL代码来实现动态调用。
从测试结果看,相比Direct Call,Type.InvokeMember要接近慢三个数量级;MethodBase.Invoke虽然比Type.InvokeMember要快三倍,但比Direct Call仍慢270倍左右。可见动态方法调用的性能是非常低下的。我们的建议是:除非要满足特定的需求,否则不要使用!1.6.4 推荐的使用原则
模式
1. 如果可能,则避免使用反射和动态绑定
2. 使用接口调用方式将动态绑定改造为早期绑定
3. 使用Activator.CreateInstance(Type)方式动态创建对象
4. 使用typeof操作符代替GetType调用
反模式
1. 在已获得Type的情况下,却使用Assembly.CreateInstance(type.FullName)
1.7 基本代码技巧
这里描述一些应用场景下,可以提高性能的基本代码技巧。对处于关键路径的代码,进行这类的优化还是很有意义的。普通代码可以不做要求,但养成一种好的习惯也是有意义的。1.7.1 循环写法
可以把循环的判断条件用局部变量记录下来。局部变量往往被编译器优化为直接使用寄存器,相对于普通从堆或栈中分配的变量速度快。如果访问的是复杂计算属性的话,提升效果将更明显。for(int i = 0, j = collection.GetIndexOf(item);i < j;i++)
需要说明的是:这种写法对于CLR集合类的Count属性没有意义,原因是编译器已经按这种方式做了特别的优化。1.7.2 拼装字符串
拼装好之后再删除是很低效的写法。有些方法其循环长度在大部分情况下为1,这种写法的低效就更为明显了:
public static string ToString(MetadataKey entityKey){
string str = ”“;
object [] vals = entityKey.values;for(int i = 0;i < vals.Length;i ++){
str += ” , “ + vals[i].ToString();}
return str == ”“ ? ”“ : str.Remove(0 , 1);}
推荐下面的写法:
if(str.Length == 0)str = vals[i].ToString();else
str += ” , “ + vals[i].ToString();其实这种写法非常自然,而且效率很高,完全不需要用个Remove方法绕来绕去。1.7.3 避免两次检索集合元素
获取集合元素时,有时需要检查元素是否存在。通常的做法是先调用ContainsKey(或Contains)方法,然后再获取集合元素。这种写法非常符合逻辑。
但如果考虑效率,可以先直接获取对象,然后判断对象是否为null来确定元素是否存在。对于Hashtable,这可以节省一次GetHashCode调用和n次Equals比较。
如下面的示例:
public IData GetItemByID(Guid id){
IData data1 = null;
if(this.idTable.ContainsKey(id.ToString()){
data1 = this.idTable[id.ToString()] as IData;}
return data1;}
其实完全可用一行代码完成:return this.idTable[id] as IData;1.7.4 避免两次类型转换
考虑如下示例,其中包含了两处类型转换:
if(obj is SomeType){
SomeType st =(SomeType)obj;st.SomeTypeMethod();}
效率更高的做法如下:
SomeType st = obj as SomeType;if(st!= null){
st.SomeTypeMethod();}
1.7.5为字符串容器声明常量,不要直接把字符封装在双引号” “里面。
//避免
//
MyObject obj = new MyObject();
obj.Status = ”ACTIVE“;
//推荐
const string C_STATUS = ”ACTIVE“;
MyObject obj = new MyObject();
obj.Status = C_STATUS;
1.7.6 用StringBuilder代替使用字符串连接符
//避免
String sXML = ” “;
sXML += ”“;
sXML += ”Data“;
sXML += ”“;
sXML += ”“;
//推荐
StringBuilder sbXML = new StringBuilder();
sbXML.Append(” “);
sbXML.Append(”“);
sbXML.Append(”Data“);
sbXML.Append(”“);
sbXML.Append(”“);
1.7.7 避免在循环体里声明变量,应该在循环体外声明变量,在循环体里初始化。
//避免
for(int i=0;i<10;i++)
+”
“
{
SomeClass objSC = new SomeClass();} //推荐
SomeClass objSC = null;for(int i=0;i<10;i++){
objSC = new SomeClass();)
1.8 Hashtable 1.8.1 Hashtable机理
Hashtable是一种使用非常频繁的基础集合类型。需要理解影响Hashtable的效率有两个因素:一是散列码(GetHashCode方法),二是等值比较(Equals方法)。Hashtable首先使用键的散列码将对象分布到不同的存储桶中,随后在该特定的存储桶中使用键的Equals方法进行查找。
良好的散列码是第一位的因素,最理想的情况是每个不同的键都有不同的散列码。Equals方法也很重要,因为散列只需要做一次,而存储桶中查找键可能需要做多次。从实际经验看,使用Hashtable时,Equals方法的消耗一般会占到一半以上。
System.Object类提供了默认的GetHashCode实现,使用对象在内存中的地址作为散列码。我们遇到过一个用Hashtable来缓存对象的例子,每次根据传递的OQL表达式构造出一个ExpressionList对象,再调用QueryCompiler的方法编译得到CompiledQuery对象。以ExpressionList对象和CompiledQuery对象作为键值对存储到Hashtable中。ExpressionList对象没有重载GetHashCode实现,其超类ArrayList也没有,这样最后用的就是System.Object类的GetHashCode实现。由于ExpressionList对象会每次构造,因此它的HashCode每次都不同,所以这个CompiledQueryCache根本就没有起到预想的作用。这个小小的疏漏带来了重大的性能问题,由于解析OQL表达式频繁发生,导致CompiledQueryCache不断增长,造成服务器内存泄漏!解决这个问题的最简单方法就是提供一个常量实现,例如让散列码为常量0。虽然这会导致所有对象汇聚到同一个存储桶中,效率不高,但至少可以解决掉内存泄漏问题。当然,最终还是会实现一个高效的GetHashCode方法的。
以上介绍这些Hashtable机理,主要是希望大家理解:如果使用Hashtable,你应该检查一下对象是否提供了适当的GetHashCode和Equals方法实现。否则,有可能出现效率不高或者与预期行为不符的情况。
1.8.2 使用HashTale代替其他字典集合类型的情形:
其他字典集合类型(如StringDictionary,NameValueCollection,HybridCollection),存放少量数据的时候可以使用HashTable。很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类:
非泛型集合类 泛型集合类
ArrayList List
HashTable DIctionary
SortedList SortedList
我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化
用 Dictionary
1.9 避免使用ArrayList。
因为任何对象添加到ArrayList都要封箱为System.Object类型,从ArrayList取出数据时,要拆箱回实际的类型。建议使用自定义的集合类型代替ArrayList。.net 2.0提供了一个新的类型,叫泛型,这是一个强类型,使用泛型集合就可以避免了封箱和拆箱的发生,提高了性能。
1.10从XML对象读取数据
如果只是从XML对象读取数据,用只读的XPathDocument代替XMLDocument,可以提高性能
//避免
XmlDocument xmld = new XmlDocument();
xmld.LoadXml(sXML);
txtName.Text = xmld.SelectSingleNode(”/packet/child“).InnerText;
.//推荐
XPathDocument xmldContext = new XPathDocument(new StringReader(oContext.Value));
XPathNavigator xnav = xmldContext.CreateNavigator();
XPathNodeIterator xpNodeIter = xnav.Select(”packet/child“);
iCount = xpNodeIter.Count;
xpNodeIter = xnav.SelectDescendants(XPathNodeType.Element, false);
while(xpNodeIter.MoveNext())
{
sCurrValues += xpNodeIter.Current.Value+”~“;
}
}
1.11 避免使用递归调用和嵌套循环,使用他们会严重影响性能,在不得不用的时候才使用。
1.12 使用适当的Caching策略来提高性能
2.Ado.Net
2.1 应用Ado.net的一些思考原则
1.根据数据使用的方式来设计数据访问层 2.缓存数据,避免不必要的操作 3.使用服务帐户进行连接 4.必要时申请,尽早释放 5.关闭可关闭的资源 6.减少往返
7.仅返回需要的数据 8.选择适当的事务类型 9.使用存储过程
2.2 Connection 数据库连接是一种共享资源,并且打开和关闭的开销较大。Ado.net默认启用了连接池机制,关闭连接不会真的关闭物理连接,而只是把连接放回到连接池中。因为池中共享的连接资源始终是有限的,如果在使用连接后不尽快关闭连接,那么就有可能导致申请连接的线程被阻塞住,影响整个系统的性能表现。2.2.1 在方法中打开和关闭连接
这个原则有几层含义:
1.主要目的是为了做到必要时申请和尽早释放
2.不要在类的构造函数中打开连接、在析构函数中释放连接。因为这将依赖于垃圾回收,而垃圾回收只受内存影响,回收时机不定
3.不要在方法之间传递连接,这往往导致连接保持打开的时间过长
这里强调一下在方法之间传递连接的危害:曾经在压力测试中遇到过一个测试案例,当增大用户数的时候,这个案例要比别的案例早很久就用掉连接池中的所有连接。经分析,就是因为A方法把一个打开的连接传递到了B方法,而B方法又调用了一个自行打开和关闭连接的C方法。在A方法的整个运行期间,它至少需要占用两条连接才能够成功工作,并且其中的一条连接占用时间还特别长,所以造成连接池资源紧张,影响了整个系统的可伸缩性!
2.2.2 显式关闭连接
Connection对象本身在垃圾回收时可以被关闭,而依赖垃圾回收是很不好的策略。推荐使用using语句显式关闭连接,如下例:
using(SqlConnection conn = new SqlConnection(connString)){
conn.Open();
} // Dispose is automatically called on the conn variable here
2.2.3 确保连接池启用
Ado.net是为每个不同的连接串建立连接池,因此应该确保连接串不会出现与具体用户相关的信息。另外,要注意连接串是大小写敏感的。2.2.4 不要缓存连接
例如,把连接缓存到Session或Application中。在启用连接池的情况下,这种做法没有任何意义。
2.3 Command
2.3.1 使用ExecuteScalar和ExecuteNonQuery
如果想返回像Count(*)、Sum(Price)或Avg(Quantity)那样的单值,可以使用ExecuteScalar方法。ExecuteScalar返回第一行第一列的值,将结果集作为标量值返回。因为单独一步就能完成,所以ExecuteScalar不仅简化了代码,还提高了性能。
使用不返回行的SQL语句时,例如修改数据(INSERT、UPDATE或DELETE)或仅返回输出参数或返回值,请使用ExecuteNonQuery。这避免了用于创建空DataReader的任何不必要处理。2.3.2 使用Prepare
当需要重复执行同一SQL语句多次,可考虑使用Prepare方法提升效率。需要注意的是,如果只是执行一次或两次,则完全没有必要。例如:
cmd.CommandText = ”insert into Table1(Col1, Col2)values(@val1, @val2)“;
cmd.Parameters.Add(”@val1“, SqlDbType.Int, 4, ”Col1“);cms.Parameters.Add(”@val2“, SqlDbType.NChar, 50, ”Col2“);
cmd.Parameters[0].Value = 1;
cmd.Parameters[1].Value = ”XXX“;cmd.Prepare();
cmd.ExecuteNonQuery();
cmd.Parameters[0].Value = 2;
cmd.Parameters[1].Value = ”YYY“;cmd.ExecuteNonQuery();
cmd.Parameters[0].Value = 3;
cmd.Parameters[1].Value = ”ZZZ“;cmd.ExecuteNonQuery();
2.3.3 使用绑定变量 ★
SQL语句需要先被编译成执行计划,然后再执行。如果使用绑定变量的方式,那么这个执行计划就可以被后续执行的SQL语句所复用。而如果直接把参数合并到了SQL语句中,由于参数值千变万化,执行计划就难以被复用了。例如上面Prepare一节给出的示例,如果把参数值直接写到insert语句中,那么上面的四次调用将需要编译四次执行计划。
为避免这种情况造成性能损失,要求一律使用绑定变量方式。
2.4 DataReader
DataReader最适合于访问只读的单向数据集。与DataSet不同,数据集并不全部在内存中,而是随不断发出的read请求,一旦发现数据缓冲区中的数据均被读取,则从数据源传输一个数据缓冲区大小的数据块过来。另外,DataReader保持连接,DataSet则与连接断开。2.4.1 显式关闭DataReader
与连接类似,也需要显式关闭DataReader。另外,如果与DataReader关联的Connection仅为DataReader服务的话,可考虑使用Command对象的ExecuteReader(CommandBehavior.CloseConnection)方式。这可以保证当DataReader关闭时,同时自动关闭Connection。2.4.2 用索引号访问代替名称索引号访问属性
从Row中访问某列属性,使用索引号的方式比使用名称方式有细微提高。如果会被频繁调用,例如在循环中,那么可考虑此类优化。示例如下:
cmd.CommandText = ”select Col1, Col2 from Table1“;SqlDataReader dr = cmd.ExecuteReader();
int col1 = dr.GetOrdinal(”Col1“);int col2 = dr.GetOrdinal(”Col2“);
while(dr.Read()){
Console.WriteLine(dr[col1] + ”_“ + dr[col2]);}
2.4.3 使用类型化方法访问属性
从Row中访问某列属性,用GetString、GetInt32这种显式指明类型的方法,其效率较通用的GetValue方法有细微提高,因为不需要做类型转换。2.4.4 使用多数据集
部分场景可以考虑一次返回多数据集来降低网络交互次数,提升效率。示例如下:
cmd.CommandText = ”StoredProcedureName“;// The stored procedure returns multiple result sets.SqlDataReader dr = cmd.ExecuteReader();
while(dr.read())// read first result set
dr.NextResult();
while(dr.read())//
2.5 DataSet
2.5.1 利用索引加快查找行的效率
如果需要反复查找行,建议增加索引。有两种方式:
1.设置DataTable的PrimaryKey
适用于按PrimaryKey查找行的情况。注意此时应调用DataTable.Rows.Find方法,一般惯用的Select方法不能利用索引。2.使用DataView
适用于按Non-PrimaryKey查找行的情况。可为DataTable创建一个DataView,并通过SortOrder参数指示建立索引。此后使用Find或FindRows查找行。
3.ASP.NET
3.1 减少往返行程(Reduce Round Trips)
使用下面的方法可以减少Web服务器和Browser之间的往返行程:
1.为Browser启用缓存
如果呈现的内容是静态的或变化周期较长,应启用Browser缓存,避免发出冗余的http请求。2.缓冲页面输出
如果可能,则尽量缓冲页面输出,处理结束后再一次传送到客户端,这可以避免频繁传递小块内容所造成的多次网络交互。由于这种方式在页面处理结束之前客户端无法看到页面内容,因此如果一个页面的尺寸较大的话,可考虑使用Response.Flush方法。该方法强制输出迄今为止在缓冲区中的内容,你应当采用合理的算法控制调用Response.Flush方法的次数。
3.使用Server.Transfer重定向请求
使用Server.Transfer方法重定向请求优于Response.Redirect方法。原因是Response.Redirect会向Broswer回送一个响应头,在响应头中指出重定向的URL,之后Brower使用新的URL重新发出请求。而Server.Transfer方法直接是一个简单的服务端调用,完全没有这些开销!
需要注意Server.Transfer有局限性:第一,它会跳过安全检查;第二,只适用于在同一Web应用内的页面间跳转。
3.2 避免阻塞和长时间的作业 如果需要运行阻塞或长时间运行的操作,可以考虑使用异步调用的机制,以便Web服务器能够继续处理其它的请求。
1.使用异步方式调用Web服务和远程对象
只要有可能就要避免在请求的处理过程中对Web服务和远程对象的同步调用,因为它占用的是的ASP.NET 线程池中的工作线程,这将直接影响Web服务器响应其它请求的能力。
2.考虑给不需要返回值的Web方法或远程对象的方法添加OneWay属性
这种模式能让Web Server调用之后就立即返回。可根据实际情况决定是否使用这种方法。
3.使用工作队列
将作业提交到服务器上的工作队列中。客户端通过发送请求来轮询作业的执行结果。
3.3 使用缓存
缓存能在很大程度上决定ASP.NET应用的最终性能。Asp.net支持页面输出缓存和页面部分缓存,并提供Cache API,供应用程序缓存自己的数据。是否使用缓存可考虑下面的要点:
1.识别创建与访问代价较大的数据
2.评估需要缓存数据的易变性
3.评估数据的使用频次
4.将要缓存数据中易变数据和不变数据分离,只缓存不变数据
5.选择合适的缓存机制(除Asp.net Cache外,Application state和Session state也可以作为缓存使用)
3.4 多线程
1.避免在请求处理过程中创建线程
在执行请求的过程中创建线程是一种代价较大的操作,会严重影响Web Server的性能。如果后续的操作必须用线程完成,建议通过thread pool来创建/管理线程。
2.不要依赖线程数据槽或线程静态变量
由于执行请求的线程是ASP.NET thread pool中的工作线程,同一个Client的两次请求不一定由相同的线程来处理。
3.避免阻塞处理请求的线程
参考”避免阻塞和长时间的作业“小节。
4.避免异步调用
这和1的情况类似。异步调用会导致创建新的线程,增加服务器的负担。所以,如果没有并发的作业要执行,就不要执行异步调用。
3.5 系统资源
1.考虑实现资源池以提升性能
2.明确地调用Dispose或Close释放系统资源 3.不要缓存或长时间占用资源池中的资源 4.尽可能晚的申请,尽可能早的释放
3.6 页面处理
1.尽量减小Page的尺寸
包括缩短控件的名称、CSS的class的名称、去掉无谓空行和空格、禁用不需要的ViewState
2.启用页面输出的缓冲区(Buffer)
如果Buffer的机制被关闭,可以用下面的方法打开。
使用程序打开页面输出缓存:
Response.BufferOutput = true;
使用@Page开关打开页面输出缓冲机制:
<%@ Page Buffer = ”true“ %>
使用Web.config或Machine.config配置文件的
节点:
3.利用Page.IsPostBack优化页面输出
4.通过分离页面的不同的内容,来提高缓存效率和减少呈现的时间
5.优化复杂和代价较大的循环
6.合理利用客户端的计算资源,将一些操作转移到客户端进行
3.7 ViewState
ViewState是Asp.net为服务端控件在页面回传之间跟踪状态信息而设计的一种机制。
1.关闭ViewState
如果不需要跟踪页面状态,例如页面不会 回传(PostBack)、不需要处理服务端控件事件或者每次页面刷新时都会重新计算控件内容,那么就不需要用ViewState来记录页面状态了。可以对特定的WebControl设置EnableViewState属性,也可以在页面一级设置:
<%@ Page EnableViewState=”false“ %>
2.在恰当的时间点初始化控件属性
ASP.NET的控件在执行构造函数、初始化的期间设置的属性不会被跟踪变化;而在初始化阶段之后对属性的修改都会被跟踪,并最终记录到IE页面的__VIEWSTATE之中。所以,选择合理的初始化控件属性的执行点,能有效的减小页面尺寸。
3.谨慎选择放到ViewState中的内容
放到ViewState中的内容会被序列化/反序列化,Asp.net为String、Integer、Boolean等基本类型的序列化做了优化,如果Array、ArrayList、HashTable存储的是基本类型效率也较高,但其它类型则需要提供类型转换器(Type Converter),否则将使用代价昂贵的二进制序列化程序。
4.JScript
4.1 JScript性能优化的基本原则
1.尽可能少地减少执行次数。毕竟对解释语言来说,每一个执行步骤,都需要和解释引擎做一次交互。
2.尽可能使用语言内置的功能,比如串链接。
3.尽可能使用系统提供的API来进行优化。因为这些API是编译好的二进制代码,执行效率很高。
4.书写最正确的代码。容错功能是要付出性能代价的。
4.2 JScript语言本身的优化
4.2.1 变量
1.尽量使用局部变量。
因为全局变量其实是全局对象的成员,而局部变量在栈上定义,优先查找,性能相对于全局变量要高。
2.尽量在一个语句中做定义变量和赋值。
3.省略不必要的变量定义。
如果变量的定义可以被一个常量替代,就直接使用常量。
4.使用Object语法对对象赋值。Object的赋值语法在操作复杂对象时效率更高。
例如,可以将下面的代码:
car = new Object();car.make = ”Honda“;car.model = ”Civic“;
car.transmission = ”manual“;car.miles = 100000;
car.condition = ”needs work“;替换成:
car = {
make: ”Honda“, model: ”Civic“,transmission: ”manual“, miles: 100000,condition: ”needs work“ }
4.2.2 对象缓存
1.缓存对象查找的中间结果。
因为JavaScript的解释性,所以a.b.c.d.e,需要进行至少4次查询操作,先检查a再检查a中的b,再检查b中的c,如此往下。所以如果这样的表达式重复出现,只要可能,应该尽量少出现这样的表达式,可以利用局部变量,把它放入一个临时的地方进行查询。
2.缓存创建时间较长的对象。
自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用,应采用缓存的方式。
4.2.3 字符串操作
1.使用”+=“ 追加字符串,使用”+“来连接字符串。
如果是追加字符串,最好使用s+=anotherStr操作,而不是要使用s=s+anotherStr。
如果要连接多个字符串,应该使用”+“,如:
s+=a;
s+=b;
s+=c;
应该写成
s+=a + b + c;
2.连接大量的字符串,应使用Array的join方法。如果是收集字符串,最好使用JavaScript数组缓存,最后使用join方法连接起来,如下:
var buf = new Array();for(var i = 0;i < 100;i++){
buf.push(i.toString());}
var all = buf.join(”“);
4.2.4 类型转换
1.使用Math.floor()或者Math.round()将浮点数转换成整型。
浮点数转换成整型,这个更容易出错,很多人喜欢使用parseInt(),其实parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,我们应该使用Math.floor()或者Math.round()。
对象查找中的问题不一样,Math是内部对象,所以Math.floor()其实并没有多少查询方法和调用的时间,速度是最快的。
2.自定义的对象,推荐定义和使用toString()方法来进行类型转换。
对于自定义的对象,如果定义了toString()方法来进行类型转换的话,推荐显式调用toString()。因为内部的操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String,所以直接调用这个方法效率会更高。
4.2.5 循环的优化
1.尽可能少使用for(in)循环。
在JavaScript中,我们可以使用for(;;),while(),for(in)三种循环,事实上,这三种循环中for(in)的效率极差,因为他需要查询散列键,只要可以就应该尽量少用。
2.预先计算collection的length。
如:将for(var i = 0;i < collection.length;i++)
替换成:for(var i = 0, len = collection.length;i < len;i++)
效果会更好,尤其是在大循环中。
3.尽量减少循环内的操作。
循环内的每个操作,都会被放大为循环次数的倍数。所以,大循环内微小的改进,在性能的整体提升上都是可观的。
4.使用循环替代递归。
相比循环,递归的效率更差一些。递归的优点是在形式上更自然一些。所以,在不影响代码的维护性的前提下,用循环替代递归。
4.2.6 其它方面
1.尽量使用语言内置的语法。
”var arr = [„];“和”var arr = new Array(„);“是等效的,但是前者的效能优于后者。同样,”var foo = {};“的方式也比”var foo = new Object();“快;”var reg = /../;“要比”var reg=new RegExp()“快。
2.尽量不要使用eval。
使用eval,相当于在运行时再次调用解释引擎,对传入的内容解释运行,需要消耗大量时间。
3.使用prototype代替closure。
使用closure在性能和内存消耗上都是不利的。如果closure使用量过大,这就会成为一个问题。所以,尽量将:
this.methodFoo = function()
替换成:
MyClass.protoype.methodFoo = function()
和closure存在于对象实例之中不同,prototype存在于类中,被该类的所有的对象实例共享。
4.避免使用with语句。
With语句临时扩展对象查找的范围,节省了文字的录入时间,但付出了更多的执行时间。因为每个给出的名称都要在全局范围查找。所以,可以将下面的代码:
with(document.formname){
field1.value = ”one“;field2.value = ”two“;}
变更为:
var form = document.formname;form.field1.value = ”one“;form.field2.value = ”two“;
4.3 DOM相关
4.3.1 创建DOM节点
相比较通过document.write来给页面生成内容,找一个容器元素(比如指定一个div或者span)并设置他们的innerHTML效率更高。而设置innerHTML的方式比通过createElement方法创建节点的效率更高。事实上,设置元素的innerHTML是创建节点效率最高的一种方式。
如果必须使用createElement方法,而如果文档中存在现成的样板节点,应该是用cloneNode()方法。因为使用createElement()方法之后,你需要设置多次元素的属性,使用cloneNode()则可以减少属性的设置次数。同样,如果需要创建很多元素,应该先准备一个样板节点。
4.3.2 离线操作大型的DOM树
在添加一个复杂的DOM树时,可以先构造,构造结束后再将其添加到DOM数的适当节点。这能够节省界面刷新的时间。
同样,在准备编辑一个复杂的树时,可以先将树从DOM树上删除,等编辑结束后再添加回来。
4.3.3 对象查询
使用[”“]查询要比.item()更快。调用.item()增加了一次查询和函数的调用。
4.3.4 定时器
如果针对的是不断运行的代码,不应该使用setTimeout,而应该用setInterval。setTimeout每次要重新设置一个定时器。
4.4 其他
1.尽量减小文件尺寸。
将JScript文件中无关的空行、空格、注释去掉,有助于减小JS文件的尺寸,提高下载的时间。(可以通过工具来支持代码发布)
2.尽量不要在同一个Page内同时引用JScript和VBScript引擎
3.将Page内的JScript移入到单独的JS文件中。
4.将Page内的JScript放置在Page的最下面,有助于提高页面的响应速度。
5.利用cache,减少JScript文件的下载次数
6.在HTML内书写JScript文件的URL时,注意统一大小写。这样可以利用前面URL缓存的文件。
C# 性能优化——三种字符串拼接效率
2011年04月07日 星期四 17:56 字符串拼接主要包括三类:+,String.Format(),StringBuilder.Append()1)对于少量固定的字符串拼接,如string s= ”a“ + ”b“ + ”c“,系统会优化成s= String.Concat(”a“,”b“,”c“),不会新建多个字符串。
如果写成string s=”a“;s +=”b“;s+=”c“;则会创建三个新的字符串。2)String.Format的源代码: public static String Format(IFormatProvider provider, String format, params Object[] args){ if(format == null || args == null)throw new ArgumentNullException((format==null)?”format“:”args“);StringBuilder sb = new StringBuilder(format.Length + args.Length * 8);sb.AppendFormat(provider,format,args);return sb.ToString();} 可见,它和StringBuilder有着相似的效率,比用“+”的拼接方式高效,并且代码易于阅读。
string s= String.Format(”{0}{1}{2}“,”a“,”b“,”c");3)StringBuilder可以指定内存空间的容量,但可能需要进行数据类型转化。字符串较少时,可以使用String.Format()代替。
4)少量的字符串操作时,可以使用“+”或者String.Format();大量的字符串操作时,比如在循环体内,必须使用StringBuilder.Append()。
第三篇:NET 开发总结
.NET 开发总结
Web窗体的简单说明:
这次作业都有一个共同点就是连接数据库,对数据连接函数不是很熟悉,弄了好久,最后还是请教同学才实现数据库的连接,连接代码如下图:
数据库连接完成后,开始进行数据的整体的查询,将查询到的数据转换成参数,利用参数进行分页,将数据显示在web上去。
对于分页,我是按照每页显示是个数据来显示的,本来还打算弄一个下拉窗口,当窗口下拉式可以选择多少个数据分页显示,这一部分的功能还没来得及去实现。
分页的部分代码
对于web 的查询功能,用的是模糊查询,代码如图
本次的.net开发技术作业,我选择做webForm的分页,之前一直没有写过web的代码,只自学过一点脚本语言,对C#也不太了解,所以当做起来的时候比较困难,自己上网找了不少资料,到图书馆借了一些关于asp.net web开发的书,对C#开发的平台还不是很熟悉,当程序调试起来非常困难,经常因为小问题而浪费许多的时间,开发过程中请教过一些有过web开发经验的同学,也有帮助我进行程序的调试。由于不熟悉浪费了许多时间,没有对代码没有时间去整理,使得代码看起来很凌乱,很累赘,看起来显得麻烦,还是一些功能还没有实现,像查询后的数据进行分页,以及数据的修改和删除。
第四篇:敏捷开发简介
敏捷开发简介
2009-04-21 17:46:34.0来源:e800.com.cn
关键词:Scrum精益开发敏捷开发
在软件工业界,敏捷开发已成为众多高效开发团队的制胜之道。它不仅被许多中小公司青睐,在全球一百强的企业中,敏捷也已大行其道,受到许多资深项目管理者和开发人员的推崇。欧美软件企业中,有近半企业已采用敏捷方法进行开发。大多数尚未应用敏捷的企业,也都对其有所了解,而且很多在计划实施。中国的外企,外包公司和许多知名企业也都开始采用了敏捷方法。例如,腾讯内部几乎所有的开发团队都在实施敏捷。敏捷方法给这些企业也已带来了巨大的收益。据业内资深人士和长期从事敏捷咨询的服务公司透露,采用敏捷开发的团队一般会提高3-10倍的效率,软件的质量也有了更加可靠的保证。同时,敏捷开发的应用也给团队内的每个成员提供了良好的发展机会。他们的技术和合作水平都能得到响应的提高。敏捷的成功来源于其方法本身的适用性和团队对它的深入理解和合理运用。下面我们就对敏捷开发做一个简单的介绍和讨论。敏捷开发由几种轻量级的软件开发方法组成。它们包括:极限编程(XP),Scrum,精益开发(Lean Development),动态系统开发方法(DSDM),特征驱动开发(Feature Driver Development),水晶开发(Cristal Clear)等等。所有这些方法都具有以下共同特征,它们也是敏捷开发的原则和方法:
1.迭代式开发。即整个开发过程被分为几个迭代周期,每个迭代周期是一个定长或不定长的时间块每个迭代周期持续的时间一般较短,通常为一到六周。
2.增量交付。产品是在每个迭代周期结束时被逐步交付使用,而不是在整个开发过程结束的时候一次性交付使用。每次交付的都是可以被部署到用户应用环境中被用户使用的、能给用户带来即时效益和价值的产品。
3.开发团队和用户反馈推动产品开发。敏捷开发方法主张用户能够全程参与到整个开发过程中。这使需求变化和用户反馈能被动态管理并及时集成到产品中。同时,团队对于用户的需求也能及时提供反馈意见。
4.持续集成。新的功能或需求变化总是尽可能频繁地被整合到产品中。一些项目是在每个迭代周期结束的时候
集成,有些项目则每天都在这么做。
5.开发团队自我管理。拥有一个积极的、自我管理的、具备自由交流风格的开发团队,是每个敏捷项目必不可少的条件。人是敏捷开发的核心。敏捷开发总是以人为中心建立开发的过程和机制,而非把过程和机制强加给
人。
简史
许多人认为,相比于“传统”的瀑布开发模式,敏捷开发是一种“现代”的开发模式。但是,实际上敏捷方法,特别是迭代和增量开发方法(IID)起源于20世纪30年代的一些非软件项目。而最早引入一些敏捷方法的项目之一就是20世纪60年代初的美国航天局水星计划。在这个项目中,一些极限编程方法如测试先行等也被使用。此后,迭代和增量开发被IBM联邦系统部(FSD)和沃森研究中心(Watson Research Center)采纳。有趣的是一些研究人员甚至在关于瀑布开发模式的最早的论文中发现了敏捷开发的线索。在这篇论文中,温斯顿.罗伊斯(Winston Royce)建议在一个项目中使用两次瀑布模式,也就是使用两次迭代。20世纪70年代,最早的有记载的使用迭代和增量开发的主要项目之一,是为第一艘美国三叉戟潜艇开发的第一指挥和控制系统。该项目有大约一百万行代码,进行得非常成功。迭代和增量开发从此开始稳步发展,越来越多的项目开始使用这种开发模式。在1976年,Tom Gilb在他的著作《软件度量》(“Software Metrics”)一书中阐述了他的迭代和增量开发实践,这可能就是第一部阐述这种方法的书籍。迭代和增量开发的另一次出色发挥,是在一个美国宇航局航天飞机软件的开发项目。这个项目负责开发其航空电子设备的软件系统。改项目由IBM联邦系统部(IBM FSD)在1977至1980年完成。一些典型的敏捷做法,如使用8
个周迭代以及用反馈推动开发循序渐进等方法都在该项目中得以应用。
20世纪80年代,更多的出版物和更多的项目应用进一步推进了迭代开发的发展。在1895年,巴里贝母(Barry Boehm)正式定义了使用迭代开发的螺旋模型(Spiral model)。80年代初,在美国国防部发生
了一件有趣的事情。美国国防部一直以来都要求其软件开发商在开发过程中使用严格的瀑布开发模型。但是到了1987年末,国防部开始“建议”使用迭代和增量开发作为软件开发模式。后来美国国防部的项目审查显示,早期使用瀑布模式开发的软件项目,有75%以失败告终,有些开发出来的产品根本没有被使用过,只有2%的软件产品无需大量修改就能被正常使用。
20世纪90年代,推荐使用迭代和增量开发的出版物和文献显著增加。在经历了多次有“瀑布心态”
(„waterfall mentality‟)项目的失败之后,美国国防部开始“要求”而不是像80年代那样仅仅是“建议”他们的软件开发商使用IID开发模式。Rational统一开发过程(Rational Unified Process)也是在这一时期产生并发展起来的,它具有更规范的迭代渐进过程。到2000年底,更多的敏捷方法被广泛推广并被使用于各种不同的项目中。2001年二月,一组由17位在DSDM,XP,Scrum,FSD等领域的专家组成的代表团齐聚美国犹他州,寻找这些方法的共同点。最终,这些专家制定并宣布了敏捷开发宣言。由此形成了现在我们所
认识的敏捷开发和后来的敏捷联盟。
敏捷优势
为什么瀑布模式多数情况下总会失败?为什么我们需要敏捷开发模式?这个问题在日新月异,飞速发展的今天似乎很容易解释。尽管瀑布模式能够在一个迭代周期内表现优异,但是,在如何管理需求变化面前,瀑布模式
却显得无能为力。而事实上,大多数的软件项目都具有以下一些特点:
·在初始阶段,最终用户通常不能准确得知道他们需要什么样的软件。即便知道,也很少有人能准确清楚的表
达出来。
·对于某些项目,在一开始,我们可以很好的定义其所有的功能,但是可能有很多细节只能随着项目的不断深入才能被挖掘出来。即便是我们了解了所有的细节,大多数人还是不能很好的处理这些细节,特别是在项目开
发初期。
·外部环境如客户的业务模式,技术进步,甚至是系统的终端用户都有可能在开发过程中不断改变。而预想或
试图阻止这些改变通常都是徒劳的。
·在互联网时代,许多Web应用程序的开发都是基于对远景客户的预期,而非当前用户的实际需求。在这种
情况下,变化从开始就有,而且在系统开始应用后几乎每天都会发生。
敏捷方法处理需求和技术变化主要通过迭代过程来管理。在每一次迭代周期结束时,都应交付用户一个可用的,可部署的系统。使用并体验该系统所获得的有价值的反馈意见将按顺序,在随后的迭代周期中和其它需求变化一起在产品中实现和集成。每次迭代周期应尽可能短,以便能及时频繁地处理需求变化和用户反馈。
采用敏捷开发方式将会给企业和用户带来诸多好处:
·精确。它将带给用户真正需要的软件系统。瀑布模式通常会在产品起点与最终结果之间计划出一条直线,然后沿着直线不断往前走。然而当项目到达终点时,用户通常会发现那已经不是他们想去的地方。而敏捷方法则
采用小步的方式向前走,每走完一步,都需要及时调整并为下一步确定当前的方向,直到真正的终点。·质量。敏捷方法对每一次迭代周期的质量都有严格要求。一些敏捷方法如XP等,甚至使用测试驱动开发(test-driven development),即在正式开发功能代码之前,先开发该功能的测试代码。这些都对敏捷项
目的整个开发周期提供了可靠的质量保证。
·速度。敏捷开发提倡避免较大的前期规划,认为那是一种很大的浪费。因为很多预先计划的东西都会发生改变,大规模的前期规划通常是徒劳的。敏捷团队只专注于开发项目中当前最需要的,最具价值的部分。这样能
很快地投入开发。另外,较短的迭代周期使团队成员能迅速进入开发状态。
·丰厚的投资回报率(ROI)。在敏捷开发过程中,最具价值的功能总是被优先开发,这样能给客户带来最大的投资回报率。
·高效的自我管理团队。这既是采用敏捷开发的必然结果,也是推动敏捷开发不断前进的动力。敏捷开发要求团队成员必须积极主动,自我管理。在这样的团队中工作,每个团队成员的技术能力,交流,社交,表达和领
导能力也都能得以提高。
主要的敏捷方法
极限编程(XP)
极限编程(XP)的主要目的是降低需求变化的成本。它引入一系列优秀的软件开发方法,并将它们发挥到极致。比如,为了能及时得到用户的反馈,XP要求客户代表每天都必须与开发团队在一起。同时,XP要求所有的编程都采用结对编程(pair-programming)的方式。这种方式是传统的同行审查(peer review)的一种极端表现,或者可以说是它的替代方式。
XP定义了一套简单的开发流程,包括:编写用户案例,架构规范,实施规划,迭代计划,代码开发,单元测
试,验收测试等等。
像所有其他敏捷方法一样,XP预期并积极接受变化。它具有以下的价值观或原则:
·互动交流。团队成员不是通过文档来交流,文档不是必须的。团队成员之间通过日常沟通,简单设计,测
试,系统隐喻以及代码本身来沟通产品需求和系统设计。
·反馈。反馈是一种信息的交流,能使系统更加完善。反馈也和交流密切相关,客户的实际使用、功能测试、单元测试等都能为开发团队提供反馈信息。同时,开发团队也可以通过估计和设计用户案例的方式将信息反馈
给客户。
·简单。XP提倡简单的设计,简单的解决方案。XP总是从一个简单的系统入手,并且只创建今天,而不是明
天,需要的功能模块。因为它认为,创建明天需要的功能模块可能会由于需求的变化而成为浪费。
·勇气。XP在这一点所要达到的目的(我们认为)是鼓励一些有较高风险的良好的做法。例如,它要求程序员
尽可能频繁地重构代码,必须删除过时的代码,不解决技术难题就不罢休,等等。
·团队。XP提倡团队合作,相互尊重。XP以建立并激励团队为一项重要任务。同时它把互相尊重和实际的开发习惯相结合。比如,为了尊重其他团队成员的劳动成果,每个人不得将未通过单元测试的代码集成到系统
中。因此,每个人的代码质量必须过关。
核心做法:
·小规模,频繁的版本发布,短迭代周期。
·测试驱动开发(Test-driven development)。
·结对编程(Pair programming)。
·持续集成(Continuous integration)。
·每日站立会议(Daily stand-up meeting)。
·共同拥有代码Collative code ownership.·系统隐喻(System metaphor)。
SCRUM Scrum是一个敏捷开发框架,它由一个开发过程,几种角色以及一套规范的实施方法组成。它可以被运用于
软件开发,项目维护,也可以被用来作为一种管理敏捷项目的框架。
在Scrum中,产品需求被定义为产品需求积压(product backlogs)。产品需求积压可以是用户案例,独立的功能描述,技术要求等。所有的产品需求积压都是从一个简单的想法开始,并逐步被细化,直到可以被开
发的程度。
Scrum将开发过程分为多个Sprint周期,每个Sprint代表一个2-4周的开发周期,有固定的时间长度。首先,产品需求被分成不同的产品需求积压条目。然后,在Sprint计划会议(Sprint planning meeting)上,最重要或者是最具价值的产品需求积压被优先安排到下一个Sprint周期中。同时,在Sprint计划会上,将会预先估计所有已经分配到Sprint周期中的产品需求积压的工作量,并对每个条目进行设计和任务分配。在Sprint开发过程中,每天开发团队都会进行一次简短的Scrum会议(Daily Scrum Meeting)。会议上,每个团队成员需要汇报各自的进展情况,同时提出目前遇到的各种障碍。每个Sprint周期结束后,都会有一个可以被使用的系统交付给客户,并进行Sprint审查会议(Sprint review meeting)。审查会上,开发团队将会向客户或最终用户演示新的系统功能。同时,客户会提出意见以及一些需求变化。这些可以以新的产品需求积压的形式保留下来,并在随后的Sprint周期中得以实现。Sprint回顾会随后会总结上次Sprint周期中有哪些不足需要改进,以及有哪些值得肯定的方面。最后整个过程将从头开始,开始一个新的Sprint计划会议。
Scrum定义了4种主要的角色:
·产品拥有者(Product Owner):该角色负责产品的远景规划,平衡所有利益相关者(stakeholder)的利
益,确定不同的产品需求积压的优先级等。它是开发团队和客户或最终用户之间的联络点。
·利益相关者(Stakeholder):该角色与产品之间有直接或间接的利益关系,通常是客户或最终用户代表。
他们负责收集编写产品需求,审查项目成果等。
·Scrum专家(Scrum Master):Scrum专家负责指导开发团队进行Scrum开发与实践。它也是开发团
队与产品拥有者之间交流的联络点。
·团队成员(Team Member):即项目开发人员。
Scrum提供一个敏捷开发框架,其他许多敏捷方法都可以被集成到Scrum中。比如测试驱动开发(test-
driven development)和结对编程(pair programming)等都可以被整合到Scrum中。
精益开发(LEAN DEVELOPMENT)
精益软件开发模式是从丰田公司的产品开发方法中演化而来。它主要包括两个部分:一部分是核心思想及原
则,另外一部分由一些在相应的工具构成。
精益开发的核心思想是查明和消除浪费。在软件开发过程中,错误(bugs),没用的功能,等待以及其他任何对实现结果没有益处的东西都是浪费。浪费及其源头必须被分析查明,然后设法消除。精益开发的其它原则
包括:
·强调学习。软件开发过程是一个不断学习的过程。每个团队成员都需要从日常的失败,互动,交流以及信息
反馈中学习,不断改进所开发的产品和开发效率。
·在最后时刻做决定。这样可以避免在可能改变的事情上做无谓的努力,从而有效的避免浪费。
·用最快的速度交付用户。较短的迭代周期能够加速产品的开发及交付,加快交流,提高生产力。
·给团队自主权。激励团队并让所有团队成员自我管理始终是所有敏捷方法获得成功的基本因素之一。·诚信。确保整个系统正常工作,真正满足客户的需求是整个团队需要努力坚持的诚信和和对用户的承诺。·全局观。精益开发强调整体优化的系统。无论开发的组织还是被开发的产品,从整体上考虑优化比从各个局
部去优化更高效。
对于上述的每个原则,都有一些相应的实现工具。这些工具包括价值流图(Value Stream Mapping),基于集合的开发(set-based development),拉系统(pull system),排队论(queuing theory),等
等。
和其它敏捷方法相比,精益软件更重要的是不断完善开发过程的一种思维方式。因此,将精益模式与其他敏捷
开发模式一起使用将会取得很好的效果。
其它敏捷方法
动态系统开发方法(DSDM)是由快速应用程序开发(RAD)方法演变而来的敏捷开发模式。DSDM在普遍的敏捷价值和原则的基础上,定义了更加详细的流程,以涵盖更完整的项目生命周期。它们包括项目前期活动
(pre-project activities),项目可行性研究,功能建模,设计和开发,实施或部署,项目后期维护(post-project maintenance),等等。同时,每个过程都定义了诸如如何将每个功能模型转化为实际代码,如何将原型交付最终用户使用并审查,如何处理反馈信息等的详细步骤。因此,DSDM相比于其它敏捷
方法在过程上显得比较繁重。
特征驱动开发(FDD)是另一种敏捷开发方式,它将用户的功能需求划分成更小的功能特征,然后逐步地在每个迭代周期中开发实现这些产品特征。与DSDM方式一样,FDD仍然会在项目初期对整个项目做较大的规
划和建模,以获得对该系统的全面了解。但是相比DSDM来说,FDD在这些方面简捷了一些。
Crystal Clear是另一种敏捷方法。Crystal Clear更专注于人。相比于其他的敏捷方法,它可使人获得更大的解放。据称这种方法更适合于较小规模的开发小组(由2-8个人组成)和非关键项目。Crystal Clear定义了七种属性。前3个属性-频繁的交付(frequent delivery),渗透交流(osmotic communication),反思提高(reflective improvement)-反映出基本的敏捷开发做法和价值,如周期较短的迭代式开发,自我管理的开发团队和反馈带动增量发展等等。另外的4个属性分别是:个人安全(personal safety),集中
(focus),容易接触专家用户(easy access to expert users)和技术环境(technical
environment)。其中,容易接触专家用户实际就是敏捷方法中提到的客户持续参与,但Crystal Clear对此要求比较宽松。Crystal Clear也提供了一些通用的做法,比如,它提供了三种回顾分析的方法:访谈,问卷调查和工作组。Crystal Clear的过程也是相当简单,其中涉及短的迭代周期,日常会议及持续集成等。还有其他一些敏捷方法如敏捷统一过程(Agile Unified process),上下文驱动开发(Context Driven Development),Getting Real等。这些方法都是增量和迭代开发过程,并且重视人多过于整个过程。而各种敏捷方法的区别在于它们对敏捷的不同阐释和不同侧重。理解这些方法可以帮助我们从多个角度理解敏捷
开发,并且了解更多的最佳应用。
如何选择一种敏捷方法
选择一种合适的方法取决于多种因素。在做出决定之前,我们需要充分考虑以下这些方面:
·方法的复杂度。确保你的团队或组织能够应付这种复杂度。
·社区和业界支持。流行的方法可能并不是你最理想的选择,但流行的方法 至少有较多的社区及行业支持,可
以使你受益匪浅。
·实用工具。选择一种可以为你提供支持工具的方法。一个良好的软件工具可以帮助团队有效的处理日常工
作,促进团队协作,并减少管理成本。
·你目前的开发方式以及团队关于敏捷方法的认识程度。选择一些与你当前开发方式比较接近的敏捷方法将有
助于推动该方法的实施。
·你的团队规模。较小规模的团队最好从简单的方式入手。当然,这并不意味着你必须选择那些本身就比较简单的方法如Crystal Clear。你可以选择一些相对比较全面的方法,但从简单入手。当你的团队规模逐渐扩
大,再增加相应的细节。
·你不需要只遵从一种方法。你可以为团队选择一个主要的方法(如Scrum),然后从其他方法中借鉴对你的团队或组织有所帮助的其他方式加以整合。
敏捷总是在不断发展演变,因此,没有一个人能保证目前的敏捷方法都是正确的。每个采用敏捷开发的团队都
可以通过发现并形成自己的想法和最佳实践,对敏捷开发做出自己的贡献。
相关培训服务请查看:http:///services/training
1.SCRUM SCRUM?这个单词我以前没见过,所以我就不喜欢它,呵呵.SCRUM本义表示“混乱”,它包括
多个“怪异”的方法/过程名称。比如,SCRUM将开发过程分为30天的迭代周期,每个
迭代周期叫做一个Sprint(原意:冲啊!);每天有一个15分钟的短会,用来决定第二天的任务安排这样的短会就叫做scrum。
我不喜欢SCRUM的原因如下:
1)一个方法,搞出这么多名词,加重我们程序员的负担,不好;
2)SCRUM的迭代周期为30天,而且一个周期叫一个“冲”,那不是要累死我们程序员?
3)每天有一个15分钟的短会,唉,XX党的会多!
4)15分钟的短会叫“混乱”,那....,15分钟能结束吗?
5)SCRUM强调,开发者每天要向管理者报告项目进度,唉,我受不了了....2.Crystal Crystal根据项目规模和项目的重要性(如发射火箭的项目和一个“hello world”程序的重要性当然是不一样的)来区别项目,并赋以相应的方法,所以,crystal是方法的组合.相对于其它敏捷方法,Crystal强调软件开发流程的纪律性,所以,它比其它敏捷方法易
于使用,但它的生产率不如XP等其它敏捷方法.3.ASD(Adaptive Software Development)
ASD强调开发方法的适应性(Adaptive),这一思想来源于复杂系统的混沌理论(这个
名字大家应该都听说过了,炒股的用的很多,呵呵)。ASD不象其他方法那样有很多具体的实践做法,它更侧重于理论,因为它的作者就是搞理论出身的。
4.FDD FDD(Feature Driven Development)定义了5个流程,分别是Develop an Overall Model、Build a Features List、Plan by Feature、Design by Feature和Build by Feature。
前3个流程是在项目开始就进行的,其实总体相当于我们现在的系统分析;后两个则出
现在每次迭代周期中,FDD的迭代周期是两周,相当于我们现在的设计/编码/测试。
开发人员被归为两种,一种是主程序员,另一种是class所有者。主程序员不作具体的编程工作,但要负责将Feature和Class对应起来,并充当开发协调者、设计者、技术
支持和指导者等;class所有者则进行实际的编程。我认为这样的划分对国内的软件开
发情况不合适,因为,真正达到主程序员水平的人,太少了!
对于ASD和FDD,国内介绍的还是比较多的.5.XP
第五篇:.NET开发年终总结
公司企业个人工作总结报告
月工作总结范例:
两周的时间很快就过去了,来公司上班仅仅8天的时间,在公司领导和各部门同事的配合与协助下,我基本上完成了自己岗位上的各项职责,下面我将就自己的工作状况、感想等做一个简要的总结。
一、主要工作情况
1、参与一比多产品服务中心站点的改版
一共参与了29幅页面的页面示意图的制作,其中有两幅是试画,在进行纠正之后,用了两天的时间完成了余下的27幅,通过制作页面示意图,对visio这一图形制作工具进行了全面的了解与熟悉。
2、建立一比多免费商铺
通过建立的一比多免费商铺对一比多平台进行了解,尤其是一比多的商铺管理,通过与慧聪和阿里巴巴的比较,来找到一比多的优势与不足,提交了一份关于三方产品对比的分析报告。
3、尝试开发后台求购信息录入页面
后台求购信息页面以产品的前台求购信息页面为参考,同事参照了阿里巴巴和慧聪的前台求购信息录入页面,收集
了后台求购信息录入工作人员的意见,将其中不需要用到的地方删减,有利于加快后台部门求购信息录入的速度。
4、部门其他的例行工作任务
在完成以上三个主要任务的同时还参与了部门的其它例行工作任务,包括产品服务中心页面错误之处的维护修改申请,整理网络营销推广的方法等。
二、工作中出现的问题
1、工作过程中由于对问题没有听清楚而导致有遗
漏的问题存在,不过幸好问题不大,没有造成什么巨大的影响;
2、工作中由于对业务不够熟练、产品和流程不够熟
悉,花了很多的时间来做这方面的了解,浪费了一些时间。这短短8天的工作时间就算是我8月份的工作总结了,虽说只有8天的工作时间,但凭着这段时间所做的这些工作任务,以及同事和领导的帮助,让我成长了不少,我相信,在以后的工作中我会做的越来越好、越来越出色的,请公司放心。xxx部:xxx 日期
工作总结范文
在这一年里,凭借前几年的蓄势,杭萧钢构不但步入了高速发展的快车道,实现了更快的效益增长,而且成功地实现公司股票在上海证券交易所上市。从此,一个杭萧钢构以崭新姿态展现在世人面前,一个更具朝气和活力的、以维护股东利益为己任的新杭萧诞生了。
公司上市后,管理水平必将大幅度提高,这不仅仅是市场竞争的外在要求,更是自身发展壮大的内在要求。对于市场部来说,全面提升管理水平,与公司同步发展,既是一种压力,又是一种动力。为了完成公司年合同额三十亿的总体经营管理目标,市场部特制订年工作计划如下。
一、信息网络管理 1建立直接领导关系
市场部是负责公司信息网络建设与维护、信息收集处理工作的职能部门,接受营销副总经理的领导。市场部信息管理员与各区域市场开发助理之间是一种直接领导关系,即在信息网络建设、维护、信息处理、考核方面对市场开发助理直接进行指导和指挥,并承担信息网络工作的领导责任。
构架新型组织机构 3增加人员配置:
(1)信息管理员:市场部设专职信息管理员3名,分管不同区域,不再兼任其它工作。
()市场开发助理:浙江省六个办事处共设市场开发助理两名,其它各办事处所辖区域均设市场开发助理一名。4强化人员素质培训
春节前完成对各区域的市场部信息管理员和市场开发助理的招聘和培训,使年新的管理制度实施过程中市场部在人员素质方面有充分的保障。认真选择和慎重录用市场开发助理,切勿滥竽充数。
5加大人员考核力度
在人员配置、资源保证、业绩考核等方面对信息网络建立和维护作出实施细则规定,从制度上对此项工作作出保证。建
立市场信息管理员定期巡回分管区域指导信息管理工作的考核制度,并根据各区域实际情况和存在的问题,有针对性地加以分析和研究,以督促其在短期内按规定建立和健全信息管理的工作。
6动态管理市场网络
市场开发助理与信息管理员根据信息员提供的信息数量(以个为单位)、项目规模、信息达成率、发展下级信息员数量四项指标对信息网络成员进行定期的动态评估。在分析信息员/单位的分类的基础上,信息管理员和市场开发助理应结合信息员的背景资料进行细致地分析,确定其通过帮助后业绩增长的可能性。进一步加强信息的管理,在信息的完整性、及时性、有效性和保密性等方面做好比上一年更好。
加强市场调研,以各区域信息成员/单位提供的信息量和公司在各区域的业务进展情况,将以专人对各区域钢结构业务的发展现状和潜在的发展趋势,进行充分的市场调研。通过调研获取第一手资料,为公司在各区域的机构设置各趋合理和公司在开拓新的市场方面作好参谋。
二、品牌推广篇二:2016年暑期学校机房研发工作实习总结 2016年暑期学校机房研发工作实习总结
读了三年的大学,然而大多数人对本专业的认识还是寥寥无几,在编程与软件测试周围缠绕不定,在大二期末学院曾要求我们做一个关于计算机行业前景研究的报告,但由于当时所学知识涉及本专业知识不多,所看到的东西与本专业根本就很难联系起来,在很多同学心里面对于本专业一直很茫然。
什么是计算机科学与技术?对于我们所选的asp.net主要从事什么样的工作?本专业前途如何?带着这些问题,我们参加了这次的实习。本次实习在主管马楠老师、瞿浩、杜强和宋林四个老师带领下进行,计算机科学与技术总共四个班,110几人参加实习,我们小班四十多个人,预定为三个礼拜完成。由于所学专业的特点,我们实习的地点定为学校,环境其实挺好,机房可以二十四小时提供空调,而且只要学生愿意学习,老师都会在休息时间出现在机房。又遇暑假,其他年级的同学都已离开学校,人少就免了打扰,清静的很,真是学习的好机会。
通过这次实习,我对计算机专业在行业实践中的工作对象、面临问题及解决办法有了一个较为全面的理解。巩固专业知识的同时也增加了行业责任.本文由|方案范#文库为;您搜集整.理感,实习的日子里也加深了同学友谊,锻炼了团队精神。现将实习的个人感想如下:
在这三个礼拜的时间中,我复习了曾经学过的编程语言c#,让我对c#在认识的基础上,又具备了用c#开发windows应用程序和web应用程序的能力。现在我再去理解.net和c#,就会发现.net是个强大的新平台,而c#则是该平台下最佳的开发语言。我还系统的学习了.net编程,并努力完成我此次实习的任务----商品进销存系统设计。系统采用asp.net,开发工具为sqlserver2016,开发语言为c#。这个系统是针对中国中小企业开发的进销存管理软件,全面提高商业企业的管理效率,高效管理库存,提高销售力度,为企业增加更大利润。使用简单,最大程度的简化了财务管理软件的操作复杂性,使企业无需学习,即可自己轻松上手,不但界面简单易于操作,而且通过此系统您可以知道您每天、每月、每年的销售额、利润,统计所有的应收款、应付款,知道您的哪个分公司、门市、柜台、商品、业务员赚了多少钱,库存商品的价值,等等!有了此软件您就可以轻轻松松的打理您的企业,获得更多自由时间。还有此软件数据流比较大,数据库中表有五个,可光视图就建了十来个,我们小组经过三个礼拜的开发时间完成了该系统,也受到了老师的肯定。在此次的实习中我们小组合理分配时间,恰当的调用人手,时刻争当速度最快,界面最整洁的小组,我在其中主要完成了详细设计文档和测试设计文档的编写,还做了其中几个页面,同时协助同事进行开发,现在能熟练进行开发环境中各个控件的使用。
我们小组的名字为powerbeggar,顾名思义,power有力量的(力量来源于团结)故寓意我们小组成员的团结;beggar乞丐,powerbeggar即:有力量的乞丐!但此乞丐非彼乞丐!传统意义上的的乞丐是叫花,但是,我们觉得:理论与实际有很大的差距,课内与课外有很大的区别,基于这一点,我们认为我们很缺乏实战经验
==justlike—beggar,与此同时,也暗含了我们对于知识的渴求;另外,还隐含了我们在这个过程中不怕苦不怕累的艰苦奋斗的革命精神!指导老师们在整个实习过程中尽职尽责,对保证实习质量起到了重要作用。实习开始时,老师们深入学生的生活和学习环境,阐明实习大纲及实习计划内容,明确实习目的和要求。实习过程中,结合实习单位的具体情况,帮助学生学会具体地分析问题、解决问题,学会深化专业知识,用专业知识指导实践,指导学生做好具体工作;在业务不多的实习点,引导学生找事做,挖掘一定的实践经验;检查学生实习工作日记,掌握实习情况,指导工作及时有效;督促学生认真完成实习报告。指导老师平均每周至少与学生交流一次。基本达到了及时发现问题,解决问题,提高实习质量的目的。实习单位的指导老师认真负责。不仅指导具体工作,还无私的介绍自己的工作与社会经验。
在此次实习过程中,我们每个人都把自己当成是公司研发部的一员,我们每天坚持按时上下班,甚至有时还会早到或者加班,合理的安排自己的工作时间,在指导老师的安排下劲量做到劳逸结合,时而做个小游戏放松我们自己的大脑,随后便尽快让大脑做到高速运转,我对自己技术上的特点作一个概括。熟练的编写详细设计和测试设计文档;努力学习asp.net,asp,javascript编程;熟练掌握sqlserver2016,复习并掌握了简单的sql语句;熟悉windows应用系统的开发,开发语言为c#。
最后总结一下我在此次实习过程中的收获主要有四个方面:一是通过直接参与企业的运作过程,学到了实践知识,同时进一步加深了对理论知识的理解,使理论与实践知识都有所提高,圆满地完成了此次实习的实践任务。二是提高了实际工作能力,为就业和将来的工作取得了一些宝贵的实践经验。三是在实习过程中成立一个小团队,彼此之间互相沟通,互相帮助,为了我们的目标而努力,让我看到了大家对于工作的热情,还有每个人的工作能力。四是为毕业论文积累了素材和资料。篇三:大洋房地产公司年终总结报告
大洋房地产公司年终总结报告
今年,我公司在市委、市政府和建设局的正确领导和支持下,公司由原有的管理理念转变为变则通,通则久的管理方针,督促全体干部职工进一步解放思想,转变观念,以新的思路解决工作中遇到的新问题。公司全体干部职工团结一致,扎实苦干,在新的管理方针的指引下,积极向上,开拓进取,各项工作都取得了较好的成绩,圆满地完成了年初制定的各项工作目标。现将全年的工作情况总结如下:
一、各项工作的完成情况
1、经营指标的完成情况: 全年新开发建筑面积约1.5万m2 ,其中商业街占7300m2,竣工楼房3栋(33#、34#、35#),竣工面积9000m2,完成建设投资约800万元,实现销售收入1062万元,销售面积9327m2。续贷900万元,累计贷款约1100万元。减少应付工程款350万元。(来自:)存货房屋总计约9300m2,其中1-6区房屋面积为4734m2,商业街房屋面积为4566m2,存货约为1117万元,应收款243万元。公司机关人员工资约40万元,银行利息约90万元,办公费30万元,招待费17万元,小区物业公司维修费21万元,总费用约每年200万元。本公司经营状况较往年有所好转,望全体职工继续努力工作,再接再励。
2、小区的建设情况: 今年大洋园小区新开住宅楼3栋,建筑面积1.5万平方米,收尾工程8000平方米。在工程建设中,一是抓工程质量,二是抓工程进度,三是抓安全文明施工。
大洋园商业街建设项目,是我公司领导班子经过慎重、周密考察后决定建设的,位于济阳新老城结合部,十中以东,与兴化步行街互应,建成后将成为济阳商业领域又一热卖点。规划楼层为二至三层的独立单体楼房,建筑面积1万平方米,建设投资约800万元,又可根据用户需求在南侧自行按照统一规划建设,满足不同层次的消费者。现已全面竣工并可以使用。
3、房屋销售经营情况: 针对当前我县住房市场供大于求的实际,公司一是积极调整销售价格,尽最大限度降低售价;二是降低工程建设成本;三是应客户需求,能甩项甩项处理,由住户自行设计;同时,积极利用宣传单、宣传牌、电视台、报纸、网络等多种形式进行宣传,宣传小区优越的位置、良好的物业管理及优质的售后服务,提高了知名度和社会信誉。针对顶层楼房销售难的问题,公司经研究决定降低售价,优惠于内部职工,既解决了部分职工住房困难,又有利于资金的回收。全年销售房屋120套,销售面积9327平方米,销售收入1062万元,销售率85%。
4、宣传措施的转型情况: 现今社会是网络信息迅速发展的科技时代,公司也充分的认识到了这点,所以积极开拓新思路。今年通过办公室人员的努力,初步架设完成了自己的网站系统,全面立体的展示公司各方面的发展和业绩,既节
约了宣传经费的重复投入,又扩大了公司的社会效益和影响力,对于公司发展信息的及时传递和网络信息的准确接受提供了便利。
5、党务工作: 在新的党支部的所有全体成员以及新一任的支部书记的努力下,建立健全了党内各项工作制度。年内发展预备党员2名,转正2名,新培养入党积极分子3名,党支部的各项工作逐步完善。
6、物业管理情况: 物业管理公司是一个自主经营自负盈亏的企业,但多年来一直没有摆脱围绕总公司吃饭的不利局面。去年总公司投入近30万元的维修费,(来自:)今年公司又投入了20余万元的维修费,锅炉、管道年久失修,公司年年往里投钱,收取的费用不够开支,造成连年亏损,入不敷出。
今年,为使广大用户过一个温暖舒适的冬天,总公司今年9月下旬就对锅炉管道维修进行了部署,成立了专门领导班子,在人力、物力、财力上给予了物业公司最大限度的支持。并调整了领导班子,由公司副总袁树忠亲自抓,并印发了《致雅居园小区用户一封信》,为使广大居民过一个温暖祥和的冬天,说明情况,让居民知道,因物价因素、煤炭价格上涨,今年的取暖费价格较往年有所提高,敬请广大用户予以理解和支持。
物业公司是自负盈亏的企业,没有多余的财力来照顾大家,在取消福利取暖的今天,只能取之于民,用之于民,完全是一种市场行为,因此希望各区居民要顾全大局,如果你居住的一家停暖,将给周围住户造成很
大影响,使整体热源受到很大损失,也影响到采暖设施的热平衡。为了广大居民的利益和不影响物业公司的管理,欢迎您积极地参与采暖。作为物业公司的主管单位-开发公司,在今后的冬季供暖工作中,将进一步深化企业改革,加强内部管理,积极消化和克服种种困难,搞好设备维修和基础设施建设,最大限度地满足广大居民的需求,为今后取暖做出更大的努力。
二、存在的问题
一是年开发总量少,建设规模小,不能适应新形势的需要;二是资金回笼慢,造成公司经营困难,难以开展大的经营活动;三是由于国家土地政策至今仍在冻结,公司没有土地资源来发展业务;四是企业改革力度不够,真正形成激励机制的目标还没有实现;五是小区物业管理人员素质水平和业务技能不高,与居民之间存在这样那样的矛盾,经营状况不佳;六是各分公司的开拓市场意识还不强,围着公司转的经营模式仍没有改观;七是各项工作制度不健全,管理水平不高;八是员工的思想还不够解放,始终未能真正认识到变则通,通则久的管理方针的可行性和持续性,思想观念保守。三、二oo六年工作计划和发展战略目标
1、解放思想,转变观念,认清形势(1)定位好职工的公司形象位置。
首先给予全体干部职工一个称号公司形象代言人,职工个人在公司外面的言行代表着本公司全体,直接影响着公司的形象和声誉。因此应从长远利益和整体利益出发,采取多种方法树立公司的自豪感,产生
公司的向心力,全体职工要自觉地维护公司的声誉和利益,让员工随时感觉到自己的一切行为都代表着公司,让员工们真正认识到公司主人翁的重要性所在,时刻以此来约束自己的行为,来达到改变思想的目的,正所谓行为思动就是这个道理。(2)认清企业的市场形势,把握好时机寻求发展。
商场如战场,当今社会要想跟上时代的发展,要想有立足之地,要想在激烈的市场竞争中站稳脚步,就必须做到知己知彼,所以明年我公司要把市场形势和发展动态明朗化,通过网络信息的广泛搜集充分掌握好市场发展前景,并随时传递给每一位职工,让其真正改变思想观念,充分发挥好自己的职责和能力。
(3)没有了铁饭碗,擦好自己的吃饭碗。
大家要明白一个道理:我们搞的是开发公司,不是保险公司,铁饭碗哪里都没有了。为什么要加强学习,提高认识,认清形式,要努力实现在建设上有创新。新一轮解放思想、加快发展的热潮正在全县迅速兴起。聚精会神搞建设,一心一意谋发展。务求做到发展要有新思路,改革要有新突破,开放要有新局面,工作要有新举措。要牢固树立市场观念和精品意识,对每一项建设项目做到精心策划,精心施工,不断提高城项目的工程质量、功能质量和艺术水平。这也就是擦好自己的吃饭碗。
(4)党的思想政治工作决不是可有可无,无所作为,而是必不可少,大有作为的。