DataTable数据检索的性能分析(转寒江独钓)

我们知道在.NET平台上有很多种数据存储,检索解决方案-ADO.NET Entity Framework,ASP.NET Dynamic Data,XML, NHibernate,LINQ to SQL 等等,但是由于一些原因,如平台限制,比如说必须基于.NET Framework2.0及以下平台;遗留的或者第三方数据接口采用的就是DataTable等等,仍然需要使用DataTable作为数据存储结构。另一方面DataTable比较容易使用,一些数据访问的接口可能直接采用了DataTable结构。在使用DataTable进行数据检索的时候,有一些需要注意的地方,这些地方会严重的影响对数据的检索效率。

    本人最近工作中需要对大量的DataTable进行拼接。接口的数据是以DataSet然后里面放DataTable的方式提供的,暂不提是否合理,同时进行多个请求的时,服务端会返回一个DataSet,其中包含每个请求的结果DataTable,这些DataTable中有一列相当于”关键字”列。现在需要按照这个关键字,将这些DataTable中的列合并到一个DataTable,然后展现到界面上来。

    最开始,我使用的是DataTable的Select方法来循环遍历拼接实现的,发现很慢,于是总结了一下对DataTable进行查询等操作的一些经验,和大家分享。

一 场景

    为了简化问题,有两张DataTable,名为表A,表B,字段分别为

     表A,存储股票的最高价信息,        表B存储股票最低价信息

     SecurityCode    High                  SecurityCode    Low

     000001.SZ       20                     000001.SZ      18.5

     000002.SZ       26                     000002.SZ       56

    现在需要,将这两张表拼接到一张表中,这张表有三列字段,SecurityCode High Low,之前采用的方法是,新建一张含有这三个字段的DataTable 表C,然后复制Security字段,然后遍历另外两张表,对其采用Select方法查找对应的SecurityCode,然后复制给C中对应字段。发现效率很慢,问题出现在Select方法上,于是需要进行优化。

二 DataTable的查询效率

    DataTable提供了两个查询数据的接口,DataTable.Select和DataTable.Rows.Find方法。

    DataTable的Select方法通过传入一系列条件,然后返回一个DataRow[ ]类型的数据,他需要遍历整个表,然后挨个匹配条件,然后返回所有匹配的值。很显然在策略上,之前的DataTable拼接采用Select方法存在问题,因为我们只需要查找匹配上的一条记录即可。

    DataTable.Rows 的Find查找第一个匹配上的唯一一条记录。在指定了主键的基础上,查找会采用二叉树的方式查找,效率高。要创建主键,需要指定DataTable的PrimaryKey字段如下:

dtA.PrimaryKey = new DataColumn[] { dtA.Columns["SecurityCode"] };

当然,创建主键会增加时间消耗,这也分为在数据填充前创建和数据填充后创建。在数据量大的情况下,创建主键的消耗是需要考虑进去的。下面的图中显示了在填充数据之前创建主键,之后创建主键,以及创建Dictionary所需的时间。可以看到:

ArraySize

PreIndex Creation Time

PostIndex Creation Time

Dictionary Creation Time

10

0

0

0

50

0

0

0

100

1

0

0

500

6

1

0

1000

15

2

0

5000

107

16

2

10000

261

42

5

50000

1727

271

31

100000

3525

544

47

500000

20209

2895

240

1000000

43382

5919

517

    作图如下:

DataTable数据检索的性能分析(转寒江独钓)

从上图可以得到:

  1. 在填充数据之前创建主键,然后填充数据,比填充数据完之后创建主键消耗的时间要多。这是由于,创建主键后,再向其中添加数据,会导致需要重新生成索引,这和数据库中,不适合在频繁变动的字段上创建主键的原理是一样的。在我的笔记本 (Win7 32bit,CPU T6600 2.0GHZ,RAM 2GB)上,为100万条记录的DataTable创建索引大约需要5秒钟,所以在数据量大的情况下,需要考虑索引的创建时间。
  2. 创建DataTable然后创建主键与直接创建和该DataTable相同的Dictionary结构相比,创建Dictionary所需要的时间要少的多,而且几乎不随着记录条数规模的变大而变大。

    创建完成之后,下面来测试几种情况下的DataTable的检索效率。为此,在建立主键和没有建立索引的条件下,测试了在不同规模下 DataTable.Select, DataTable.Rows.Find 的查询速度,由于在DataTable比较小的时候,时间不能很好的显示,所以测试采用的单位是StopWatch的Tick数。每个方法在数据规模不同的情况下,各执行了10次,然后取平均值,结果如下:

ArraySize Dictionary Create Dictionary Search Table Select Indexed Table Select Table Rows Find LINQ
10 13 3 40 25 8 16
50 27 2 69 37 8 27
100 51 3 112 38 9 39
500 210 3 589 51 11 155
1000 461 4 1175 60 14 328
5000 2264 14 8412 85 17 1540
10000 6235 7 16806 99 20 3354
50000 23768 8 150133 138 26 15824
100000 49133 7 259794 147 26 31525
500000 252103 51 1547935 181 30 158317
1000000 494647 9 2736616 209 30 315716

作图如下:

DataTable数据检索的性能分析(转寒江独钓)

可以看到:

  1. 在没有创建主键的条件下,对DataTable执行Select操作时比较低效的。在建立主键之后,仅对主键所在列执行Select操作,速度提高了很多,这种差距在数据量大的情况下尤其明显,在集合大小规模为1000时,该差异达到了近20倍。
  2. LINQ对DataTable的查询效率比DataTale.Select方法要高,但是仍然比DataTable.Rows.Find方法效率要低。
  3. 在对主键进行唯一性查找时,我们应该使用DataTable.Rows.Find操作,在DataTable建立主键,并且仅对主键进行操作的情况下,Find方法会比Select方法快3-6倍,这可能是由于Select方法需要对里面的过滤字符串进行解析及判断。因为Select方法可以接受多个条件的查询以及以一些比较复杂的表达式,处理及解析可能需要耗费一些时间。并且在一般条件下Select是完全搜索,即查找整个集合找到所有满足条件的记录。而Find方法则仅对主键字段进行检索,如果没有设置主键,那么调用Find方法就会报错。
  4. 采用Dictionary来代替DataTable结构来进行检索,能达到最快的速度,且几乎不受规模的影响,但是在数据量较大的情况下,将DataTable转换为对应的Dictionary结构可能需要花费时间,如果操作频繁,诸如在进行多个DataTable基于关键字进行拼接的情况下,对目标DataTable使用Dictionary<String,DataRow> 的方式进行存储,能够使用ContainsKey的基于Hash的方式对关键字进行查找,这能极大地提高效率。并且在DataTable列有重复字段,不能建立主键的情况下,可以采用Dictionary<string,List<DataRow>>能够解决DataTable无法创建主键,从而导致查找性能下降的问题。

 

三 实施效果

    基于上面的分析,在实际中的工作中,替换了Select方法,创建了一个类型为Dictionary<String,DataRow>的包含目标合并后DataTable对象的所有行的结构C,其中关键字为SecurityCode,DataRow为包含SecurityCode,High,Low三列数据的行。在合并的时候,直接遍历表A的所有行,然后判断在C中是否包含该行中的SecurityCode,如果包含,取出,直接赋值。然后遍历表B。整个过程使得DataTable合并的效率至少提高了10倍。

四 结语

    本文简要介绍了DataTable中检索数据的两种方法,DataTable.Select 和DataTable.Rows.Find方法。在测试方法的执行效率之前介绍了如何为DataTable设置主键,并比较了在数据填充之前和数据填充之后设置主键花费的时间,结果表明,在数据填充完成之后,设置主键要比在填充数据之前设置主键效率要高的多。设置主键之后,比较了在有无主键的情况下,DataTable.Select 方法在仅对主键字段进行过滤时的性能,结果表明,在仅对主键进行检索时,设置主键之后使用DataTable.Select 方法会比没有主键的情况下的检索速度会快非常多。在相同条件下,如果仅需要查找某一条记录,使用DataTable.Rows.Find会比DataTable.Select快很多。在某些需要频繁操作DataTable查询的时候,要避免在循环体内调用DataTable.Select方法,采用将DataTable转换为等价的Dictionary结构,能够有效解决由于键值重复导致不能创建主键的问题并且Dicitonary的采用哈希表的方式查找能够极大地提高查询效率。

    点击此处下载本文测试用例及代码,希望对您在对DataTable进行检索操作时,如何提高效率能够带来一点儿帮助。

    注:个人认为若DataTable设值主键且仅查找主键,使用后设置主键方式比Dictionary速度要快。

Activity生命周期

Activity生命周期共7种状态,每种状态完成不同使命。生命周期如下图所示:

Activity生命周期

执行顺序

函数名

功能

调用次数

1

onCreate

系统初始化函数,用来完成Activity的初始化工作。比如获取界面控件句柄、关联Activity对应的视图文件 、获取数据库连接等。

一次

2

onStart

绘制用户界面并在屏幕上预以显示,但用界面不可操作。

多次

3

Activity running

运行状态,界面既可见又可操作

多次

4

onResume

用来执行onPause方法后的恢复操作,界面进入既可见又可操作的阶段 。  

多次

5

onPause

保存操作状态,界面进入不可操作状态,但用户界面依然可见。

一次

6

onStop

释放系统数据但系统资源并没真正销毁,界面就不可见状态。

多次

7

onDestroy 

销毁系统资源。

多次

 

 

js压缩工具(转载)

怎么压缩Js?为什么要压缩Javascript? Javascript compressed/crunched
开发Ajax除了自己要写js代码外,同样也免不了要使用其它第三方js库,是否该为JavaScript减肥?
当你提高了用户体验,做出了很绚丽的效果而欣喜的时候,是否想过优化一下JS的效率,比如微软的live,其中的js做了压缩处理。JS的速度分为两种,JS下载速度和Js执行速度。

今天就先来说说JS下载速度。要想js的下载速度快,就需要尽量减小js文件的大小。

两种Js压缩工具(Javascript压缩工具)

Javascript compressed – YUI Compressor

According to Yahoo!’s Exceptional Performance Team, 40% to 60% of Yahoo!’s users have an empty cache experience and about 20% of all page views are done with an empty cache。

The goal of JavaScript and CSS minification is always to preserve the operational qualities of the code while reducing its overall byte footprint (both in raw terms and after gzipping, as most JavaScript and CSS served from production web servers is gzipped as part of the HTTP protocol). The YUI Compressor is JavaScript minifier designed to be 100% safe and yield a higher compression ratio than most other tools. Tests on the YUI Library have shown savings of over 20% compared to JSMin (becoming 10% after HTTP compression). Starting with version 2.0, the YUI Compressor is also able to compress CSS files by using a port of Isaac Schlueter’s regular-expression-based CSS minifier。

http://developer.yahoo.com/yui/compressor/

Download the YUI Compressor. 
http://www.julienlecomte.net/yuicompressor/

YUI Compressor最新版本下载 – YUI Compressor 2.4.1下载地址:
http://www.julienlecomte.net/yuicompressor/yuicompressor-2.4.1.zip

JS和CSS压缩工具图形界面版本下载地址
淘宝团队对YUICompressor做了层简单的封装,称之为TBCompressor.

http://lifesinger.org/blog/wp-content/uploads/2008/10/TBCompressor_v2.4.zip

淘宝是怎么压缩js和css的,淘宝使用的就是YUI Compressor
目前Jquery从1.3版本开始也使用YUICompressor

引用
The YUI Compressor is a JavaScript compressor which, in addition to removing comments and white-spaces, obfuscates local variables using the smallest possible variable name. This obfuscation is safe, even when using constructs such as ‘eval’ or ‘with’ (although the compression is not optimal is those cases) Compared to jsmin, the average savings is around 20%.
The YUI Compressor is also able to safely compress CSS files. The decision on which compressor is being used is made on the file extension (js or css)




Javascript compressed – ESC Introduction 

这里我们可以使用一个工具ESC(ECMAScript cruncher)来帮我们完成这个工作,不过这个工具只能在Windows下使用。到http://www.saltstorm.net/depo/esc/introduction.wbm?pod=js下载ESC.zip,解压后看看它的帮助文档。很简单。

ESC is an ECMAScript pre-processor written in JScript, enabling an unlimited number of external scripts to be compressed/crunched into supertight, bandwidth-optimized packages. Featuring several compression-techniques such as comment removal, whitespace stripping, newline stripping and variable substitution ESC can reduce the overall size of your code with up to ~45%. Single, multiple scripts and even directories with scripts can be merged together at the compression level you decide. The processed output can later be appended or written to a file, or piped to another application for further processing via STDOUT. 
  
ESC do NOT support crunching of inline scripts. So any attempt passing HTML, ASP, JSP, PHP or other equivalent documents to ESC is done at your own risk.  
  
ESC supports four levels of compression, where a higher level equals higher compression. Beware though that levels >2 requires your code to be syntaxically perfect or ESC will punish you by producing a broken and useless output.  
  
The compression ratio should hit around 25% using the default compression level on a vanilla looking script, but results as high as ~45% can be achieved depending on the script’s design / your style of writing code.  
  
压缩级别分为5种,从0到4

Level 0 :: No compression

Level 1 :: Comment removal

Level 2 :: Whitespace removal

Level 3 :: Newline removal

Level 4 :: Variable substitution

在WINDOWS命令行下执行

cscript ESC.wsf -ow menu2.js menu.js将会把menu.js按照js压缩级别2来压缩(默认js压缩级别为2)为menu2.js

cscript ESC.wsf -l 3 -ow menu3.js menu.js将会把menu.js按照js压缩级别3来压缩为menu3.js

需要注意的是,js压缩级别4会把变量名修改,如果你的js中用到了全局变量或者类的话,就不能使用该压缩级别了,否则其它使用你的js的文件可能会无法正常运行。

试了一下,把yui的menu.js压缩了一下,对应的级别和压缩率分别如下:

js压缩级别1:压缩率44.41%

js压缩级别2:压缩率62.82%

js压缩级别1:压缩率64.93%

原来130多K的js文件压缩后也就40多K,看来还是挺有用处的。

另外还有一个小工具jsmin也可以压缩,不过没有ESC的level选项,看了一下好像压缩效果类似于ESC的level3.济南大学的一些老师写了个jsmin的图形界面程序JsMinGUI,使用起来更加方便。:-)

Dojo项目组也提供了一个工具,shrinksafe可以通过http://alex.dojotoolkit.org/shrinksafe/在线的上传要压缩的文件,处理完毕后可以保存到本地,另外shrinksafe还提供了一个本地运行的版本,需要jre1.4的支持。

Ps:对于一些压缩的代码,在阅读时可以用JavaScript Code Improver来进行格式化。看看它主页上的一个例子:
javascript压缩代码示例
原来的代码:

<script language=”JavaScript”>var i=0,s=””,k=0;function foo(){for(j=0;j<10;j++){for(i=0;i<10;i++){s=”string1″;k=Math.floor(Math.random()*10);}for(i=20;i>9;i–){s=”string2″;k=I;}}}</script>



格式化后:

<script language=”JavaScript”>
var I = 0, s = “”, k = 0;
function foo()
{
for(j = 0; j < 10; j++) 
{
for(I = 0; I < 10; i++) 
{
s = “string1″;
k = Math.floor( Math.random()*10 );
}
for(I = 20; I > 9; i–) 
{
s = “string2″;
k = I;
}
}
}
</script>




js压缩,巨NB的dHTML特效. 来自:
http://hometown.aol.de/_ht_a/memtronic/MemTronic_CruncherCompressor_v09g.html

JS压缩示例样本:JS压缩示例样本


更多的JS压缩器以及混淆器

In terms of code minification, the most widely used tools to minify JavaScript code are Douglas Crockford’s JSMIN, the Dojo compressor and Dean Edwards’ Packer:

Douglas Crockford’s JSMIN
http://crockford.com/javascript/jsmin

the Dojo compressor
http://dojotoolkit.org/docs/shrinksafe

Dean Edwards’ Packer
http://dean.edwards.name/download/

http://dean.edwards.name/packer/   在线Js压缩
A Online JavaScript Compressor/Obfuscator version 2.0.2
Also available as a .NET application
开源下载:
http://dean.edwards.name/download/#packer
JS压缩器帮助:http://dean.edwards.name/packer/usage/
http://dean.edwards.name/packer/usage/sample.html

http://hometown.aol.de/_ht_a/memtronic/

JavaScript Compressor/Obfuscator Demo:
http://www.brainjar.com/js/crunch/demo.html 

JavaScript Code Improver:
JavaScript Code Improver Download


前面提到的Javascript压缩,都是采用删除注释,删除多余空格,替换字符等方式进行的,还有一种通过服务器的配置来实现Js静态压缩的方法:
关于JavaScript的gzip静态压缩方法
传统的JS压缩(删除注释,删除多余空格等)提供的压缩率有时还是不尽不意,幸亏现在的浏览器都支持压缩传输(通过设置http header的Content-Encoding=gzip),可以通过服务器的配置(如apache)为你的js提供压缩传输,或是appfuse中使用的GZipFilter使tomcat也提供这种能力

现在的问题是这种动态的压缩会导致服务器CPU占用率过高,现在我想到的解决辨法是通过提供静态压缩(就是将js预先通过gzip.exe压缩好)

一.下面描述在tomcat中的应用

1.将prototype.js通过gzip.exe压缩保存成prototype.gzjs 
2.设置header,我编写了一个简单的AddHeadersFilter来将所有以gzjs结尾的文件增加设置header Content-Encoding=gzip 
web.xml中的配置 

<filter>  
     <filter-name>AddHeaderFilter</filter-name>  
     <filter-class>  
         badqiu.web.filter.AddHeaderFilter   
     </filter-class>  
     <init-param>  
         <param-name>headers</param-name>  
         <param-value>Content-Encoding=gzip</param-value>  
     </init-param>  
</filter>  
  
<filter-mapping>  
     <filter-name>AddHeaderFilter</filter-name>  
     <url-pattern>*.gzjs</url-pattern>  
</filter-mapping>



测试prototype.js是否正常的代码 

<html>  
<head>  
<!– type=”text/javascript”不可少,有的浏览器缺少这个不能运行 –>  
<script src=”prototype.gzjs” type=”text/javascript”></script>  
</head>  
<body >  
     <input id=”username” name=”username” value=”badqiu”/><br />  
     <input id=”email” value=”badqiu@gmail.com”/>  
<script>  
     <!– 测试prototype的方法是否正常–>  
     alert($F(‘username’))   
</script>  
</body>  
</html>



在Apache httpd中可以直接通过在httpd.conf增加AddEncoding x-gzip .gzjs来映射.gzjs文件的header

二.相关压缩率数据 
1. prototype.js 1.5.0_rc0原始大小56KB,未经任何处理直接使用gzip压缩为12KB,总压缩率79% 
2. 通过js压缩工具压缩过的protytype.js为20KB,使用gzip压缩为10KB,总压缩率为83% 
3. 实际项目中的多个js合并成的文件 439KB,直接通过gzip压缩为85KB,总压缩率81% 
4. 439KB经过js压缩为165KB,再经过gzip压缩为65KB,总压缩率86%

基本上你都可以忽略js压缩工具的压缩率,直接使用gzip压缩

gzip下载地址 http://www.gzip.org 
tomcat的压缩配置示例下载地址: 
http://www.blogjava.net/Files/badqiu/gziptest.rar

其主要是利用服务器自带的动态压缩功能 传输时压缩数据流.

Ajax与系列精华Javascript库(Modello)
广告图片轮显-广告图片轮流显示
AJAX+POPUP+数据库,实现动态无限级栏目
JacaScript 通用表单验证函数(我佛山人)——改进版
多级关联菜单数据库版(老问题精解)
Css house—Css房子—Css高手境界
用CSS和JS画出来的美女(酷)
display与visibility的详细文档说明
实例分析CSS属性Display与Visibility不同
Flash CSS Box Model(CSS 盒模型)
CSS中的滑动门技术
CSS实现完美垂直居中
面向对象的JavaScript举例
使用this指针与prototype实现面向对象时的区别
FrameSet 与 Iframe 彻底剖析

通用滚动条配色工具(滚动条的CSS)
Javascript 压缩工具合集(Javascript compressed,Js压缩)
CSS巧用expression来区分只读文本框
CSS如何使DIV层水平居中(包括水平/垂直)
Javascript和弹出窗口
Web 2.0 编程思想:16条法则(Dion Hinchcliffe)
Ajax跨域工具: Modello.ajax

Javascript压缩工具(Javascript compressed,Js压缩)

读完这7本书再投资

  一本好的投资书对一个投资者来说,非常重要,这个重 要性类似于认识交通标志对于开车的重要性。好的投资书起码它可以节省你很多时间,因为滥竽充数的投资书和杰出的投资书大部分都同样无趣,如果谁咬牙坚持读 完一本这样的书,又完全是负效应,还不如把时间用来睡觉对身体还更有帮助。
  《第一财经周刊》本周汇集了29位专业投资人士和46位业余投资人的好书推荐,他们的意见五花八门,总共推荐了52本投资宝典。但是根据理财栏目一向 坚持的价值投资原则,我们筛选掉了那些关于线图和趋势判断指南,这些作者包括我们经常拿来开玩笑的威廉·江恩、托马斯·艾略特和罗伯特·爱德华兹。这真有 点不公平,就像我们老板说的,有意删节的真实就是不真实,我们只希望所推荐的书籍能在价值上对此进行弥补。其次,我们也注重了推荐的书是不是够有趣,读有 趣的投资书才会让投资者不会对投资落下什么心理阴影。

01
《彼得·林奇的成功投资》
彼得·林奇
机械工业出版社

  就像彼得·林奇在他的序言中写的那样,这本书是鼓励个人投资者信心的,而且向投资者传递最基础的投资知识。
  无论如何投资者都应该相信神奇的“银发彼得”,在彼得·林奇出任麦哲伦基金的基金经理人的13年间(1977—1990),麦哲伦基金管理的资产由 2000万美元成长至140亿美元,基金投资人超过100万人,成为富达的旗舰基金,基金的年平均复利报酬率达29.2%,这大大超过了同期标准普尔。
  不过也不得不说彼得·林奇是个幸运儿,在他掌控麦哲伦基金期间,正好也是美国股市从低谷向黄金时代转变的一段时间,而且林奇还恰巧错过了几次大的金融危机。
  在《彼得·林奇的成功投资》一书中,彼得·林奇为了鼓舞个人投资者的士气,不惜花大量篇幅去说明机构投资者所与生俱来的诸多缺陷,然后大力鼓舞个人投资者,并认为他们战胜机构投资者并不是不可能的事。
  林奇介绍他的投资经验时把要买的公司归为13条,其避而不买的公司归为6条,先看看他追求的那13条吧:1.傻名字 2.乏味 3.令人厌烦 4.有庇护的独立子公司 5.乏人关注的潜力股 6.充满谣言的公司 7.大家不想关注的行业 8.增长处于零的行业 9.具保护壁垒的企业 10.消耗性大的消费品 11.直接受惠高技术的客户 12.连其雇员也购买的股票 13.会回购自己股份的公司—这些“好”公司可能正好与大多数投资者想象的相反。
  《彼得·林奇的成功投资》对投资的看法,实际上是一个成功的美国共同基金看法—也就是中国的公募基金经理的看法—他的很多操作可能在当时,1989年对于美国来说是适用的,但是在20年后的中国,书中所提到的很多利基都已经消失了。
  不过,不管怎么说,《彼得·林奇的成功投资》还是一本初级投资者想要的那种书,它会大大提高初学投资者对投资的兴趣。

02
《股市真规则》
帕特·多尔西
中信出版社

  最好的投资者实际操作读本,无论你是在美国还是中国。
  如果一个智力正常却懵懂于股市的人,认真地研读完了帕特·多尔西的《股市真规则》,然后再花一天的功夫弄明白中国资本市场的一些交易要求后,那么他基本上就可以开始投资了,而且可以肯定,这个火星人的投资成绩基本应该能在所有投资者中达到中上游水平。
  帕特·多尔西是晨星公司股票研究部的负责人,书中系统介绍了晨星公司对美国上市公司股票估值的方法,特别给出了银行业、软件业、医疗保健业等13个行 业的研究方法和投资要关注的要点。就像他的老板乔·曼索托评价的那样,多尔西善于用简单平实的推理和语言使复杂问题得出答案,而且这个解答又看起来显而易 见。
  多尔西也是巴菲特的崇拜者之一,他的《股市真规则》的基本哲学框架是遵循巴菲特以及芒格的价值投资思维而建造的,他认为成功的投资建立在五个核心原则基础上:
1 做好投资功课
2 寻找有强大竞争力的公司
3 有一个安全边际
4 长期持有
5 知道何时卖出
  在投资者通晓这些原则后,多尔西又讲到什么是投资者不应该做的,在书的第十三到第二十六章中,作者还一一为投资者们提供了各种行业公司分析的模板。
  另外多尔西写作此书的目的还有一点,就是告诫投资者,投资需要独立思考,要忽视周围的“噪声”,做出有利可图的长期投资决定。格雷厄姆和巴菲特也经常 指出,如果你认为自己的投资理由是对的,那正是你要担心的地方。《股市真规则》也希望读者挑战他的投资思想,找到自己独立成功的投资道路。

03
《投资学》
兹维·博迪等/机械工业出版社
威廉·夏普/中国人民大学出版社

  这两本《投资学》都是最牛的投资学课本。
  首先介绍的这本《投资学》作者由兹维·博迪、亚历克斯·凯恩和艾伦·J·马库斯共同完成,他们分别是来自波士顿大学、加州大学、波士顿学院的三位教 授,这三个人就像投资界的报时鸟一样,每隔三年就出版一本新版的投资学教材,据说英文原版已经出到了第八版,中文译本的最新版本是第七版。在每次的新版 《投资学》里,他们都会加入投资学新的研究成果,并且会加入最近的投资案例。
  而另一本《投资学》(中国人民大学出版社出版)的作者威廉·夏普就更著名了,他在1990年获得了诺贝尔经济学奖,当时他只有56岁—这对于一个获得 诺贝尔经济学奖的教授来说已经够年轻的了—我们的理财栏目也曾经用过他的资产定价模型, 而他与人合著的《投资学》更是深入浅出的说明那些能要人命的资产定价的计算。
  如果一个投资者有足够的耐性,去看这两本巨著,那收获肯定是令人羡慕的。这两本《投资学》所讲的内容范围类似,都是初级投资学的终极武器—终极武器的 意思有两部分,一是说,投资者研读完这两部学说中的一部,基本就可以解决一切投资中的理论问题;其次,如果你是个公司人,那么研读一部《投资学》大概要花 费你半年内所有的业余时间。

04
《聪明的投资者》
本杰明·格雷厄姆
江苏人民出版社

  沃伦·巴菲特、查理·芒格、比尔·鲁安、桑迪·戈特斯曼、沃尔特·施洛茨这些人除了都是亿万富翁,还有什么共同特点?他们还都是格雷厄姆俱乐部的成 员,格雷厄姆便是价值投资的鼻祖。格雷厄姆是个极为矛盾的人,他经历过1929年的大萧条,所以在投资生涯中一直保持着保守的策略;而格雷厄姆又有着杰出 的语言天赋,精通葡萄牙语,拉丁语和希腊语;格雷厄姆还结过三次婚,最后死在了法国情妇家里。他的著作里就体现了他这种矛盾性:保守的思想和杰出的表达能 力。
  《聪明的投资者》大概是第一本不鼓励投资者频繁交易,而推崇长期投资的证券分析书籍。巴菲特曾经多次在他讲演时说,投资者只要认真研读该书的第八章和第二十章就可以了,这两章的内容超过了现在出版的所有投资书的价值。

05
《一个美国资本家的成长》
罗杰·罗恩斯坦
中信出版社

  市场上随处可见沃伦·巴菲特的大传或别传之类的书,这些书大多是中国知识产权保护不严造成的,其实巴菲特的传记只有两本,那就是爱丽丝·施罗德的《滚 雪球》和罗杰·罗恩斯坦的《一个美国资本家的成长》,相比之下《滚雪球》因为其宣传力度和更多与巴菲特贴近性而名气更大,但是专业人士更多地推荐了《一个 美国资本家的成长》。其中原因可能是该书更关注于巴菲特的投资策略和公司价值分析,《滚雪球》更多地提到巴菲特的私生活,比如和妻子苏茜的婚姻就花去了好 几个章节。
  作者罗恩斯坦是《华尔街日报》资深财经记者,对沃伦·巴菲特进行过多年的跟踪研究。本书不仅证明了投资是一种理性的、可以捉摸的事业,而且为外行人解释了华尔街神秘的背后故事。

06
《怎样选择成长股》
菲利普·费雪
三环出版社

  这是流传最广的投资经典之一,这本书启发了无数人,很多后来的投资大师都从这本薄薄的册子里得到投资的精髓。当然也是这本书启发了沃伦·巴菲特,巴菲特称自己在第一次阅读到《怎样选择成长股》后非常兴奋,立刻就决定去找费雪谈谈。
  “当我见到他时,他和他的思想都给我留下了深刻的印象。利用菲利普的技能,就能获得对行业及其商业模式的彻底理解……能使一个人做出明智的投资决定。”而费雪则称巴菲特为霍华德—这是因为巴菲特的父亲霍华德做过州议员,而费雪喜欢背美国全体议员的名字来给自己催眠。
  《怎样选择成长股》可能是我们推荐的书中最薄的一本了,书的结构非常简单而且主要就是寻找优秀股票的十五个原则。什么时候买?什么时候卖出?什么时候 不要买、投资者的五不要和再一次五不要,还有就是保守型投资者高枕无忧—这一段写的是投资的商业逻辑—简单吧!而且内容还都是一个普通投资者最需要知道 的。
  但是这本书有个缺点,不知道是翻译得不好还是费雪这个人天生无趣—大家对费雪的印象是孤僻、强悍,而且具有古怪的幽默感—看费雪这本著作就和费雪当初背那些参议员的名录有同样的功效。如果是英文比较牛的人还是看看英文的原版吧。

07
《大投机家:最佳金钱故事》
安德烈·科斯托拉尼
海南出版社

  安德烈·科斯托拉尼在我们的推荐中是个例外,他是个十足的投机分子,他的《大投机家》里既说到投机,又有部分和价值投资相契合,他也认为在他80年的交易所生涯中,还没认识一位能长期取得成功的交易所投机手。
  安德烈·科斯托拉尼是出生在匈牙利的犹太人,被喻为欧洲的沃伦·巴菲特和证券教父。从1906年一直到1999年,他活了93岁,所以又被称为“20 世纪股市见证人”、“20世纪金融史上最成功的投资者之一”。1919年,13岁的科斯托拉尼随家人移居维也纳后,开始着迷于欧洲各种货币的不同变化,从 而展开其绚丽多彩的投机人生。
  他的前半生经历稍微有点像索罗斯,犹太人—战争—避难,但是后来科斯托拉尼的性格显然要比索罗斯积极,在35岁赚到足以养老的财富之后,他没有甘于平 淡就此退休,过人的精力使他转而开始发展第二事业,成为财经杂志的专栏作家,举个足以说明问题的数据,他曾为德国经济评论杂志《资本》供稿长达25年。
  他一生共出版了13本国际畅销著作。并且,从1970年代开始,科斯托拉尼便在德国和世界各大都市的咖啡馆中,教授股市知识,不断教导青年朋友:在股票市场上成功,不是靠计算,而是思想,用脑子里的思想。
  据说科斯托拉尼在往返欧洲各地讲课过程中还会把别人给他定的头等舱机票退掉,换成经济舱,然后把多出的钱自己留着用—有这种心机的人肯定是热爱生活 的。《大投机家:最佳金钱故事》讲的基本就是科斯托拉尼的投机生涯,这本书和他本人一样有趣。而且,这个投机分子也对那些希望成为投机分子的家伙进行了不 少告诫,比如“有几种不同的方法输掉财富:吸毒、赌 博、女人和股票。”“我的大部分经验是在损失惨重的交易经过中获得的。因此我也可以说,一位交易所投机 者一生中没有至少两次破产,他就不配得到这一称号。”
 
看上去太好的事情通常不是真的—《股市真规则》
有足够的内幕消息,再加上100万美元,那么就足够让你在一年内破产的了—巴菲特《一个美国资本家的成长》
投资很有趣很刺激,但如果你不深入研究那这个游戏就很危险

PKI标准可以分为第一代和第二代标准

第一代PKI标准主要包括美国RSA公司的公钥加密标准(Public Key Cryptography Standards,PKCS)系列、国际电信联盟的ITU-T X.509、IETF组织的公钥基础设施X.509(Public Key Infrastructure X.509,PKIX)标准系列、无线应用协议(Wireless Application Protocol ,WAP)论坛的无线公钥基础设施(Wireless Public Key Infrastructure,WPKI)标准等。第一代PKI标准主要是基于抽象语法符号(Abstract Syntax Notation One,ASN.1)编码的,实现比较困难,这也在一定程度上影响了标准的推广。
第二代PKI标准是在2001年,由微软、VeriSign和webMethods三家公司发布了XML密钥管理规范(XML Key Management Specification,XKMS),被称为第二代PKI标准。XKMS由两部分组成:XML密钥信息服务规范(XML Key Information Service Specification,X-KISS)和XML密钥注册服务规范(XML Key Registration Service Specification,X-KRSS)。X-KISS定义了包含在XML-SIG元素中的用于验证公钥信息合法性的信任服务规范;使用X-KISS规范,XML应用程序可通过网络委托可信的第三方CA处理有关认证签名、查询、验证、绑定公钥信息等服务。X-KRSS则定义了一种可通过网络接受公钥注册、撤销、恢复的服务规范;XML应用程序建立的密钥对,可通过X-KRSS规范将公钥部分及其它有关的身份信息发给可信的第三方CA注册。X-KISS和X-KRSS规范都按照XML Schema 结构化语言定义,使用简单对象访问协议(SOAP V1.1)进行通信,其服务与消息的语法定义遵循Web服务定义语言(WSDL V1.0)。目前XKMS已成为W3C的推荐标准,并已被微软、VeriSign等公司集成于他们的产品中(微软已在ASP.net中集成了XKMS,VeriSign已发布了基于Java的信任服务集成工具包TSIK)。
CA中心普遍采用的规范是X.509[13]系列和PKCS系列,其中主要应用到了以下规范:
1.X.209(1988) 
ASN.1是描述在网络上传输信息格式的标准方法。它有两部分:第一部份(ISO 8824/ITU X.208)描述信息内的数据、数据类型及序列格式,也就是数据的语法;第二部分(ISO 8825/ITU X.209)描述如何将各部分数据组成消息,也就是数据的基本编码规则。 
ASN.1原来是作为X.409的一部分而开发的,后来才独立地成为一个标准。这两个协议除了在PKI体系中被应用外,还被广泛应用于通信和计算机的其他领域。 
2.X.500(1993) 
X.500是一套已经被国际标准化组织(ISO)接受的目录服务系统标准,它定义了一个机构如何在全局范围内共享其名字和与之相关的对象。X.500是层次性的,其中的管理域(机构、分支、部门和工作组)可以提供这些域内的用户和资源信息。在PKI体系中,X.500被用来惟一标识一个实体,该实体可以是机构、组织、个人或一台服务器。X.500被认为是实现目录服务的最佳途径,但X.500的实现需要较大的投资,并且比其他方式速度慢;而其优势具有信息模型、多功能和开放性。 
3.X.509(1993) 
X.509是由国际电信联盟(ITU-T)制定的数字证书标准。在X.500确保用户名称惟一性的基础上,X.509为X.500用户名称提供了通信实体的鉴别机制,并规定了实体鉴别过程中广泛适用的证书语法和数据接口。 
X.509的最初版本公布于1988年。X.509证书由用户公共密钥和用户标识符组成。此外还包括版本号、证书序列号、CA标识符、签名算法标识、签发者名称、证书有效期等信息。这一标准的最新版本是X.509 v3,它定义了包含扩展信息的数字证书。该版数字证书提供了一个扩展信息字段,用来提供更多的灵活性及特殊应用环境下所需的信息传送。 
4.PKCS系列标准 
PKCS是由美国RSA数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。到1999年底,PKCS已经公布了以下标准: 
PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封。 
PKCS#3:定义Diffie-Hellman密钥交换协议。 
PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。使用MD2或MD5 从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息。 
PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式。 
PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息。 
PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等。 
PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型。 
PKCS#10:描述证书请求语法。 
PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备。 
PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。 
PKCS#13:椭圆曲线密码体制标准。 
PKCS#14:伪随机数生成标准。 
PKCS#15:密码令牌信息格式标准。 
5.OCSP在线证书状态协议 
OCSP(Online Certificate Status Protocol)[14]是IETF颁布的用于检查数字证书在某一交易时刻是否仍然有效的标准。该标准提供给PKI用户一条方便快捷的数字证书状态查询通道,使PKI体系能够更有效、更安全地在各个领域中被广泛应用。 
6.LDAP 轻量级目录访问协议 
LDAP规范(RFC1487)简化了笨重的X.500目录访问协议,并且在功能性、数据表示、编码和传输方面都进行了相应的修改。1997年,LDAP第3版本成为互联网标准。目前,LDAP v3已经在PKI体系中被广泛应用于证书信息发布、CRL信息发布、CA政策以及与信息发布相关的各个方面。

Fitnesse使用

Fitnesse 的使用
一,介绍
Fitnesse是一种可以有效提供给软件开发前期各种角色合作的框架。
前端采用wiki界面便于编写case,后端将具体执行可以比较方便的添加各种feature。
前端case和后端feature共同作用起来就可以实现自动化测试。

二,原理
如何使wiki形式的case,驱动后端的class执行具体的代码,是Fitnesse的主要实现,现在存在两种方式

Fit: Framework for Integrated Testing
Fit是采用来控制Fitnesse test table执行的引擎。后台新添加的case需要引用该引擎。
Test table的格式也是来源于Fit。

Slim:Simple List Invocation Method
            instruction list 
+————-+    o—>     +——————–+      +———-+       +—————————————–+
| FitNesse |—[socket]–>| SlimServer |—–>| Fixtures |——>| SUT(System Under test) | 
+————-+    <—o     +——————–+      +———-+       +—————————————–+ 
              response list

1)FitNesse通过命令行的方式触发slim Server
2)Fitnesse随后会发一个命令的list以及期待的结果到SlimServer。
3)然后slimServer会去调用相应的Fixture。

对各语言的支持情况:

 Fitnesse使用

三,内部包含的Fixture

Slim: simple list Invocation method

http://fitnesse.org/FitNesse.UserGuide.SliM.SlimProtocol

Fitnesse使用

Fit:http :// fitnesse.org / FitNesse.UserGuide.FitFramework

Fitnesse使用

四,添加Feature
1)Java API
采用Fit模式:
自己新建的fixture需要继承Fit中的一种Fixture

例如:

Package eg;
import fit.ColumnFixture;   
 
public class Division extends ColumnFixture   
{   
   public double numerator;   
   public double denominator;   
   public double quotient() {   
       return numerator/denominator;   
    }   
}
 
在wiki界面上就可以调用
Fitnesse使用

 

如果采用slim模式:

我们需要添加的fixture:

package fitnesse.slim.test;

import java.util.List;
public class ShouldIBuyMilk {
private int dollars;
private int pints;
private boolean creditCard;

public void setCaseInWallet(int dollars){
this.dollars=dollars;
}
public void setPintsOfMilkRemaining(int pints){
this.pints=pints;
}
public void setCreditCard(String valid){
if(valid == “yes”)
creditCard = true;
else
creditCard = false;
}
public String goToStore(){
if (pints==0&&(dollars>2||creditCard))
return “yes”;
else
return “no”;
}
 public void execute() {  }
 public void reset() {  } 
 public void table(List<List<String>> table) {}

}

添加wiki并执行就是这样的结果:

Fitnesse使用

 

2)C++的支持:

为了实现对C++测试的支持,Fitnesse存在Fit的C++版本,便于新的C++ feature的加入

 我们需要下载CppTestTool,然后在同级目录下建立结构:

比如: addTest—–|——-bin

                                    |——-CppTestTools

                                    |——-include

                                    |——-lib

                                    |——-src

在src中添加我们需要的new feature

一旦触发wiki上的开始按钮,fitnesse就会给FitServer法请求,Fit就会去调用我们新加的这部分feature。

首先是main函数,int main(int argc, char* argv[])
{
 FixtureMaker* maker = new HomeGuardFixtureMaker();
 int status = FitnesseServer::Main(argc, argv, maker);
 return status;
}

在main函数中就会把用大的feature都注册过来

#include <Fit/Platform.h>
#include <Fit/Fit.h>
#include <Fit/Summary.h>
#include <Fit/ResolutionException.h>

#include “MgmtFixtureMaker.h”

#include “addsampletest.h”

#include <iostream>
#include <string>

using namespace std;

HomeGuardFixtureMaker::HomeGuardFixtureMaker()
{
}

HomeGuardFixtureMaker::~HomeGuardFixtureMaker()
{
}

Fixture* HomeGuardFixtureMaker::make(const string& fullName)
{

 string name = fullName;
   string libraryName = splitName(fullName).first;
    if (libraryName != fullName)
        name = splitName(fullName).second;

    PUBLISH_FIXTURE(Fixture);
    PUBLISH_FIXTURE(ColumnFixture);
    PUBLISH_FIXTURE(ActionFixture);
    PUBLISH_FIXTURE(PrimitiveFixture);
    PUBLISH_FIXTURE(Summary);

 // mgmt test
 PUBLISH_FIXTURE(addsampleTest)

    throw ResolutionException(name);

    return 0;
}

 

 

我们的新feature主体,需要用到的方法名,同样需要声明

#include <string>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <map>

#include <Fit/ActionFixture.h>
class addsampleTest : public Fixture
{
public:
    addsampleTest()
 { PUBLISH_ENTER(addsampleTest, std::string, addstring1);
   PUBLISH_ENTER(addsampleTest, std::string, addstring2);
   PUBLISH_ENTER(addsampleTest, std::string, addpath);
   PUBLISH_CHECK(addsampleTest, std::string, runTest);
 }

void addstring1(std::string input){
   string1 = input;   
}
 void addstring2(std::string input){
   string2 = input;
}
void addpath(std::string input){
   path=input;
}
 std::string runTest(){
   string command=””;
   command=path+” “+string1+” “+string2+”>ll.log”;
  
   int tmp = system(command.c_str());
   return “success”;
}
private:
   std::string string1;
    std::string string2;
    std::string path;
};

这样wiki界面上就可以直接调用了:

Fitnesse使用

 

 

adb install INSTALL_FAILED_ALREADY_EXISTS

安装时候碰到的一个问题:已经签名的包,重新通过adb install 会提示安装错误。提示:Failure [INSTALL_FAILED_ALREADY_EXISTS]

为啥eclipse自己就可以不停滴覆盖重装呢?

因为eclipse自动打包是debug的签名,而我打如果是release签名就会出现上面的报错。解决办法:adb install -r

adb install -r 这里的r是reinstall 的缩写。顺便学习一下adb install的相关参数。

adb install -r  (reinstall) 重装

adb install -s (sdcard)  装在SD卡上而不是internal storage

adb uninstall -k (keep) 保留用户数据。

使用IntrospectorCleanupListener 解决quartz引起的内存泄漏

“在服务器运行过程中,Spring不停的运行的计划任务和OpenSessionInViewFilter,使得Tomcat反复加载对象而产生框架并用时可能产生的内存泄漏,则使用IntrospectorCleanupListener作为相应的解决办法。”

对于这一句话,引用关于IntrospectorCleanupListener一段解释:

引用
spring中的提供了一个名为 org.springframework.web.util.IntrospectorCleanupListener的监听器。它主要负责处理由  JavaBeans Introspector的使用而引起的缓冲泄露。spring中对它的描述如下:它是一个在web应用关闭的时候,清除JavaBeans Introspector的监听器.web.xml中注册这个listener.可以保证在web 应用关闭的时候释放与掉这个web 应用相关的class loader 和由它管理的类如果你使用了JavaBeans Introspector来分析应用中的类,Introspector 缓冲中会保留这些类的引用.结果在你的应用关闭的时候,这些类以及web 应用相关的class loader没有被垃圾回收.不幸的是,清除Introspector的唯一方式是刷新整个缓冲.这是因为我们没法判断哪些是属于你的应用的引用.所以删 除被缓冲的introspection会导致把这台电脑上的所有应用的introspection都删掉.需要注意的是,spring 托管的bean不需要使用这个监听器.因为spring它自己的introspection所使用的缓冲在分析完一个类之后会被马上从javaBeans Introspector缓冲中清除掉.应用程序中的类从来不直接使用JavaBeans Introspector.所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题.例如:Struts 和Quartz.单个的内部查看泄漏会导致整个的web应用的类加载器不能进行垃圾回收.在web应用关闭之后,你会看到此应用的所有静态类资源(例如单 例).这个错误当然不是由这个类自 身引起的.

用法很简单,就是在web.xml中加入:
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>

只知道servlet标准不允许在web容器内自行做线程管理,quartz的问题确实存在。  

对于Web容器来说,最忌讳应用程序私自启动线程,自行进行线程调度,像Quartz这种在web容器内部默认就自己启动了10线程进行异步job调度的框架本身就是很危险的事情,很容易造成servlet线程资源回收不掉,所以我一向排斥使用quartz。

quartz还有一个问题就是不支持cluster。导致使用quartz的应用都没有办法做群集。

如果是我的话,我采取的办法就是自己单独启动一个Job Server,来跑job,不会部署在web容器中。