fukuball / jieba-php

"結巴"中文分詞:做最好的 PHP 中文分詞、中文斷詞組件。 / "Jieba" (Chinese for "to stutter") Chinese text segmentation: built to be the best PHP Chinese word segmentation module.
http://jieba-php.fukuball.com
MIT License
1.32k stars 260 forks source link

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

Open createlinux opened 5 years ago

createlinux commented 5 years ago

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

createlinux commented 5 years ago

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

fukuball commented 5 years ago

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

createlinux commented 5 years ago

贴个示例代码

`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代码以守护进程模式运行,速度杠杠的。

461025412 commented 5 years ago

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

createlinux commented 5 years ago

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

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

wyq2214368 commented 4 years ago

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

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

pndx commented 2 years ago

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