fukuball / jieba-php

"結巴"中文分詞:做最好的 PHP 中文分詞、中文斷詞組件。 / "Jieba" (Chinese for "to stutter") Chinese text segmentation: built to be the best PHP Chinese word segmentation module.

Home Page:http://jieba-php.fukuball.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

作者你好,提个优化内存消耗和加载字典时间的建议

createlinux opened this issue · comments

如果能写成单例模式就好了,结合swoole让实例常驻内存。
然后搭建一个swoole api应用。使用的时候请求api接口,因为实例常驻内存,不用每次都初始化,所以内存消耗和加载速度非常的快。
我测了一下:内存消耗和时间花费都在加载字典上面。停词花费的时间并不多。
我把搜狗的几个词库加进去,10万3000行左右。加载速度特别慢,其他的步骤还好。

  • 内存使用:0.67919158935547|初始化之前| 花费时间:0
  • 内存使用:79.676719665527|结巴初始化完成| 花费时间:0.12999987602234
  • 内存使用:82.161094665527|Finalseg初始化完成| 花费时间:0.14949989318848
  • 内存使用:109.49954223633|JiebaAnalyse初始化完成| 花费时间:0.33049988746643
  • 内存使用:207.0001373291|加载字典完成| 花费时间:2.8549997806549
  • 内存使用:207.19972229004|加载停词完成| 花费时间:2.8864998817444
  • 内存使用:207.19972229004|0 | 花费时间:2.8864998817444
  • 内存使用:208.78179931641|1| 花费时间:3.0029997825623
  • 内存使用:208.78179931641|2| 花费时间:3.0714998245239
  • 内存使用:208.78179931641|3| 花费时间:3.1409997940063
  • 内存使用:208.78179931641|4| 花费时间:3.2099997997284
  • 内存使用:208.78179931641|5| 花费时间:3.2795000076294
  • 内存使用:208.78179931641|6| 花费时间:3.3494999408722
  • 内存使用:208.78179931641|7| 花费时间:3.4249999523163
  • 内存使用:208.78179931641|8| 花费时间:3.4954998493195
  • 内存峰值:224.774879455579| 花费时间:3.5649998188019

解决方法已经出来了:
使用swoole搭建一个http服务器,因为是常驻内存,所以加载字典步骤在服务器启动的时候就已经加载好了。然后查询的时候请求接口就Ok了。速度杠杠的。这个是php终极解决方案。

@GlaryJoker 感謝,我把這個 issue 留著,讓大家可以參考一下作為一種 solution

贴个示例代码

`require_once dirname(DIR).'/vendor/autoload.php';
use Fukuball\Jieba\Jieba;
use Fukuball\Jieba\JiebaAnalyse;
use Fukuball\Jieba\Finalseg;
//Jieba::init(array('mode'=> 'Default','dict' => 'big'));
Jieba::init(array('mode'=>'Search Engine','dict'=>'small'));
Finalseg::init();
JiebaAnalyse::init();
$dictPath = dirname(DIR). '/dict/text_dict.txt';

$stopDictPath = dirname(__DIR__).'/dict/chinese_sw.txt';
Jieba::loadUserDict($dictPath);
JiebaAnalyse::setStopWords($stopDictPath);
$topLimit = 20;

$http = new swoole_http_server("127.0.0.1",9501);
$http->on("request",function($request,$response) use ($topLimit){
$response->header("Content-Type", "application/json; charset=utf-8");

$title = $request->post['title'] ?? 'none';
$content = $request->post['content'] ?? 'none';
$token = $request->post['token'] ?? 'none';       

    $content = urldecode($content);
$title = urldecode($title);

if($token === 'none') $response->end(json_encode([]));

if($title !== 'none' && mb_strlen($title) > 10){
    $titleTags = implode(',',array_keys(JiebaAnalyse::extractTags($title, $topLimit)));
}

if($content !== 'none' && mb_strlen($content) > 15){
	$contentTags = implode(',',array_keys(JiebaAnalyse::extractTags($content,$topLimit)));
}
$response->write(json_encode([
    'title' => $titleTags ?? 'none',
    'content' => $contentTags ?? 'none',
    'ini_memory' => ini_get('memory_limit'),
    'usage' => memory_get_usage()/1024/1024
],JSON_UNESCAPED_UNICODE));
//$response->end();

});

$http->start();`

nginx 配置

`server {
listen 9583;
server_name www.example.com;
large_client_header_buffers 4 128k;

location / {
    proxy_http_version 1.1;
    proxy_set_header Connection "keep-alive";
    proxy_set_header X-Real-IP $remote_addr;       
    proxy_set_header Transfer-Encoding: "gzip";
    proxy_pass http://127.0.0.1:9501;
    
}

}
`

php代码以守护进程模式运行,速度杠杠的。

如何热加载用户自己的词典?

如何热加载用户自己的词典?

可以把字典放redis里,需要改一下源代码,自己可以fork一份

解决方法已经出来了:
使用swoole搭建一个http服务器,因为是常驻内存,所以加载字典步骤在服务器启动的时候就已经加载好了。然后查询的时候请求接口就Ok了。速度杠杠的。这个是php终极解决方案。

我之前也弄了个简单的服务,基于swoole让字典常驻内存。
https://github.com/wyq2214368/laravel-jieba

commented

@wyq2214368 问一下,为什么要controller有构造方法才能在常驻内存?我试了下,controller没有构造方法就没有常驻内存了。