CRF 移植

Part 1.

前些天把詞性標註的接口與分詞的接口全並在一起,終於達到了足夠穩定的程度(小數據量自己測試)。爲在線上作爲服務提供之用,而必須改裝爲線程安全的版本,就編程習慣而言問題不大:1.將strtok 的使用換成strtok_r ;2. 非線程間共享的全局變量封類進終端管理類,而全局共享的依然可以寫成全局變量的形式,比如配置文件類CConfig config("res.config")。但其中的線程池的管理類就較麻煩了,設計考慮較多。爲了之後的擴展和速度可能存在的問題,將其設計成終端用戶 一個用戶擁有一個線程池的方式,而不是所有的用戶共用一個線程池,當然也可以設計成這樣,不過因爲用戶之間是不相關的,而且這樣的設計並不複雜,所以暫時採用一個用戶擁有一個線程棧吧。

這其中到是學了一招,以前一直沒用過:一個類的static函數怎樣訪問該類的非static變量?

方式有多種,不過核心都是在調用這個static函數時傳入this指針,在函數體之初將這個void*的參數轉化爲這個類的對象

[CMyClass* myObj = (CMyClass*) arg;]
在操作非static變量時加上this->就可以了。

這個多用在pthread_create這個函數中。

參見:http://hi.baidu.com/ivy_jing/blog/item/abe56f123ecab414213f2e1c.html


Part 2.

線程安全版調通之後就是移植問題了。

由於CRF++本身的Makefile實在是複雜,之間也是直接修改其內部代碼(因爲要優化、提速、查詢解碼等),將其自成的libcrfpp.a作爲本服務器上的靜態調用沒有問題,但是移植到其它服務器就不行了,先是剔除thrift等相關內容後,將其項目中的庫文件主動打包

ar -rc libcrfpp.a *.o .libs/*.o libs/*.a libs/*.so

並將其libcrfpp.so.0也同時提供,而且要將*.so.0的所在目錄放在環境變量裏(加在 ld.so.conf 中,並使其生效(idconfig),  有一段時間忘記生效了,搞死人了,之前是真不知道要這樣,還是同事幫忙才知道的 )。


Part 3.

移植成功之後,還利用了Valgrind 進行了內存查看,解決了每個用例3個字節的泄漏問題,這個比較贊,之前都沒發現。以後要常用Valgrind這個工具。


總結:

真是不移植不知道問題的存在,不給別人提供服務不擔心自已代碼的隱患。

以後寫代碼要從一開始就注意線程安全性,並常用Valgrind這樣的工具,對庫的封裝和使用也要注意。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章