php 函数 慢,PHP uniqid函数执行缓慢的有关问题

测试结果:

[myfunc==>uniqid] => Array( [ct] => 10000 [wt] => 39975062 [cpu] => 0 [mu] => 960752 [pmu] => 0)

竟然需要接近40秒的时间生成,单次执行需要3969微秒,也即是0.003969秒生成。如果用户提交表单的同时生成兑换码,最坏情况下需要4分钟才给用户反应,当然可以用消息队列异步生成,但是为啥uniqid需要如此多的时间来生成一个简单的字符串呢?

然后去查看uniqid的实现源码,代码贴在下面

PHP_FUNCTION(uniqid){ char *prefix = "";#if defined(__CYGWIN__) zend_bool more_entropy = 1;#else zend_bool more_entropy = 0;#endif char *uniqid; int sec, usec, prefix_len = 0; struct timeval tv; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &prefix, &prefix_len, &more_entropy)) { return; }#if HAVE_USLEEP && !defined(PHP_WIN32) if (!more_entropy) {#if defined(__CYGWIN__) php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must use 'more entropy' under CYGWIN"); RETURN_FALSE;#else usleep(1);#endif }#endif gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); sec = (int) tv.tv_sec; usec = (int) (tv.tv_usec % 0x100000); /* The max value usec can have is 0xF423F, so we use only five hex * digits for usecs. */ if (more_entropy) { spprintf(&uniqid, 0, "%s%08x%05x%.8F", prefix, sec, usec, php_combined_lcg(TSRMLS_C) * 10); } else { spprintf(&uniqid, 0, "%s%08x%05x", prefix, sec, usec); } RETURN_STRING(uniqid, 0);}

看逻辑也没有复杂的操作,也是对现在时间秒和微秒进行简单的处理,然后写了个简单的测试

int getUniqid( char * uid) { int sec, usec; struct timeval tv; gettimeofday(( struct timeval *) &tv, ( struct timezone *) NULL); sec = ( int) tv. tv_sec; usec = ( int ) (tv.tv_usec % 0x100000); sprintf(uid, "%08x%05x" , sec, usec); return 1;}

执行1W次也就需要2000微秒,这又是为啥?但是我们发现生成的uid中存在大量的重复,这是才注意点原代码中的usleep函数,

加上usleep函数在测试,这次和PHP结果一致也需要将近40秒,usleep在此为了保持每次生成的uid不同。

那问题出现在usleep函数上了,然后在usleep前后加上取间隔时间,代码如下

struct timeval start, end; gettimeofday(( struct timeval *) &start, ( struct timezone *) NULL); usleep(1); gettimeofday(( struct timeval *) &end, ( struct timezone *) NULL); unsigned long space = (end.tv_sec - start. tv_sec) * 1000000 + end.tv_usec - start. tv_usec; spaceCost += space;

最后发现生成1W奖品码需要39.99587739.995877秒,而usleep间隔时间总和39.982442m,通过打印usleep时间发现每次usleep(1)从进程挂起到唤醒需要4000微秒,本来就知道usleep达不到精度,也也相差太远了点。

最后用了下面代码生成奖品码

/** * 生成兑换码并保存到数据库 返回setNo * $pageId 活动ID * $level 奖品等级 * $numbers 生成奖品的个数 */ public static function generateCDKEYAndSave($pageId,$level,$numbers){ $level1Prefix =array(2,5,9,'E','F','M','N','Q','K','Z');//一等奖的前缀 $level2Prefix =array(1,3,7,'A','C','J','R','U','V','X');//二等奖的前置 $level3Prefix = array(4,6,8,'B','D','G','H','I','L','O','P','R','S','T','W','Y');//三等奖的前缀 if(empty($pageId) || empty($level) || empty($numbers)) return false; $levelPrefix =$level1Prefix; if($level==2) $levelPrefix = $level2Prefix; if($level==3) $levelPrefix = $level3Prefix; $codes =array(); $now = time(); for($i=0;$i

附带uuid测试代码

#include #include #include #include unsigned long sleepCost = 0;int getUniqid( char * uid,int times) { struct timeval start, end; gettimeofday(( struct timeval *) &start, ( struct timezone *) NULL); usleep(1); gettimeofday(( struct timeval *) &end, ( struct timezone *) NULL); unsigned long space = (end.tv_sec - start. tv_sec) * 1000000 + end.tv_usec - start. tv_usec; sleepCost += space; if (0 == times%1000) printf ("\n-----sleep cost-------\n%lu usec\n", space); int sec, usec; struct timeval tv; gettimeofday(( struct timeval *) &tv, ( struct timezone *) NULL); sec = ( int) tv. tv_sec; usec = ( int ) (tv.tv_usec % 0x100000); sprintf(uid, "%08x%05x" , sec, usec); return 1;}int main( int argc, char * argv[]) { struct timeval start, end; gettimeofday(( struct timeval *) &start, ( struct timezone *) NULL); for ( int i = 1; i <= 10000; i++) { char data[20]; getUniqid(data,i); } gettimeofday(( struct timeval *) &end, ( struct timezone *) NULL); unsigned long space = (end.tv_sec - start. tv_sec) * 1000000 + end.tv_usec - start. tv_usec; printf( "\n-----cost-------\n% lu usec\n \n-----sum sleep sost-------\n% lu usec\n" , space,sleepCost);}

相关文章

相关视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值