本文初步实现了list链表unionlist{intval;char*valStr;};structArrayStringList{intlength;//当前长度intcapacity;//容量字符*数据;/arraypointer};$char){$c[$i]=$char;}returnFFI::cast(FFI::type('char*'),$c);}classFFIHelper{privatestatic$ffi;publicstaticfunctioncreate(){if(empty(self::$ffi)){self::$ffi=\FFI::load("./test.h");}返回自我::$ffi;}}类StringArray{私人$char;私人$ArrayList;公共函数__construct(int$capacity=0){if($capacity>0){$this->create($capacity);}}/***创建列表*/publicfunctioncreate(int$capacity){if(!is_numeric($容量)||$capacity<=0){thrownew\Exception("list长度不能为0");}$this->char=\FFI::new('char*['.($capacity).']',false,true);$this->ArrayList=FFIHelper::create()->new('structArrayStringList');$this->ArrayList->capacity=$capacity;}publicfunctionappend($string){$postion=$this->ArrayList->length;如果($postion>=$this->ArrayList->capacity){$this->grow($this->ArrayList->capacity*2);}$this->char[$postion]=stringToCharPtr($string."\0");如果($postion==0){$this->ArrayList->data=$this->char[0];}$this->ArrayList->length++;}publicfunctionget($postion){return$this->ArrayList->data;}publicfunctiondelete($postion){如果($postion<0){thrownew\Exception("删除位置不能小于0");}if($postion>$this->ArrayList->length){thrownew\Exception("删除位置大于列表长度");}$node=$this->ArrayList->data+$postion;对于($i=$postion+1;$i<$this->ArrayList->length;$i++){}}publicfunctionlength(){return$this->ArrayList->length;}/***增加数组的长度*/publicfunctiongrow($size){if($size<$this->ArrayList->capacity){thrownew\Exception("无需增加列表容量");}$oldData=$this->ArrayList->data;$newData=\FFI::new('char*['.($size).']',false,true);\FFI::memcpy($newData,$this->char,\FFI::sizeof($oldData)*$this->ArrayList->length);$this->ArrayList->data=$newData[0];$this->char=$newData;$this->ArrayList->容量=$尺寸;\FFI::免费($旧数据);}publicfunctiongetList(){return$this->ArrayList;}publicfunction__destruct(){}}$star_memory=memory_get_usage();$start=microtime(true);$list=newStringArray(1000000);var_dump($list->append("aaashello"));var_dump($list->append("aaashello"));var_dump($list->append("aaashello"));$i=0;$data=[];while(true){$list->append(“aaas你好”);//$data[]="aaasyouok".$我;$i++;如果($i>1000000){中断;}}var_dump(FFI::string($list->get(0)));$end_memory=memory_get_usage();$elapsed=microtime(true)-$start;echo"Thattook$elapsedseconds.\n";var_dump((($end_memory-$star_memory)/1024/1024)."M");由于PHP底层对字符串进行了处理,相同的字符串只会存储一次,引用次数用一个计数器来表示,而本文实现的字符串并没有进行处理,所以每次都会重新创建一个新的字符串。通过文中的代码测试,发现即使不对字符串进行处理,内存占用也会优化至少3倍。当然,目前的美中不足就是字符串转成char指针的时间比较长,需要优化。
