February 8, 2012
| 作者:白菜
|
分类:随便侃侃
firefox 10最严重的一个bug就是光标无缘无故经常丢失,突然输入框和地址栏的光标就不见了,输入还正常,但是复制粘贴没办法了,怎么弄也出不来。只有回到桌面刷新下资源管理器或者刷新下网页才能恢复。
这个bug在firefox9的版本时就存在,但没有10中这么严重和频繁,已经严重影响了正常使用。这个bug在相关社区已经有多人反映了,我就不清楚,官方怎么还没做出回应改进?是没测试过还是根本不知道?这种bug比任何效率神马的都紧急。
February 6, 2012
| 作者:白菜
|
分类:软件&IDE
因为工作中经常需要用到流程图软件,上网仔细挑选了几款相对比较优秀的软件,一一介绍。
注意:流程图也叫Flowchart,不是思维导图Mind Map。不过有的软件既能绘制Mind Map,也能绘制Flowchart,如Edraw Mind Map(也称亿图图示专家),不过亿图如今有了专门的Flowchart了。
1.Diagram Designer
免费软件,windows平台,最新版本 1.25.下载地址:
http://meesoft.logicnet.dk/
安装包体积:1.3M
可以画一些简单的流程图,GUI示意图(Diagram Designer的特色就在这里),主要的图元有:简单图形,流程图,GUI窗口和元素,UML类图。
优点和特色:体积小,可画GUI示意图,展示窗口,表格等。
缺点:图元样式不够丰富,太少了。属性和文本编译不够直观,另外导出的图像质量不是很好,特别是曲线图形锯齿比较明显。导出时,不会智能的选择指导出可见部分。因此使用前需要预先设置好画布大小。
输出效果:

2.Dia
免费软件,跨平台,最新版本0.97.2,下载地址:
http://projects.gnome.org/dia/WINDOWS安装包 19M.由于dia最初是linux平台下的软件,所以发扬了linux桌面软件bug比较多,用户不友好,难适应的传统。
阅读剩余部分...
February 5, 2012
| 作者:白菜
|
分类:网页前端
目前支持SPDY协议的应用有:firefox开发板,jetty8等。
SPDY 目前是一种应用层实验性协议,旨在让互联网访问更快速,减少web页面的延迟。
SPDY 设计特点
协议在SSL层的基础上,增加了一个session 层,从而在一个tcp 连接基础上,实现了多并发和交叉流传输
HTTP 的GET ,POST 仍旧采用旧有的消息格式,当然SPDY 协议对原有的数据做了封装和编码,这里采用Wrapper设计模式。

流是双向的,比如,既可以从客户端发起,也可以从服务器端发起(PUSH)
SDPY的目标就是通过其基本特性和高级特性,来达到低访问延迟
基本特性包括
1 流复用
SPDY最牛逼的地方,是允许在一个TCP连接里面,允许无限并发流(在双方资源可承受的情况下)。因为请求是在一个单一的通道交错传输,TCP的可以达到很高的效率,从而更少的网络连接需要,可以以很高的 数据密度做传输。
2 具备优先级的请求
虽然无限的并行数据流的解决了序列化的问题,但是它们引入了另一个问题:如果由于信道带宽的限制,客户端可能会阻止怕堵塞通道的要求。为了克服这个问题,SPDY实现请求的优先次序:客户端可以请求尽可能多的项目,每个请求分配一个优先级。这样即使高优先级的请求仍处在pending状态,通道也不会传输非关键的,低优先级的请求,这样就有效地阻止了传输拥塞。
3 HTTP Header 压缩
对于HTTP 请求,响应头,SPDY都做了压缩,这样包更小,对于RESTFUL类型的WEB2.0 ,or OpenAPI 业务,将会有可观的效率提升。
高级特性
1 服务器端推送
SPDY通过X-Associated-Content 协议头来向客户端推送数据,头通知客户端,我要向你推送资源,准备接收好了。最近火爆的Google+ ,如果你用chrome浏览器,默认就采用SPDY技术,并且开启了服务器推送技术。服务器的推技术,全面提升了用户体验,是G+ 产品很快占据了足够多的优势,最近Facebook 开发自己的浏览器,也有摆脱现在技术限制的考虑
2 服务器暗示
不像上面提到的PUSH 技术,服务器会先告诉浏览器,你可以下载ABC资源了,这个ABC资源,可能就是下一个页面的JS ,CSS ,或者内容。服务器不会主动推送的,仍旧等待客户端请求,这对于低速网络,是个很大的优化,有点类似于我们的预加载技术
效果测试
TOP25 网站的平均页面加载时间
|
DSL 2 Mbps downlink, 375 kbps uplink |
Cable 4 Mbps downlink, 1 Mbps uplink |
|
Average ms |
Speedup |
Average ms |
Speedup |
| HTTP |
3111.916 |
|
2348.188 |
|
| SPDY basic multi-domain* connection / TCP |
2242.756 |
27.93% |
1325.46 |
43.55% |
| SPDY basic single-domain* connection / TCP |
1695.72 |
45.51% |
933.836 |
60.23% |
| SPDY single-domain + server push / TCP |
1671.28 |
46.29% |
950.764 |
59.51% |
| SPDY single-domain + server hint / TCP |
1608.928 |
48.30% |
856.356 |
63.53% |
| SPDY basic single-domain / SSL |
1899.744 |
38.95% |
1099.444 |
53.18 |
| SPDY single-domain + client prefetch / SSL |
1781.864 |
42.74% |
1047.308 |
55.40% |
February 2, 2012
| 作者:白菜
|
分类:JAVA
伪共享False sharing说明JVM底层技术也不让人那么放心。
内存缓存系统中基本单元是高速缓存行(Cache lines). cpu会把数据从内存加载到高速缓存中 ,这样可以获得更好的性能,高速缓存默认大小是64 Byte为一个区域,一个区域在一个时间点只允许一个核心操作,也就是说不能有多个核心同时操作一个缓存区域。
因为高速缓存是64字节,而Hotspot JVM的对象头是两个部分组成,第一部分是由24字节的hash code和8字节的锁等状态标识组成,第二部分是指向该对象类的引用。基本类型字节如下:
doubles (8) and longs (8)
ints (4) and floats (4)
shorts (2) and chars (2)
booleans (1) and bytes (1)
references (4/8)
因此,一个高速缓存64字节可以放下多个字段,如果这多个字段位于同一个高速缓存区,虽然它们是类的不同字段,如下代码:
Class A{
int x;
int y;
}
x和y被放在同一个高速缓存区,如果一个线程修改x;那么另外一个线程修改y,必须等待x修改完成后才能实施。
虽然两个线程修改各种独立变量,但是因为这些独立变量被放在同一个高速缓存区,性能就影响了。测试结果如后面。
当多核CPU线程同时修改在同一个高速缓存行各自独立的变量时,会不自不觉地影响性能,这就发生了伪共享False sharing,伪共享是性能的无声杀手。
解决方便是将高速缓存剩余的字节填充填满(pad),确保不发生多个字段被挤入一个高速缓存区,下面测试结果图就是和填充后性能比较。
实现字节填充的框架有 Disruptor,在RingBuffer中实现填充。关于Disruptor可见infoQ这个视频,用1毫秒的延时得到100K+ TPS吞吐量,JDK的ArrayQueue并行环境不见得是最快的,该视频后面讨论很多,让人大跌眼镜啊,开放源码多有好处啊,别人能发现你不能发现的漏洞。另外一篇解剖Disruptor
C#也有类似伪共享发生,见
这里

参考:
http://www.jdon.com/jivejdon/thread/42451
LMAX架构
disruptor - 并发编程框架
http://www.infoq.com/presentations/LMAX
February 1, 2012
| 作者:白菜
|
分类:编程算法
February 1, 2012
| 作者:白菜
|
分类:php
l来自雪候鸟的文章:
http://www.laruence.com/2012/02/01/2503.html,正好解释了这个问题。
原问题来自这里
http://bbs.phpchina.com/thread-230760-1-1.html
string exec ( string $command [, array &$output [, int &$return_var ]] )
第三个参数, 怎么不能接收负数??
这里的&$return_var就是程序返回值,起初我的回答是可以为负数。
一般在C语言里我们会这样写
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("^_^\n");
return -5;
}
这个-5就是返回值,但习惯上是写成0或者1的。
注意:很多人的C代码里把main函数写成 void main() 这样实际上是不对的,详细的就不说了。
把上面的代码编译后,到CMD下运行,然后就能看到输出结果了。接着,输入“echo %ERRORLEVEL%”,回车,就可以看到程序的返回值了。这个%ERRORLEVEL%就代表了程序的返回状态。在WIN下确实是可以为负数的。如图所示:

,php调用也是正常的。
E:\dev\php535>php -r "exec('return.exe',$out,$a);var_dump($a);"
int(-2)
但是到了linux下,始终为正数,刚开始怀疑是权限问题,用了chmod +x后,排除了权限问题。
exec("/home/wwwroot/test/rtest.out 2>&1",$out,$a);
var_dump($out,$a);
array(1) { [0]=> string(3) "^_^" } int(251)
看起来成了256+return val,可以看到实际上返回了负数,只不过被转换成正数了。
接着看了下standard/exec.c里的源代码,没发现啥端倪,干到很奇怪,突然想到自己忘了一步。忘了看程序返回给OS的值了.
可以使用echo $? 显示最后命令的推出状况。
-bash-3.00$ vi main.c
-bash-3.00$ gcc -o ./mm main.c
-bash-3.00$ ll
total 48
drwxr-xr-x 3 www www 4096 May 4 2011 2011
drwxr-xr-x 6 www www 4096 Jun 23 2011 eoc
-rwxr-xr-x 1 www www 7131 Feb 1 12:47 hello
-rw-r--r-- 1 www www 3 Feb 1 12:51 hello.c
-rw-r--r-- 1 www www 99 Feb 1 12:50 main.c
-rwxr-xr-x 1 www www 4714 Feb 1 12:51 mm
drwxr-xr-x 3 www www 4096 Jun 24 2011 test
-bash-3.00$ ./mm
^_^
-bash-3.00$ echo $?
251
-bash-3.00$
这样就可以看看exec返换给OS的值是多少。
在linux下,这个返回值就是无符号类型,返回的是一个正数,所以传给php也是正数了,php实际上也是调用的exec所返回的值。
OUT了,也许linux就是这么规定的,程序中泰返回值为1~255区间,而自己不清楚这个规则。不过还没有确定是否linux里就是这么规定的。虽然问题很蛋疼,意义不大,不过也可以在这里留给遇到类似问题的人参考。不过到这里也没深究的必要了。谁要是真想彻底搞清楚,可以看看shell这块
January 12, 2012
| 作者:白菜
|
分类:心情与文字
看见周边这么多人各种总结回顾,再一想,人的一生也不过900个月而已,转瞬即逝,而我也不能免俗,嘘叹毕业已经一年半矣,虚度了300多个月了,竟也过了人生的1/3了,换句话说,土已经埋到大腿了。
10年七月毕业至今,只回过一次家,家远在几千里外的西南,每当吃饭时,总怀恋家乡,这里的饭菜,要是在俺家,那都是喂猪的,缺油少盐,调料、佐料简陋的无语,让人甚是怀恋西南的精致和美味,西南有各种北方人没吃过的,没见过的美食。到了这里,都是奢望。
现在是冬天了,出租屋里没有空调,没有暖气,在宿舍手脚冰冷,晚上睡觉盖两床被子仍瑟瑟发抖。
不抱怨了,还是说点正事。
一、生活上
1.生活仍然简简单单,不过倒是恋爱了,找到了实实在在那个对自己好的人,在乎我的人,这就够了。虽此前有过种种分分合合,不过现在我们都很有信心坚持下去,说不定很快就谈婚论嫁了。
2.依然是周一到周六公司上班,周日上午睡觉,下午逛逛。不喜欢喧闹,平平淡淡就好。晚上呢,10年12月-11月6月期间,每天睡觉不超过4个小时,用了半年的时间实现了九阳神功第一重的修炼。这之后稍微收敛了点,细火慢熬修炼第二重。
3.吃的不是很好,北方伙食和南方不是一个档次,所以没胖,还是很瘦。
4.这一年半,累计消费55449人民币。
二、做过的事
1.真没做啥事,就是上班,吃饭,学习,睡觉。
2.技术上从草根php转型JAVA开发,很感谢公司给我机会,让我这个因为专业原因被四处鄙视的半路出家的毕业生有了份工作,而且公司气氛很好,开发流程很正规,让我养成了好的代码习惯。另外,技术上放弃python学习,专攻java,C,php,数据库等。也放弃了之前热爱的PS和FLASH制作,想当年,我就是靠着我PS的照片招摇撞骗的,嘿嘿。期间翻译过PY手册,不过已经放弃,写过一个php的学习指南,也大半年没更新了,还写过几个小小的软件,就此而已,也没啥大作为。偶尔骂骂人,然后被人骂。
三、看过的书
一堆了,《java编程思想》,《可爱的python》,《TCP/IP》,《算法导论》,《windows程序设计》《java虚拟机》,《深入理解MYSQL》,《C++ primer》,《大话数据结构》然后就是一堆的C,linux的书籍了,一年半重点看了10本书。没有看过小说,要看的话也是用手机看的,或者MP4看的电子书,不过电子书看的累,基本都没深入。
另外,《英语学习》这本杂志是必看的。
累计学习时间2000小时.
四、想做的事
1.活下去,继续生活,和她在一起;
2.给自己放一个月假,整整学了400多天了,没睡过安稳觉了。能晚上十点睡,早上八点起我就满足了;
3.继续啃我的二十本书,力求技术突飞猛进,修炼九阳神功第三重;
4.长胖5-10公斤。
January 9, 2012
| 作者:白菜
|
分类:JAVA
简介: Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错。在这期的Java 理论与实践中,Brian Goetz 将介绍几种正确使用 volatile 变量的模式,并针对其适用性限制提出一些建议。
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。
锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。
Volatile 变量
Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。
出于简易性或可伸缩性的考虑,您可能倾向于使用 volatile 变量而不是锁。当使用 volatile 变量而非锁时,某些习惯用法(idiom)更加易于编码和阅读。此外,volatile 变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。
正确使用 volatile 变量的条件
您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
- 对变量的写操作不依赖于当前值。
- 该变量没有包含在具有其他变量的不变式中。
实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。
第一个条件的限制使 volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使 x 的值在操作期间保持不变,而 volatile 变量无法实现这点。(然而,如果将值调整为只从单个线程写入,那么可以忽略第一个条件。)
大多数编程情形都会与这两个条件的其中之一冲突,使得 volatile 变量不能像 synchronized 那样普遍适用于实现线程安全。清单 1 显示了一个非线程安全的数值范围类。它包含了一个不变式 —— 下界总是小于或等于上界。
清单 1. 非线程安全的数值范围类@NotThreadSafe
public class NumberRange {
private int lower, upper;
public int getLower() { return lower; }
public int getUpper() { return upper; }
public void setLower(int value) {
if (value > upper)
throw new IllegalArgumentException(...);
lower = value;
}
public void setUpper(int value) {
if (value < lower)
throw new IllegalArgumentException(...);
upper = value;
}
}
阅读剩余部分...