共计 2077 个字符,预计需要花费 6 分钟才能阅读完成。
本文通过 PHP FFI 个性初步实现了 list 链表
<?php
// php 字符串转 C char 指针
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 $ffi;
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 指针耗时比拟久,扔须要优化。
正文完