手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP

[向东]简单的PHP的任务队列

来自向东:http://www.xiangdong.org/blog/post/1743/

文章太长,不作过多介绍,反正,文章的头部就说明了大概的意思。。。
原文如下:
写了一个简单的队列任务处理。多进程任务,异步任务可能会用到这个(主要是命令行应用)
比如,任务的某个一个环节速度十分不稳定,可能执行几秒,也可能执行几分钟,
我就可以把那个环节包括前面的部分扔进队列,多跑几个进程,同时往队列里面写。
然后后面比较快的环节只跑一个处理任务就OK了。让整体速度达到更好的效果。

write.php: 将任务写入队列

PHP代码
  1. <?php  
  2. /* 
  3. 产生队列 
  4. */  
  5. //用微秒生成队列文件名。因为会有多个队列,所以加了一个identifier来区分各个队列  
  6. function mt($identifier='default')  
  7. {  
  8.         return sprintf("%.6f.%s",strtok(microtime(),' ')+strtok(''),$identifier);  
  9. }  
  10.   
  11. while(1) //实际中尽量不要while(1) 非要while(1)记得任务完成要break  
  12. {  
  13.         if(count(glob('./queue/*.identifier'))>=10) //队列最大长度,不限制的话硬盘可能会受不了哦。  
  14.         {  
  15.                 sleep(1);//记住这里要sleep,否则队列满了cpu占用很高  
  16.                 continue;  
  17.         }  
  18.         $url = 'www.'.time().'.com'//随便举个例子,我用时间戳生成了一个网址  
  19.         echo "$url\r\n";  
  20.         $fp = fopen('./queue/'.mt('identifier'),'w');  
  21.         fwrite($fp,$url);  
  22.         fclose($fp);  
  23.         sleep(1);//这里不需要sleep,我sleep是因为我的任务太简单。  
  24. }  
  25. ?>  

read.php:

PHP代码
  1. <?php  
  2. /* 
  3. 处理队列 
  4. */  
  5.   
  6. while(1) //实际程序最好不要while(1)如果while(1),记得处理完任务要break  
  7. {  
  8.         if($queue = glob('./queue/*.identifier'))  
  9.         {  
  10.                 $q = array_shift($queue);  
  11.                 $url = file_get_contents($q);  
  12.                 echo $url."\r\n";  
  13.                 unlink($q);  
  14.         }  
  15.         sleep(1);//这里要不要sleep或sleep多久自己凭感觉来。  
  16. }  
  17. ?>  

相关的资料:双向队列

baidu和google上没有查到PHP双向队列的资料,搜索到java的双向队列定义如下:双向队列(双端队列)就像是一个队列,但是你可以在任何一端添加或移除元素。
而双端队列是一种数据结构,定义如下:
A deque is a data structure consisting of a list of items, on which the following operations are possible.
* push(D,X) -- insert item X on the rear end of deque D.
* pop(D) -- remove the front item from the deque D and return it.
* inject(D,X) -- insert item X on the front end of deque D.
* eject(D) -- remove the rear item from the deque D and return it.
Write routines to support the deque that take O(1) time per operation.

翻译:双端队列(deque)是由一些项的表组成的数据结构,对该数据结构可以进行下列操作:
push(D,X) 将项X 插入到双端队列D的前端
pop(D) 从双端队列D中删除前端项并将其返回
inject(D,X) 将项X插入到双端队列D的尾端
eject(D) 从双端队列D中删除尾端项并将其返回
编写支持双端队伍的例程,每种操作均花费O(1)时间

百度百科:(deque,全名double-ended queue)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。

转贴一个使用Php数组函数实现该功能的代码:

PHP代码
  1. <?php  
  2. //Input limit double-ende queue  
  3. class DoubleEndedQueue1 {  
  4. var $queue = array();  
  5. function add($var){  
  6.     return array_push($this->queue, $var);  
  7. }  
  8. function frontRemove(){  
  9.     return array_shift($this->queue);  
  10. }  
  11. function rearRemove(){  
  12.     return array_pop($this->queue);  
  13. }  
  14. }  
  15.   
  16. //Output limit double-ende queue  
  17. class DoubleEndedQueue2 {  
  18. var $queue = array();  
  19. function remove(){  
  20.     return array_pop($this->queue);  
  21. }  
  22. function frontAdd($var){  
  23.     return array_unshift($this->queue, $var);  
  24. }  
  25. function rearAdd($var){  
  26.     return array_push($this->queue, $var);  
  27. }  
  28. }  
  29.   
  30. //Test code  
  31. $q = new DoubleEndedQueue1;  
  32. $q->add('aaa');  
  33. $q->add('bbb');  
  34. $q->add('ccc');  
  35. $q->add('ddd');  
  36.   
  37. echo $q->frontRemove();  
  38. echo "<br>";  
  39. echo $q->rearRemove();  
  40. echo "<br>";  
  41. print_r($q->queue);  
  42. ?>  
array_push -- 将一个或多个单元压入数组的末尾(入栈)
array_unshift -- 在数组开头插入一个或多个单元
array_pop -- 将数组最后一个单元弹出(出栈)
array_shift -- 将数组开头的单元移出数组

// 来自 PHP5 in Practice  (U.S.)Elliott III & Jonathan D.Eisenhamer
PHP代码
  1. <?php  
  2. // A library to implement queues in PHP via arrays  
  3. // The Initialize function creates a new queue:  
  4. function &queue_initialize() {  
  5.     // In this case, just return a new array  
  6.     $new = array();  
  7.     return $new;  
  8. }  
  9. // The destroy function will get rid of a queue  
  10. function queue_destroy(&$queue) {  
  11.     // Since PHP is nice to us, we can just use unset  
  12.     unset($queue);  
  13. }  
  14. // The enqueue operation adds a new value unto the back of the queue  
  15. function queue_enqueue(&$queue$value) {  
  16.     // We are just adding a value to the end of the array, so can use the  
  17.     //  [] PHP Shortcut for this.  It's faster than using array_push  
  18.     $queue[] = $value;  
  19. }  
  20. // Dequeue removes the front of the queue and returns it to you  
  21. function queue_dequeue(&$queue) {  
  22.     // Just use array unshift  
  23.     return array_shift($queue);  
  24. }  
  25. // Peek returns a copy of the front of the queue, leaving it in place  
  26. function queue_peek(&$queue) {  
  27.     // Return a copy of the value found in front of queue  
  28.     //  (at the beginning of the array)  
  29.     return $queue[0];  
  30. }  
  31. // Size returns the number of elements in the queue  
  32. function queue_size(&$queue) {  
  33.     // Just using count will give the proper number:  
  34.     return count($queue);  
  35. }  
  36. // Rotate takes the item on the front and sends it to the back of the queue.  
  37. function queue_rotate(&$queue) {  
  38.     // Remove the first item and insert it at the rear.  
  39.     $queue[] = array_shift($queue);  
  40. }  
  41. // Let's use these to create a small queue of data and manipulate it.  
  42. // Start by adding a few words to it:  
  43. $myqueue =& queue_initialize();  
  44. queue_enqueue($myqueue'Opal');  
  45. queue_enqueue($myqueue'Dolphin');  
  46. queue_enqueue($myqueue'Pelican');  
  47. // The queue is: Opal Dolphin Pelican  
  48. // Check the size, it should be 3  
  49. echo '<p>Queue size is: ', queue_size($myqueue), '</p>';  
  50. // Peek at the front of the queue, it should be: Opal  
  51. echo '<p>Front of the queue is: ', queue_peek($myqueue), '</p>';  
  52. // Now rotate the queue, giving us: Dolphin Pelican Opal  
  53. queue_rotate($myqueue);  
  54. // Remove the front element, returning: Dolphin  
  55. echo '<p>Removed the element at the front of the queue: ',  
  56.     queue_dequeue($myqueue), '</p>';  
  57. // Now destroy it, we are done.  
  58. queue_destroy($myqueue);  
  59. ?>  

Tags: 任务队列

几个ZendStudio使用教程

Zendstudio.net,看这个网站的名称就知道,它是专注于zs工具的。
事实上也确实是这样的。站长还提供了一些KEY的生成工具,阿弥陀佛,罪过罪过。。

站长不但对ZS有研究,同时还本着开源的心态,把自己的一些心得整理出来,是flash的哦。大家可以在线观看。。
站长把一些5.5和6.1的使用教程都列出来了。
如果您是使用6.1的话,那就比较方便了。。。直接打开:http://www.zendstudio.net/zend-studio-tutorial/,就可以看到教程。

  1. zend studio 6.1中文视频教程-快速入门
  2. Zend Studio For Eclipse 6.1 视频教程-调试php程序
  3. 让zend studio for eclipse支持xdebug(视频教程)
  4. 在zend studio for eclipse中使用xdebug调试php程序
  5. 在zend studio for eclipse中寻找消失了的zend studio 5.5特色功能(筹备中…)
  6. 使用profile来优化你的php程序性能,提高程序效率(筹备中…)

新站上只有6.1的教程,如果你还在使用ZS 5.5,不用担心,这里也有:

  1. 基础部分:
    1. ZDE的初级安装教程(图)
    2. Zend Studio 5.5.1 界面详细介绍及菜单、工具栏功能详解(图)
    3. Zend Studio 首选项(preferences)功能、设定详解(图)
    4. Zend Studio的特色功能——模板(templates)
    5. zend studio的特色功能——代码片段(code snippets)
    6. Zend Studio快捷键一览表
    7. zend studio 5.5无法打开主界面故障解决方法一例
    8. 修改zend studio 的默认字体 让编辑器看起来更舒服
    9. 用Zend Studio管理数据库—zde的SQL管理器功能介绍

  2. 提高部分:
    1. 服务器调试——Zend Debugger 的安装教程
    2. Zend Studio的远程调试(服务器调试)技术 Zend Debugger(一)
    3. Zend studio的项目管理和服务器调试(视频教程)

-EOF-
写了这么多,也贴了N多链接,就再贴一下zendstudio.net站长的资料吧。。。
大家随便YY去吧

  • 昵称:徐徐
  • 英文名:gently
  • MSN:my-msn
  • 身高:跟姚明没得比
  • 三围:您所在的用户组无权查看该信息
  • 介绍:目前处于IT食物链底层,若在万恶的旧社会,那就是被剥削被压迫的那个阶层。
  • 人生关键词:积极、自信、踏实。

Tags: zendstudio, php, 教程

数组非数字键名引号的必要性

风雪之隅的网站上大多是对PHP的底层进行关注的文章,如果对PHP的核心内容有兴趣不妨多翻阅一下他的网站。

本文的标题,其实是一个老问题了。
大家都知道,PHP对于没有引号的字符串,会当成常量来处理,如果该常量不存在,则直接输出该字符串。也就是多做了几步处理。
事实上,上面的这个知识点,很早就知道,但,不是我自己研究出来的。虽然自己写过代码进行测试过。

雪候鸟则直接从OPCODE上进行查看,给你一个直观印象。好,我们来看看原文吧
地址:http://www.laruence.com/2009/04/24/695.html
内容:
我看到过很多人操作数组的时候, 对于数组中的非数字键名不使用引号,

PHP代码
  1. $array[key] = $value;  

我可以理解有些人可能会觉得这样的代码很”整洁”, 并且也能正常执行.
更甚至,如果他很”幸运的”php配置的好:

PHP代码
  1. error_reporting = ~E_NOTICE  

他也许永远都沉浸在自己的”整洁”风格中, 看不到任何的NOTICE提示, 也不会意识到, 他这么做, 能损失多少的性能~

来, 我们一起来看看:

PHP代码
  1. good.php:  
  2. <?php  
  3.    $array = array();  
  4.    $i = 0;  
  5.    while(++$i < 1000){  
  6.        $array['good'] = 2;  
  7.    }  
  8. ?>  
  9.    
  10. bad.php:  
  11. <?php  
  12.    $array = array();  
  13.    $i = 0;  
  14.    while(++$i < 1000){  
  15.        $array[good] = 2;  
  16.    }  
  17. ?>  
分别看运行时间(多次平均时间):
加引号的:

XML/HTML代码
  1. $ time php -f good.php  
  2.   
  3. real    0m0.013s  
  4. user    0m0.005s  
  5. sys     0m0.007s  
不加引号的:

XML/HTML代码
  1. $ time php -f bad.php  
  2.   
  3. PHP Notice:  Use of undefined constant bad - assumed 'bad' in /home/huixinchen/tmp/bad.php on line  
  4. (此处省略999行NOTICE)  
  5. real    0m0.100s  
  6. user    0m0.020s  
  7. sys     0m0.029s  
看看,差别有多大?
哦, 或许我们应该模拟一下那些”幸运的”人们的情况, 去掉花费在记录NOTICE的开销, 看看~

XML/HTML代码
  1. $ time php -f bad.php  
  2.   
  3. real    0m0.037s  
  4. user    0m0.018s  
  5. sys     0m0.018s  
我们可以看出, 基本上, 使用引号,和不使用引号的效率损失在3倍以上

那么, 这些效率损失到哪里去了呢?

我们分别看下, 俩个文件生成的OPCODE序列:

good.php :

C++代码
  1. filename:       /home/huixinchen/tmp/good.php  
  2. compiled vars:  !0 = $array, !1 = $i  
  3. line     #  op                           fetch          ext  return  operands  
  4. -------------------------------------------------------------------------------  
  5.    2     0  INIT_ARRAY                                       ~0  
  6.          1  ASSIGN                                                   !0, ~0  
  7.    3     2  ASSIGN                                                   !1, 0  
  8.    4     3  PRE_INC                                          $3      !1  
  9.          4  IS_SMALLER                                       ~4      $3, 1000  
  10.          5  JMPZ                                                     ~4, ->9  
  11.    5     6  ZEND_ASSIGN_DIM                                          !0, 'good'  
  12.          7  ZEND_OP_DATA                                             2, $6  
  13.    6     8  JMP                                                      ->3  
  14.    8     9  RETURN                                                   1  
  15.         10* ZEND_HANDLE_EXCEPTION  
bad.php :
C++代码
  1. filename:       /home/huixinchen/tmp/bad.php  
  2. compiled vars:  !0 = $array, !1 = $i  
  3. line     #  op                           fetch          ext  return  operands  
  4. -------------------------------------------------------------------------------  
  5.    2     0  INIT_ARRAY                                       ~0  
  6.          1  ASSIGN                                                   !0, ~0  
  7.    3     2  ASSIGN                                                   !1, 0  
  8.    4     3  PRE_INC                                          $3      !1  
  9.          4  IS_SMALLER                                       ~4      $3, 1000  
  10.          5  JMPZ                                                     ~4, ->10  
  11.    5     6  FETCH_CONSTANT                                   ~5      'bad'  
  12.          7  ZEND_ASSIGN_DIM                                          !0, ~5  
  13.          8  ZEND_OP_DATA                                             2, $7  
  14.    6     9  JMP                                                      ->3  
  15.    8    10  RETURN   

我们可以看出(其实,根据NOTICE的提示也知道), PHP会把没有引号引起来的键名当作是常量去获取, 当找不到的时候, 抛出一个NOTICE, 然后再根据”常量明”生成一个字符串, 然后再讲这个字符串做为键名继续~

聪明的你一定会想到, 可能会出现如下不可预期的错误:

PHP代码
  1. define('key_name' , 'laruence');  
  2. ....  
  3. //省略很多行代码  
  4. $array[key_name] = 2; //变成了 $array['laruence'] = 2;  
  5. //这样的错误, 你会很郁闷吧?  
明白了么? 数组中的非数字键的键名一定要有引号啊~
哦, 还记得有人会说, 那在字符串变量替换的时候, 写引号会导致错误,
恩, 标准写法:
PHP代码
  1. $string = "variable value is {$array['key']}"  

我很赞同:”be lazy”, 但是, lazy也是应该有原则的.

最后, 好的代码,不应该通过关闭error_reporting来伪装.

附注, FETCH_CONSTANT OPCODE中找不到常量的相关逻辑:

C++代码
  1. ....  
  2.         if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {  
  3.             zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",  
  4.                         opline->op2.u.constant.value.str.val,  
  5.                         opline->op2.u.constant.value.str.val);  
  6.             EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;//获取"常量"名字符串  
  7.             zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);//分配空间,生成字符串  
  8.         }  
  9. ....  

 

 

——EOF——

膘叔最受不了的,就是discuz,特别是模版中的变量,全部是不含单引号的。写起来是方便啊。但是性能不敢恭维。所以common.inc.php的前面几句就是error_reporting了。。隐藏掉,看你怎么办,有本事你咬我呀。。

我还能怎么办?

Tags: 风雪之隅, 细节

HTML重构

HTML重构,以前是一个新鲜的东西,我也没有理解,博客园上有人在介绍,还写了三篇。。。

我这里只简单的复制点东西,还是以链接为重吧。(战略篇全文如下)

Refactoring HTML: Improving the Design of Existing Web Applications》是一本精彩的HTML重构指南,作者给出了HTML重构的实践路线和方法。本文是《Refactoring HTML》的读书笔记,按照我的理解将全书的分为:战略篇,战术篇,工具篇。

本文是战略篇:全局方略的角度介绍重构的内涵,原因,时机,目标

嗯哼,我们开始:

 

         进行重构就像打一场仗,而战争的发起是要慎重考虑的,《孙子兵法》里面讲“兵者,国之大事,死生之地,存亡之道,不可不察也。”所以动手重构之前首先要回答下面几个问题:

  • 什么是重构?
  • 为什么进行HTML重构?
  • 什么时候进行HTML重构?
  • HTML重构的目标是什么?
  • 面对质疑:还要重构么?

 

什么是重构 Refactoring?

        本书侧重实战,没有《UML Distilled》那样高屋建瓴的抽象,即使有抽象,抽象层面牵扯的细节过多(这一点在后续的阅读中也可以发现)。这一部分内容我援引了《Refactoring: Improving the Design of Existing Code》对重构的定义:

Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.

Refactor (verb): to restructure software by applying a series of refactorings without changing its observable behavior.

 

为什么进行HTML重构?

抽象地讲,HTML重构的可以让代码更能适应变化,应对系统和领域需求为新功能的开发提供更优秀的基础。

具体地讲,HTML重构可以:

  • 让代码更具有可读性,更容易理解
  • 重构过程中往往有意外的收获:发现隐藏的系统Bug
  • 增强页面可用性, 关注点从设计者开发者转移到使用者
  • 缩短提高页面的呈现时间(Slow pages -Rendering Times)
  • 解决页面浏览器不兼容问题
  • 搜索引擎优化Search Engine Optimization

 

进行HTML重构的时机?

  • 每一次进行重新设计之前;新功能将构建在一个更稳固的基础之上
  • Refactor When You Need to Fix a Bug
  • Refactor As You Do a Code Review
  • 一个原则:勿以善小而不为;重构的过程往往是断断续续的,很少有一个连续的时间给我们进行重构。所以我们只要有机会进行重构,就动手去做吧

 

HTML重构的目标(What  Refactor To ?

  • XHTML
    理由:XHTML更加严格,浏览器不再解析乱作一团的标签而是格式规范的页内容,这时负担从浏览器转移到页面开发者。内容聚合,搜索引擎优化,样式表都可以更好的应用基础。开发者能够更容易调试和解决问题,因为问题更容易定位了。XHTML不能完全解决浏览器兼容问题,但是它能够消除大部分的浏览器不兼容问题已经居功甚伟。主流HTML编辑器都提供对XHTML的支持。XHTML是未来Web应用提供坚实的基础,如:MathXML MusicXML SVG
  •  CSS

理由:将展现层从内容中分离出来。为不同的阅读者提供高可读性。减少代码重复,节省带宽。

  • REST

REST(Representational State Transfer表述性状态转移)是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。REST提出了一些设计概念和准则:

1.网络上的所有事物都被抽象为资源(resource);

2.每个资源对应一个唯一的资源标识(resource identifier);

3.通过通用的连接器接口(generic connector interface)对资源进行操作;

4.对资源的各种操作不会改变资源标识;

5.所有的操作都是无状态的(stateless)。

 

REST之所以能够提高系统的可伸缩性,是因为它强制所有操作都是stateless的,这样就没有context的约束,如果要做分布式、做集群,就不需要考虑context的问题了。同时,它令系统可以有效地使用poolREST对性能的另一个提升来自其对clientserver任务的分配:server只负责提供resource以及操作resource的服务,而client要根据resource中的datarepresentation自己做render。这就减少了服务器的开销。

 

重构的目标不是金科玉律,你没有必要逐一进行实践。你可以按照XHTML->CSS-->Rest的顺序按部就班步步为营,也可以根据实际情况调整重构目标和计划。但是只要你做了,你就可以从重构过程中得到好处。

 

面对质疑:还要重构么?

重构的本质决定了它不是生产性的,重构的完成并没有新功能的产生。所以重构往往面临来自各方面的质疑:

  • 重构就是在浪费时间,我们还是开发新功能吧

 

面对质疑我们给出这样的答案:

  • HTML重构从长远来看为后续开发提供了一个良好的基础,实际上是节省了时间。因为系统更容易添加新功能,更容易维护。重构的过程能让开发者对以前的工作有一个思考,对新人是一个熟悉系统的机会。
  • HTML重构本身并不会占用太多的时间,因为我们有很多自动化的工具可用。
  • HTML重构不需要一个连续的时间,断断续续的时间未尝不可,对于开发者来说,进行重构就像日行一善。

 

HTML重构:战略篇


HTML重构:战术篇

 

HTML重构:工具篇

Tags: html, 重构

免费webService

这个东西,我实在不知道放在哪个分类了。。但因为我是用PHP进行开发的,因此我还是将它归为PHP分类

昨天在Yhustc的博客上看城管操作手册,结果顺便看到了这个免费的webservice列表

yhustc的博客功能越来越强大了,支持直接的ID的文章,现了也支持这种以英文名为路径的文章了,等再强一点,我也考虑换成yblog,哈哈,不过,要等他写转sablog的程序(实在是2.0到现在都没有出来,等的心急了)

对于sablog,我在另外的应用里,已经将它的模版机制全部转为discuz的,因为自己熟悉DZ的模版,改起来更快了。只是不知道何年才会派上用场。。。。

废话说了这么多,上重点的:

某网站支持

国内手机号码归属地查询WEB服务
2400多个城市5日天气预报 WEB服务
股票行情数据 WEB 服务(支持香港、深圳、上海基金、债券和股票;支持多股票同时查询)
中国电视节目预告(电视节目表)
火车时刻表 WEB 服务
IP地址来源搜索 WEB 服务
等等...

是什么网站呢?Look。。。

http://www.webxml.com.cn/zh_cn/web_services.aspx

其他两种我不懂,但wsdl我还是懂的。啥时候有空看看,oh yeah

Tags: webservice