-gwa2 vs -thinkphp

在用 -GWA2 开发过程中,接触和了解到 -thinkphp , 一款不错的PHP开发框架。 由于并行的部署了两个框架,所以比较起来就很容易的事了,有一个可供测试的任务是,从前端的form表单中搜集一些表单项数据,然后递交到后台,进行SQL组装.

然后再将查询递交给SQL发服务器,进而返回结果,进而给前端, 这是一个较为典型和常见的Web应用。 比试的结果是,同一个HTML form的请求,-GWA2 比 -thinkphp 快了一倍以上。 测试环境是在PC上搭建的基于openSuSE的VMware虚拟机,使用 -nginx 和 -php 7.0的环境,使用 fpm 模块。 以下是一些细节及可能的解析。

performance-thinkphp-vs-gwa2-201605-003
在一组连续的5次HTTP请求中, -thinkphp 的页面处理时间为 4.5秒左右,最高到6秒多,而 -gwa2 的页面处理时间为 1.7秒左右,最高到2.7秒。 其中SQL本身的执行时间变化并不大,单独在SQL的CMD下执行,耗时约为0.5秒左右。

尝试分析其中的耗时点,可能 -thinkphp 的请求流程处理环节较为复杂,且涉及到的功能多样,如在其官方文档里描述的,每个request请求,大约有68个标准的功能模块需要处理 ( -R/b2Te )

thinkphp-routing-job

在这方面, -gwa2 并没有那么复杂,更多的功能和操作还是留给了程序开发人员去设置和调配。这可能是节省资源及开支的重要的地方。

-gwa2

-gwa2

关于PHP的性能优化,之前的一个关注和测试实验是, “php的所谓优化” ( -R/22SK   ), 文章写到, “OO思想其实有些拿性能换便利,从尊重人惰性来说,只会通过升级硬件在获得便利的同时来获取高性能。 …类写的尽量简单,尽量使用内置函数,可有效提升(550.92-179.11)/550.92 = 67.4% “.

而观察和阅读 -thinkphp 则是完全的各种面向对象的设计与实现,如果这个实验的数据可供参考,则更多的类的设计与实现,就是让业务代码距离PHP内置函数越远,从而性能上会有所折扣。 同样地,我们还使用Java语言做过类似的实验。 在 “关于log4j和Sysytem.out.println的性能比较测试” ( -R/I2SL   )文章,我们观察到 ,”log4j和System.out.println资源耗时均值比为:4.13:1 。 ”

同时也意识到, “log4j与System.out.println不具有可比性,做这个测试的目的是:论证在一个对性能要求很高的环境中,是否可以使用log4j, 也即要用数据说明,log4j的额外开销是多少?这些开销对高性能系统来说是否是值得的,或者,是否是能够承受的?” 借此,也许可以小结此文,也许追求大而全功能强大的  -thinkphp 与 -gwa2 不具有可比性。

恰好在读关于 -apache 和 -nginx 对比的文章,其中一个比喻很形象,也适用于很多场合: Apache就像是具有60K个功能的Word字处理软件一样,普通用户经常使用的也许就只有6个功能;恰好Nginx在做这6件事时,表现得较好。  

发表在 -GWA2, 编程技术, 计算机技术 | 标签为 , , , | 留下评论

医用外科口罩一次性医疗专用口罩防尘透气成人三层防护透气医生插座保护套儿童防触电插孔安全塞防护盖宝宝婴幼儿插头插座孔插板床上电脑桌大学生宿舍上铺懒人可折叠小桌子家用寝室简约学习书桌电热蚊香液套装无味婴儿孕妇家用补充液插电式灭蚊液

-GWA2更新:扩展增加read/writeObject to setBy/getBy

继续需求驱动,-GWA2 扩展增加read/writeObject 到 setBy/getBy中,对数据持久化层的访问增加了对文件系统和远程接口的支持。本周还深入了解了 -ThinkPHP 这一开发框架,随着对其深入理解,也再次陷入了为何需要,为何那么多开发框架被开发出来 这样的思考题中。

但这个问题现在还没有解,采用类比思考的方法,人们所说的话,为何有那么多语言? 同一门语言,为何有那么多种方言? 计算机操作系统为何有那么多分类? 同样是Linux操作系统,为何有那么多分支旁系?也许世界原本是多态和丰富的,世界的多样性,大多是个体的差异所导致。比如,世界上应该有最好的某个苹果,也有最差的某个梨子,只是个体和子群的所处环境、认知差异等,导致一个绝对意义上的好的苹果在A或者A群看来是好的或者最好的,在B或者B群看来是差的或者最差的,在C或者C群看来,很一般般,而D或者D群可能说,这是什么东西。没错,他们都没有错,从他们自己的观点、视角和认知来看,他们的判断是符合一般逻辑推理过程的。

在“化干戈为玉帛:平息争执的四个方法( -R/X2Tc )”的文章中,我们曾观察到“人将自己视为真理,可能是所有争执的起源,所有战争的导火索”。也许这能很好地解释,哪种开发框架好,为何有那么多软件开发框架被开发出来。

归正,在技术实现上, -GWA2 的设计中,此前将所有对对象的改变,默认持续化存储是 数据库,没有深入考虑或者实现其扩展将持久化存储到其他方式方法,比如网络、文件系统等,本周在研发中遇到实例,就顺便将改变状态的主方法 getBy/setBy做了扩展,使之能够支持读写文件和网络访问。也即,增加了 readObject/writeObject。 其技术细节如下:

1. readObject
在 getBy 中判断 getBy 的第一个参数 $fields 中是否包括 “:”, 如果包括,则视为读取文件系统或者网络系统,而不是数据库系统。
进一步地,当判断成从非数据库读取时,则分别判断是:
a) ‘file:’ , 这个关键词表示,从文件系统读取;
b) ‘url:’ , 这个关键词表示,从网络远程通过URL读取。
-gwa2-readObject-201605

2. writeObject
同样地, 在 -GWA2 中,在 setBy 方法中,判断其第一个参数 $fields, 如果保护有 ‘:’ 关键词,则视为存储持久化到非数据库系统,由此将处置权交给 writeObject. 在 writeObject 中进一步地判断:
a) 若存储为 ‘file:’ 关键词,则调用文件写操作系统;
b) 若存储为 ‘url:’ 关键词,则存储为进一步调用远端接口,此时为触发 HTTP POST/GET 方法,封装细节见程序代码。

3. 调用样例
调用上述写入或者读取非数据库的持久化趁,使用:
$obj = $webappInstance->getBy(‘url:’, $args);
$obj = $webappInstance->getBy(‘file:’, $args);
$obj = $webappInstance->setBy(‘url:’, $args);
$obj = $webappInstance->setBy(‘file:’, $args);
其中,当 ‘file:’ 时,
$args = array(‘target’=>’xxx’, ‘content’=>’xxx’, ‘islock’=>1, ‘isappend’=>1);
当 ‘url:’ 时,
$args = array(‘target’=>’xxx’, ‘method’=>’xxx’, ‘header’=>array(‘headerxxx’=>’headerxxx_value’), ‘parameter’=>array(‘parameter_1’=>’parameter_1_value’));
上述方法的返回值,遵循 getBy / setBy 的定义,统一规范为
return array(boolean <true|false>, array(‘content’=>$returnObject, ‘errorcode’=>’xxxx’, ‘errordesc’=>’xxxx’));
其中, 成功 true 时,只有 content 的键值; 失败 false 时,只有 errorcode 和 errordesc 。
如下是几个实例:
-gwa2-readObject-example-201605

其中,errorcode 是 -GWA2 特有的一种标记系统,系全局所有,用于全局定位。 默认采用 timestamp 的 YYmmddHHMM 十位数字系统。

—- —- —- —-

当编程语言不再是羁绊时,思想和文化变作为主因,比如上面修改中,为何要将 read/writeObject 融入到 getBy/setBy 中,而不是在 WebApp 中直接调用?

 

发表在 -gMIS, -GWA2, 编程技术, 计算机技术 | 标签为 , , , , , | 一条评论

冰糖雪梨膏儿童宝宝砀山慈梨膏山羊绒围巾女冬英伦百搭围脖双面格子加厚保暖披肩显白黑茶色蓝黑色板栗色中国电信 电信流量5G卡手机卡

-gMIS/-GWA2更新:自动安装程序和MySQLi

五一期间,京津冀可恶的雾霾圈住了奔向原野的心,刚好抽空完善了针对 -gMIS 和 -GWA2 的自动安装程序,同时更新了inc/mysql.class中对 MySQLi的支持,额外的收获,在制作自动安装程序时,发现一种生成 HTML Form的方法,内容附后面。

1. 自动在线安装程序install.php
gMIS、GWA2 提供了自动在线安装程序,将 install.php 脚本程序下载并放置到目标安装目录下,通过浏览器访问该脚本,运行 install.php 即启动安装程序。

gmis-install-start-201604

安装程序首先检查当前安装环境,目前的可读及可写;然后进行源代码的下载,源代码从 –Github-Wadelau 上读取,下载到Zip压缩包后,使用系统自带的相关程序进行解压,然后进行数据库的配置、样例模块Hello的初始化设置。

安装程序最后会引导到项目的初始页面。install.php 详细构成部件及构成请参考下图。

-gMIS自助安装

Figure 7 auto installation in -gMIS

安装程序依赖操作系统所提供的一些操作命令:

  • rm
  • mv
  • wget
  • unzip

2. MySQLi的支持
在较新的 -PHP 环境中,运行 mysql_connect 时,会报错:
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in xxxx file.

MySQLi名称是取自MySQL Improved的缩写,它是MySQL针对PHP所设计的一个扩充模组。虽然PHP原本就有能够存取MySQL的函式库,但是在MySQL 4.1.3版之后,PHP官方强烈推荐使用MySQLi。

mysqli扩展,我们有时称之为MySQL增强扩展,可以用于使用 MySQL4.1.3或更新版本中新的高级特性。mysqli扩展在PHP 5及以后版本中包含。mysqli扩展有一系列的优势,相对于mysql扩展的提升主要有:

  • 面向对象接口
  • prepared语句支持(译注:关于prepare请参阅mysql相关文档)
  • 多语句执行支持
  • 事务支持
  • 增强的调试能力
  • 嵌入式服务支持

在提供了面向对象接口的同时也提供了一个面向过程的接口。mysqli扩展是使用PHP扩展框架构建的,它的源代码在PHP源码目录下的ext/mysqli中。

与PDO (PHP 数据对象)不同,后者提供了一个 数据访问 抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。 PDO 不提供 数据库 抽象层;它不会重写 SQL,也不会模拟缺失的特性。如果需要的话,应该使用一个成熟的抽象层。

由于在 -GWA2 的设计中,已经将存储驱动单独隔离开来,如数据库的驱动,经由 inc/dba.class 来实现,MySQL的连接,默认使用 inc/mysql.class 来实现,因此改进架构对MySQLi的支持,只要修改数据库连接驱动,inc/mysql.class文件中相应的文件即可。

同时,考虑前向兼容没有 MySQLi 的运行环境,需要在过度阶段对MySQL的运行模式进行判断,也即优先判断当前环境是否支持 MySQLi — 如果支持,则启用功能更强大的 MySQLi 增强扩展, 如果不支持,则仍回归使用旧式的 MySQL 扩展。

//-

function _initconnection(){
if ($this->m_link==0){
$real_host = $this->m_host.”:”.$this->m_port;
//echo $real_host,$this->m_user,$this->m_password;
$this->mode = function_exists(‘mysqli_connect’) ? ‘mysqli’ : ‘mysql’;
if($this->mode == ‘mysqli’){
$this->m_link = new mysqli($this->m_host, $this->m_user, $this->m_password, $this->m_name, $this->m_port);
}
else{
$this->m_link = mysql_connect($real_host,$this->m_user,$this->m_password) or die($this->Err(“mysql connect”));
}
//echo $this->Err();
//echo “[“.$this->m_link.”]”;
if ($this->mode == ‘mysql’ && “” != $this->m_name){
mysql_select_db($this->m_name, $this->m_link) or die($this->Err(“use “.$this->m_name));
}
if(get_magic_quotes_gpc()){ $this->ismagicquote = 1; }
}
}

在发起连接之后,其他相关的函数调用或者对象及方法的使用,也要根据此处的 $this->mode 做相应的调整。

3. 一种快捷的 HTML Form 生成方法
HTML Form在 WebApp 中应用非常广泛,是进行数据交互的基本形式之一,构造一个HTML Form有很多种方法,如下是在PHP中,快速生成一个Form表单的方法之一。

# create a form output
function xForm($nextact, $fields, $isfile=0){
$rd = rand(100, 99999);
$form_header = “\n<br/><div id=’formdiv”.$rd.”‘><form name=\”myform$rd\” id=\”myform$rd\” action=\””.$nextact.”\” method=\”post\” “;
if($isfile == 1){
$form_header .= ” enctype=\”multipart/form-data\””;
}
else{
$form_header .= ” enctype=\”application/x-www-form-urlencoded\””;
}
$form_header .= “>”;
$form_footer = “<br/><br/><input type=’submit’ name=’mysubmit’ value=’确定&下一步’ />”;
$form_footer .= “&nbsp;&nbsp;<input name=’myback’ type=’button’ value=’取消&返回’ onclick=’javascript:window.history.back(-1);’ />”;
$form_footer .= “</form></div>”;

$form_field = ”;
$xform = ”;
if(is_array($fields)){
foreach($fields as $k=>$v){
$dispname = ”;
$form_field = ‘<input name=”‘.$k.'” id=”‘.$k.'”‘;
if(is_array($v)){
foreach($v as $k1=>$v1){
if($k1 == ‘dispname’){ $dispname = $v1; }
else{ $form_field .= ” $k1=’$v1′”; }
}
}
else{
print __FILE__.”: illegal setting. 1604161129.”;
}
$form_field = “\n<br/><br/>”.$dispname.”: “.$form_field.” />”;
$xform .= $form_field;
}
}
else if($fields == null){
# no extra field.
}
else{
print __FILE__.”: illegal setting. 1604161130.”;
}

#return $form_header.$form_field.$form_footer;
return $form_header.$xform.$form_footer;

}

使用范例:

$out .= xForm($file.’&step=dolicense’, array(‘hasagree’=>array(‘type’=>’checkbox’, ‘dispname’=>’我已阅读使用协议并同意’)));

将会生成一个完整的,还有一个填写字段的HTML Form表单。

 

发表在 -gMIS, -GWA2, 编程技术, 计算机技术 | 标签为 , , , | 留下评论

冰糖雪梨膏儿童宝宝砀山慈梨膏山羊绒围巾女冬英伦百搭围脖双面格子加厚保暖披肩显白黑茶色蓝黑色板栗色中国电信 电信流量5G卡手机卡

0429首都网络安全日2016及自然域名

参加了0429首都网络安全日第三届活动,差不多花了一天的时间,上午看各种展览,下午参加论坛听专家、院士和学者、大咖的观点分享,有几点出乎所料,记录一下。最安全银行芯片卡(IC卡)有些让人担心;常规的域名会是(存在)安全问题,新式自然域名(-NatureDNS )普及待推广;账号认证及加解密与SOTP。

1. 最安全银行芯片卡(IC卡)有些让人担心
当携带带有NFC(Near-Field Communication,近场通信)功能的芯片式的银行卡经过装置有窃取功能的门或其他装置时,银行卡中的信息会被读取并破解,以下是我的智能芯片银行卡被读取到屏幕截图,跟裸奔一样。卡信息及卡内存储的消费记录,一览无余。

300839_IMGxs20160429xs163717xfJPGx

芯片ic银行卡

理论上,“与磁条卡相比,IC卡安全保密性高,难以伪造;存储容量大”( -R/T2TS ),在这次展示中,如果不关闭NFC功能,安全性岌岌可危。即便关闭了NFC功能,被盗窃之后的破解,也几乎不是问题。加密算法或方式方法的升级迫在眉睫。

2. 常规的域名会是(存在)安全问题,新式自然域名(-NatureDNS )普及待推广
在安全日现场有个安全知识测试,其中考察对知名网站域名的记忆成为对网络安全的一项测试。
工商银行官网-201604
看到这一幕,我想如果使用自然域名  -工商银行-中国工商银行   是否就不会有这些安全问题?
类似的还有:
58同城官网.201604
对应的自然域名: -58  ,  -58同城
taobao官网.201604
对应的自然域名: -taobao  ,  -淘宝   ,   -淘宝网

3. 账号认证及加解密与SOTP
SOTP是Super One-Time Password,在展会上看到的一种账号认证解决方案,公开的资料不多,但也对现有的账号认证体系了做了相应的Literature Review,如下图:
sotp-201604由于此前申请过该领域的专利“登录方法、注册方法、登录装置以及登录和注册系统”( -R/q2TS  ),也发表过相关论文”隐式网络账号设计与研究”(-R/u2TV ),所以感兴趣了解更多。在随后的检索中发现,2015年众人网络的密文传输专利( -R/o2TW ),其算法逻辑如下图所示,原理上看,仍是客户端加密然后传输到服务器端解密,与传统不同或新增的部分是使用了随机键盘,随机键盘在过往也在多种场合见到。
sotp-201604-002

不确定SOTP是否就是上面这个专利,或者跟这个是否有关系,然若能普及,提升用户移动应用的体验,也是好事。

概而言之,首都网络安全日,既有对普通观众的安全知识教育及普及功能,也是行业从业者的盛会。

发表在 -NatureDNS/-自然域名, 社会生活, 计算机技术 | 标签为 , , | 留下评论

山羊绒围巾女冬英伦百搭围脖双面格子加厚保暖披肩显白黑茶色蓝黑色板栗色中国电信 电信流量5G卡手机卡京东制作

自然域名(NatureDNS)都谁在用?哪些网站有自然域名?

自然域名(NatureDNS)自2013年推出,至今已三周年了。

现在有哪些人在用自然域名?哪些网站有自然域名可以使用?有如下两种方式可以获悉。

1. 在自然域名的官方网页( -NatureDNS )上可以看到“正在访问”
via-naturedns-in-homepage

在官网的右侧,有正在被访问的自然域名,读者可以一目了然的看到正在使用中的自然域名列表。通过上图,我们发现  -中国政府网  , -国家发改委  , -微软  等等都开通了自然域名访问途径。 居然还有  -海盗湾   , 这个 你懂的 网站。

2. 在 –  或者 -Google 等搜索引擎中,如果搜索 naturedns 这个关键词,在搜索结果集里能够看到一些访问地址中含有 _via=naturedns 的条目,凡是有此纪录的,则表明该网站已经开通了使用自然域名进行访问的功能。
via-naturedns-in-bing via-naturedns

通过如上,我们可以获知 -北京市工商局  , -中国银行  , -豆瓣网 , -凯迪网  等等,都开通了自然域名访问的途径。

 

 

发表在 -NatureDNS/-自然域名, 服务器运维, 计算机技术 | 标签为 , | 留下评论

床上电脑桌大学生宿舍上铺懒人可折叠小桌子家用寝室简约学习书桌电热蚊香液套装无味婴儿孕妇家用补充液插电式灭蚊液护发素发膜正品修复干枯免洗家用护发补水顺滑女士发热焗油膏书皮纸自粘透明磨砂加厚包书皮小学生一二三四年级上册上学期书膜全套课本书本保护套16k封面外壳防水a4

多线程同步的锁:互斥锁和读写锁

在 -maimai 上读到去阿里的同学考察多线程的锁问题,想起早几年写的一个用Java实现的Session Server(现在还在服役中),起初是基于Java的Synchronized用在方法和对象上,后来改由ConcurrentHashMap做容器。参照 -ChinaUnix 上,ifndef 给例子(-R/92TQ ),我重复了一下这个实验,算是对互斥锁和读写锁的一种回顾。

概念,“线程同步简单的说就是当多个线程共享相同的内存时,当某个线程可以修改变量,而其他线程也可以读取或修改这个变量的时候,就需要对这些线程进行同步,以确保他们在访问变量的存储内容时不会访问到无效的数值。”,确保同步的措施是在操作前进行加锁。

互斥锁, “我们可以把互斥量想成一把锁。在访问共享资源前 对互斥量进行加锁,在访问完后释放互斥量上的锁。
对互斥量进行加锁后,任何其他试图再对该互斥量加锁的线程都会被阻塞直到当前持有锁的线程释放锁。”

读写锁, “当读写锁是写加锁时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。
当读写锁是读加锁时,在这个锁被解锁之前,所有试图以读模式对他进行加锁的线程都可以得到访问权”。

根据如上描述,以及Java SDK中对 Synchronized和ConcurrentHashMap的描述,

Synchronized,“ it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.”(-R/P2Tc )

ConcurrentHashMap,” even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. ”(-R/22Uk ) …“It uses a multitude of locks, each lock controls one segment of the hash. When setting data in a particular segment, the lock for that segment is obtained.”(-R/b2Tc )

从上文的描述来看,Synchronized的实现类似互斥锁,而ConcurrentHashMap的实现类似于读写锁。

实际的例子,若多线程不加锁,运行的结果将很异常,如下程序:

/*
 * pthread mutex lock, rwlock test
* wadelau@ufqi.com, Mon Apr  4 21:32:27 CST 2016
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
int i = 0;
static int COUNT_NUM = 1000000;
static void *thread_1();
static void *thread_2();
int main(void){
int err;
pthread_t th1, th2;
err = pthread_create(&th1, NULL, thread_1, (void *)0);
if(err != 0){
printf(“Create new thread error: %s\n”, strerror(err));
exit(0);
}
err = pthread_create(&th2, NULL, thread_2, (void *)0);
if(err != 0){
printf(“Create new thread error: %s\n”, strerror(err));
exit(0);
}
err = pthread_join(th1, NULL);
if( err != 0){
printf(“Wait thread done error: %s\n”, strerror(err));
exit(0);
}
err = pthread_join(th2, NULL);
if( err != 0){
printf(“Wait thread done error: %s\n”, strerror(err));
exit(0);
}
printf(“i=%d\n”, i);
exit(0);
}
static void *thread_1(void *args){
int j;
for(j=0; j<COUNT_NUM; j++){
i++;
}
pthread_exit((void *)0);
}
static void *thread_2(void *args){
int j;
for(j=0; j<COUNT_NUM; j++){
i++;
}
pthread_exit((void *)0);
}

编译时,使用:

shell> gcc -lpthread xxx.c  -o xxx.out

程序运行十次的结果各不相同:

shell> for i in {0..9}; do ./pthread_nolock.out; done;

i=1042904
i=1064909
i=1026858
i=1038045
i=1133655
i=1085719
i=1029224
i=1089466
i=1020473
i=1041702

对线程使用互斥锁:

static int COUNT_NUM = 1000000;
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
err = pthread_create(&th1, NULL, thread_1, (void *)0);
pthread_mutex_destroy(&mutex);
printf(“i=%d\n”, i);
for(j=0; j<COUNT_NUM; j++){
pthread_mutex_lock(&mutex);
i++;
pthread_mutex_unlock(&mutex);
}

 

再次运行的结果:

shell> for i in {0..9}; do ./pthread_mutex.out ; done;
i=2000000
i=2000000
i=2000000
i=2000000
i=2000000
i=2000000
i=2000000
i=2000000
i=2000000
i=2000000

已经完全符合预期了。 再对线程使用读写锁。代码变化:

static int COUNT_NUM = 1000000;
//pthread_mutex_t mutex;
pthread_rwlock_t rwlock;
//pthread_mutex_init(&mutex, NULL);
pthread_rwlock_init(&rwlock, NULL);
err = pthread_create(&th1, NULL, thread_1, (void *)0);
//pthread_mutex_destroy(&mutex);
pthread_rwlock_destroy(&rwlock);
printf(“i=%d\n”, i);
 volatile int a;
 for(j=0; j<COUNT_NUM; j++){
        pthread_rwlock_rdlock(&rwlock);
        a = i;
        pthread_rwlock_rdlock(&rwlock);
 }

再次运行程序,并计时,看看读写锁的程序时间:

shell> for i in {0..9}; do time ./pthread_rwlock_rd.out ; done;
i=1000000
real    0m0.534s
user    0m0.576s
sys     0m0.460s
i=1000000
real    0m0.333s
user    0m0.392s
sys     0m0.232s
i=1000000
real    0m0.282s
user    0m0.340s
sys     0m0.180s
i=1000000
real    0m0.336s
user    0m0.340s
sys     0m0.288s
i=1000000
real    0m0.278s
user    0m0.324s
sys     0m0.188s
i=1000000
real    0m0.224s
user    0m0.268s
sys     0m0.124s
i=1000000
real    0m0.257s
user    0m0.272s
sys     0m0.192s
i=1000000
real    0m0.261s
user    0m0.296s
sys     0m0.176s
i=1000000
real    0m0.258s
user    0m0.256s
sys     0m0.212s
i=1000000
real    0m0.366s
user    0m0.420s
sys     0m0.272s

 

同时运行使用互斥锁程序并计时,数据如下:

shell> for i in {0..9}; do time ./pthread_mutex_rd.out ; done;
i=2000000
real    0m0.178s
user    0m0.168s
sys     0m0.140s
i=2000000
real    0m0.183s
user    0m0.176s
sys     0m0.140s
i=2000000
real    0m0.177s
user    0m0.188s
sys     0m0.120s
i=2000000
real    0m0.183s
user    0m0.168s
sys     0m0.152s
i=2000000
real    0m0.198s
user    0m0.152s
sys     0m0.196s
i=2000000
real    0m0.168s
user    0m0.124s
sys     0m0.160s
i=2000000
real    0m0.155s
user    0m0.160s
sys     0m0.100s
i=2000000
real    0m0.165s
user    0m0.148s
sys     0m0.136s
i=2000000
real    0m0.160s
user    0m0.140s
sys     0m0.132s
i=2000000
real    0m0.136s
user    0m0.152s
sys     0m0.080s

 

可以发现,读写锁比互斥锁的运行时间要长。然而也应该辩证的看,在一些写操作比较多或是本身需要同步的地方并不多的程序中我们应该使用互斥量,而在读操作远大于写操作的一些程序中我们应该使用读写锁来进行同步。

进一步地,在前文所述的 Session Server中,由使用互斥锁的Synchronized的更改为使用读写锁(读不上锁,写部分区间上锁)的ConcurrentHashMap,算是某种优化。

最后,想陈述的是某种编码风格,code style:

1) 逻辑区块用单行隔开,single blank line for every block
code-style-201604

2)功能区块用双空格,double blank lines for every function block
code-style-201604-002

3)左花括号 { 随上行尾部,右花括号 } 换行顶格, else, else if 换新行.

4)注释要写,能用English or pinyin,不用其他语言。

5)能不写常量字符,尽量不要写。从一开始就这么老师要求学生,每每总是抑制不住写一些常量值。

One more,起初重复运行程序十遍,我用了Awk,没有原因,就是顺手:
shell> echo “” | awk ‘{print “time ./pthread_mutex_rd.out “;}’ |sh

发表在 编程技术, 计算机技术 | 标签为 , , , , , | 留下评论

彩染发剂植物纯自己在家染头发膏女2021流行色显白天然冰糖雪梨膏儿童宝宝砀山慈梨膏山羊绒围巾女冬英伦百搭围脖双面格子加厚保暖披肩显白黑茶色蓝黑色板栗色