本文通过PHP FFI个性初步实现了list链表
<code class="php"><?<a href="https://www.gaodaima.com/tag/php" title="查看更多关于php的文章" target="_blank">php</a> // php 字符串转C <a href="https://www.gaodaima.com/tag/char" title="查看更多关于char的文章" target="_blank">char</a>指针 function stringToCharPtr(string $str) { $strChar = str_split($str); $c = FFI::new('char[' . count($strChar) . ']', false); foreach ($strChar as $i => $char) { $c[$i] = $char; } return FFI::cast(FFI::type('char *'), $c); } class FFIHelper { private static $<a href="https://www.gaodaima.com/tag/ffi" title="查看更多关于ffi的文章" target="_blank">ffi</a>; public static function create() { if (empty(self::$ffi)) { self::$ffi = \FFI::load("./test.h"); } return self::$ffi; } } class StringArray { private $char; private $capacity; private $length; public function __construct(int $capacity = 0) { if ($capacity > 0) { $this->create($capacity); } } /** * 创立list */ public function create(int $capacity) { if (!is_numeric($capacity) || $capacity <= 0) { throw new \Exception("list长度不能够为0"); } $this->char = \FFI::new ('char*[' . ($capacity) . ']', false, true); $this->capacity = $capacity; } public function append($string) { $postion = $this->length; if ($postion >= $this->capacity) { $this->grow($this->capacity * 2); } $this->char[$postion] = stringToCharPtr($string . "\0"); $this->length++; } public function get($postion) { return $this->ArrayList->data; } public function delete($postion) { if ($postion < 0) { throw new \Exception("删除地位不能够小于0"); } if ($postion > $this->ArrayList->length) { throw new \Exception("删除地位大于list长度"); } } public function length() { return $this->length; } /** * 减少数组长度 */ public function grow($size) { if ($size < $this->capacity) { throw new \Exception("无需减少list容量"); } $oldData = $this->char; $newData = \FFI::new ('char*[' . ($size) . ']', false, true); \FFI::memcpy($newData, $this->char, \FFI::sizeof($oldData) * $this->length); $this->char = $newData; $this->capacity = $size; \FFI::free($oldData); } public function getList() { return $this->char; } public function __destruct() { } } $star_memory = memory_get_usage(); $start = microtime(true); $list = new StringArray(2000000); $i = 0; $data = []; while (true) { $list->append("hello 你好"); //$data[] = "aaas你好" . $i; $i++; if ($i > 1000000) { break; } } //var_dump(FFI::string($list->get(0))); $end_memory = memory_get_usage(); $elapsed = microtime(true) - $start; echo "That took $elapsed seconds.\n"; var_dump((($end_memory - $star_memory) / 1024 / 1024) . "M");
因为PHP底层字符串做了解决,雷同字符串会只存一次,通过计数器的形式来示意援用的次数,而本文中实现的字符串并未进行认为解决。因此,每次都会从新创立新的字符串。
通过文中代码测试,发现即便为对字符串进行解决,内存占用状况也会至多优化3倍以上,当然目前美中不足的是,字符串转为char指针耗时比拟久,扔须要优化。