Skip to content

Commit 2a823e5

Browse files
committed
first commit
0 parents  commit 2a823e5

19 files changed

+703
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
php-src
3+
vendor
4+
composer.lock

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "php-src"]
2+
path = php-src
3+
url = git@github.com:php/php-src.git
4+
shallow = true

Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM php:8.1-cli
2+
3+
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
4+
5+
RUN install-php-extensions ffi mbstring
6+
7+
COPY . /app
8+
9+
RUN groupadd -r ffi && useradd -m -g ffi ffi
10+
11+
RUN chown -R ffi /app
12+
13+
USER ffi
14+
15+
WORKDIR /app

Dockerfile-compile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
FROM debian:buster-slim
2+
3+
RUN set -eux; \
4+
apt-get update; \
5+
apt-get install -y --no-install-recommends \
6+
autoconf \
7+
dpkg-dev \
8+
file \
9+
g++ \
10+
gcc \
11+
libc-dev \
12+
make \
13+
pkg-config \
14+
re2c \
15+
build-essential \
16+
bison \
17+
libxml2-dev \
18+
libffi-dev \
19+
libsqlite3-dev \
20+
strace;
21+
22+
COPY . /code
23+
24+
WORKDIR /code/php-src
25+
26+
RUN ./buildconf
27+
RUN ./configure --with-ffi
28+
RUN make
29+
RUN make install
30+
31+
RUN ./buildconf
32+
RUN ./configure --with-ffi
33+
34+
WORKDIR /code

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
The MIT License
2+
3+
Copyright (c) 2020 Sukhachev Anton
4+
5+
Permission is hereby granted, free of charge, to any person obtaining
6+
a copy of this software and associated documentation files (the
7+
"Software"), to deal in the Software without restriction, including
8+
without limitation the rights to use, copy, modify, merge, publish,
9+
distribute, sublicense, and/or sell copies of the Software, and to
10+
permit persons to whom the Software is furnished to do so, subject to
11+
the following conditions:
12+
13+
The above copyright notice and this permission notice shall be
14+
included in all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
UNAME := $(shell uname -s)
2+
HFOLDERS := -I php-src -I php-src/Zend -I php-src/main -I php-src/TSRM
3+
4+
ifeq ($(UNAME), Linux)
5+
COMMAND := g++ -O3 -fPIC -shared $(HFOLDERS) -o library/ffi_linux.so library/ffi.cpp
6+
endif
7+
8+
ifeq ($(UNAME), Darwin)
9+
COMMAND :=clang -shared -undefined dynamic_lookup $(HFOLDERS) -o library/ffi_darwin.dylib library/ffi.cpp
10+
endif
11+
12+
all:
13+
$(COMMAND)

README.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# PHP var_sizeof()
2+
3+
Function for getting full size of any PHP variable in bytes.<br>
4+
It must be more accurate tool to calculate total size of PHP variable than **memory_get_usage()**, but it has [restrictions](#restrictions).
5+
6+
### Requirements
7+
* PHP >= 7.4 (with FFI)
8+
* Linux(x86_64) / Darwin(x86_64)
9+
10+
11+
### How to install
12+
```bash
13+
composer install mrsuh/php-var-sizeof
14+
```
15+
16+
### Functions
17+
```php
18+
int var_sizeof(mixed $var);
19+
```
20+
21+
```php
22+
int var_class_sizeof(mixed $var);
23+
```
24+
25+
## Usage
26+
27+
```php
28+
<?php
29+
30+
require_once __DIR__ . '/vendor/autoload.php';
31+
32+
$int = 1;
33+
printf("variable \$int size: %d bytes\n", var_sizeof($int));
34+
35+
$array = array_fill(0, 100, $a);
36+
printf("variable \$array size: %d bytes\n", var_sizeof($array));
37+
38+
$object = new \stdClass();
39+
printf("variable \$object size: %d bytes\n", var_sizeof($object));
40+
printf("class \$object size: %d bytes\n", var_class_sizeof($object));
41+
```
42+
43+
### var_sizeof vs memory_get_usage
44+
45+
PHP 8.1.2 Linux(x86_64)
46+
47+
| type | var_sizeof(bytes) | memory_get_usage(bytes) |
48+
|----------------------------------------------------|-------------------|-------------------------|
49+
| NULL | 16 | 0 |
50+
| boolean(true) | 16 | 0 |
51+
| integer(1) | 16 | 0 |
52+
| double(1.5) | 16 | 0 |
53+
| string("hello") | 21 | 0 |
54+
| resource | 48 | 416 |
55+
| callable | 72 | 384 |
56+
| array(count: 0, list: true) | 336 | 0 |
57+
| array(count: 100, list: true) | 2,128 | 8,248 |
58+
| array(count: 1,000, list: true) | 16,464 | 36,920 |
59+
| array(count: 10,000, list: true) | 262,224 | 528,440 |
60+
| array(count: 100, list: false) | 5,192 | 0 |
61+
| array(count: 1,000, list: false) | 41,032 | 4,096 |
62+
| array(count: 10,000, list: false) | 655,432 | 126,976 |
63+
| EmptyClass{} | 72 | 40 |
64+
| ClassWithArray{"array(count: 0, list: true)"} | 408 | 56 |
65+
| ClassWithArray{"array(count: 100, list: true)"} | 2,200 | 8,304 |
66+
| ClassWithArray{"array(count: 1,000, list: true)"} | 16,536 | 36,976 |
67+
| ClassWithArray{"array(count: 10,000, list: true)"} | 262,296 | 528,496 |
68+
| ClassWithObject{"EmptyClass{}"} | 144 | 96 |
69+
70+
| type | var_class_sizeof(bytes) | var_sizeof(bytes) | memory_get_usage(bytes) |
71+
|----------------------------------------------------|-------------------------|-------------------|-------------------------|
72+
| EmptyClass{} | 1,362 | 72 | 40 |
73+
| ClassWithArray{"array(count: 0, list: true)"} | 1,494 | 408 | 56 |
74+
| ClassWithArray{"array(count: 100, list: true)"} | 1,494 | 2,200 | 8,304 |
75+
| ClassWithArray{"array(count: 1,000, list: true)"} | 1,494 | 16,536 | 36,976 |
76+
| ClassWithArray{"array(count: 10,000, list: true)"} | 1,494 | 262,296 | 528,496 |
77+
| ClassWithObject{"EmptyClass{}"} | 1,495 | 144 | 96 |
78+
79+
### Restrictions
80+
* objects - you need to use var_sizeof() with var_class_sizeof() to calculate total variable size because class structure load once for one class
81+
* var_class_sizeof() - function calculate current/parent class properties sizes only. It's not calculate functions/callable sizes
82+
* resource/callable - var_sizeof() calculate only major structures
83+
84+
## For contributors
85+
86+
### How to compile library
87+
```bash
88+
cd php-src
89+
./buildconf
90+
./configure
91+
cd ..
92+
make
93+
```

bin/render-table.php

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
<?php
2+
3+
require_once __DIR__ . '/../vendor/autoload.php';
4+
5+
function sdump($var): string
6+
{
7+
switch (true) {
8+
case is_null($var):
9+
case is_resource($var):
10+
return sprintf("%s", gettype($var));
11+
case is_callable($var):
12+
return sprintf("callable");
13+
case is_bool($var):
14+
return sprintf("%s(%s)", gettype($var), $var ? 'true' : 'false');
15+
case is_integer($var):
16+
case is_double($var):
17+
return sprintf("%s(%s)", gettype($var), $var);
18+
case is_string($var):
19+
return sprintf("%s(\"%s\")", gettype($var), $var);
20+
case is_array($var):
21+
22+
$isList = array_keys($var) === range(0, count($var) - 1) || empty($var);
23+
24+
return sprintf("%s(count: %s, list: %s)", gettype($var), number_format(count($var)), $isList ? 'true' : 'false');
25+
26+
case is_object($var):
27+
$reflection = new ReflectionObject($var);
28+
$properties = [];
29+
foreach ($reflection->getProperties() as $reflectionProperty) {
30+
$properties[] = sdump($reflectionProperty->getValue($var));
31+
}
32+
33+
return sprintf("%s%s", get_class($var), str_replace(['[', ']'], ['{', '}'], json_encode($properties)));
34+
}
35+
36+
return '';
37+
}
38+
39+
class EmptyClass
40+
{
41+
}
42+
43+
class ClassWithArray
44+
{
45+
public array $array;
46+
47+
public function __construct(array $array)
48+
{
49+
$this->array = $array;
50+
}
51+
}
52+
53+
class ClassWithObject
54+
{
55+
public EmptyClass $container;
56+
57+
public function __construct()
58+
{
59+
$this->container = new EmptyClass();
60+
}
61+
}
62+
63+
$tableCommonBuilder = new \MaddHatter\MarkdownTable\Builder();
64+
$tableCommonBuilder->headers(['type', 'var_sizeof(bytes)', 'memory_get_usage(bytes)']);
65+
66+
$tableObjectBuilder = new \MaddHatter\MarkdownTable\Builder();
67+
$tableObjectBuilder->headers(['type', 'var_class_sizeof(bytes)', 'var_sizeof(bytes)', 'memory_get_usage(bytes)']);
68+
69+
function addCommonRow(\MaddHatter\MarkdownTable\Builder $tableBuilder, $var, int $memory)
70+
{
71+
$tableBuilder->row([sdump($var), number_format(var_sizeof($var)), number_format($memory)]);
72+
}
73+
74+
function addObjectRow(\MaddHatter\MarkdownTable\Builder $tableBuilder, $var, int $memory)
75+
{
76+
$tableBuilder->row([sdump($var), number_format(var_class_sizeof($var)), number_format(var_sizeof($var)), number_format($memory)]);
77+
}
78+
79+
$memory = memory_get_usage();
80+
$null = null;
81+
$memoryUsage = memory_get_usage() - $memory;
82+
addCommonRow($tableCommonBuilder, $null, $memoryUsage);
83+
84+
$memory = memory_get_usage();
85+
$bool = true;
86+
$memoryUsage = memory_get_usage() - $memory;
87+
addCommonRow($tableCommonBuilder, $bool, $memoryUsage);
88+
89+
$memory = memory_get_usage();
90+
$integer = 1;
91+
$memoryUsage = memory_get_usage() - $memory;
92+
addCommonRow($tableCommonBuilder, $integer, $memoryUsage);
93+
94+
$memory = memory_get_usage();
95+
$double = 1.5;
96+
$memoryUsage = memory_get_usage() - $memory;
97+
addCommonRow($tableCommonBuilder, $double, $memoryUsage);
98+
99+
$memory = memory_get_usage();
100+
$string = 'hello';
101+
$memoryUsage = memory_get_usage() - $memory;
102+
addCommonRow($tableCommonBuilder, $string, $memoryUsage);
103+
104+
$memory = memory_get_usage();
105+
$resource = fopen('php://memory', 'r');
106+
$memoryUsage = memory_get_usage() - $memory;
107+
addCommonRow($tableCommonBuilder, $resource, $memoryUsage);
108+
109+
$memory = memory_get_usage();
110+
$callable = function () {
111+
};
112+
$memoryUsage = memory_get_usage() - $memory;
113+
addCommonRow($tableCommonBuilder, $callable, $memoryUsage);
114+
115+
$memory = memory_get_usage();
116+
$array0 = [];
117+
$memoryUsage = memory_get_usage() - $memory;
118+
addCommonRow($tableCommonBuilder, $array0, $memoryUsage);
119+
120+
$memory = memory_get_usage();
121+
$array100 = array_fill(0, 100, null);
122+
$memoryUsage = memory_get_usage() - $memory;
123+
addCommonRow($tableCommonBuilder, $array100, $memoryUsage);
124+
125+
$memory = memory_get_usage();
126+
$array1000 = array_fill(0, 1000, null);
127+
$memoryUsage = memory_get_usage() - $memory;
128+
addCommonRow($tableCommonBuilder, $array1000, $memoryUsage);
129+
130+
$memory = memory_get_usage();
131+
$array10000 = array_fill(0, 10000, null);
132+
$memoryUsage = memory_get_usage() - $memory;
133+
addCommonRow($tableCommonBuilder, $array10000, $memoryUsage);
134+
135+
$memory = memory_get_usage();
136+
$array100 = array_fill(0, 99, null);
137+
$array100['index'] = null;
138+
$memoryUsage = memory_get_usage() - $memory;
139+
addCommonRow($tableCommonBuilder, $array100, $memoryUsage);
140+
141+
$memory = memory_get_usage();
142+
$array1000 = array_fill(0, 999, null);
143+
$array1000['index'] = null;
144+
$memoryUsage = memory_get_usage() - $memory;
145+
addCommonRow($tableCommonBuilder, $array1000, $memoryUsage);
146+
147+
$memory = memory_get_usage();
148+
$array10000 = array_fill(0, 9999, null);
149+
$array10000['index'] = null;
150+
$memoryUsage = memory_get_usage() - $memory;
151+
addCommonRow($tableCommonBuilder, $array10000, $memoryUsage);
152+
153+
$memory = memory_get_usage();
154+
$emptyClass = new EmptyClass();
155+
$memoryUsage = memory_get_usage() - $memory;
156+
addCommonRow($tableCommonBuilder, $emptyClass, $memoryUsage);
157+
addObjectRow($tableObjectBuilder, $emptyClass, $memoryUsage);
158+
159+
$memory = memory_get_usage();
160+
$classWithArray0 = new ClassWithArray([]);
161+
$memoryUsage = memory_get_usage() - $memory;
162+
addCommonRow($tableCommonBuilder, $classWithArray0, $memoryUsage);
163+
addObjectRow($tableObjectBuilder, $classWithArray0, $memoryUsage);
164+
165+
$memory = memory_get_usage();
166+
$classWithArray100 = new ClassWithArray(array_fill(0, 100, null));
167+
$memoryUsage = memory_get_usage() - $memory;
168+
addCommonRow($tableCommonBuilder, $classWithArray100, $memoryUsage);
169+
addObjectRow($tableObjectBuilder, $classWithArray100, $memoryUsage);
170+
171+
$memory = memory_get_usage();
172+
$classWithArray1000 = new ClassWithArray(array_fill(0, 1000, null));
173+
$memoryUsage = memory_get_usage() - $memory;
174+
addCommonRow($tableCommonBuilder, $classWithArray1000, $memoryUsage);
175+
addObjectRow($tableObjectBuilder, $classWithArray1000, $memoryUsage);
176+
177+
$memory = memory_get_usage();
178+
$classWithArray10000 = new ClassWithArray(array_fill(0, 10000, null));
179+
$memoryUsage = memory_get_usage() - $memory;
180+
addCommonRow($tableCommonBuilder, $classWithArray10000, $memoryUsage);
181+
addObjectRow($tableObjectBuilder, $classWithArray10000, $memoryUsage);
182+
183+
$memory = memory_get_usage();
184+
$classWithObject = new ClassWithObject();
185+
$memoryUsage = memory_get_usage() - $memory;
186+
addCommonRow($tableCommonBuilder, $classWithObject, $memoryUsage);
187+
addObjectRow($tableObjectBuilder, $classWithObject, $memoryUsage);
188+
189+
echo sprintf("PHP %s %s(%s)\n\n", phpversion(), php_uname('s'), php_uname('m'));
190+
echo $tableCommonBuilder->render();
191+
echo "\n";
192+
echo $tableObjectBuilder->render();

0 commit comments

Comments
 (0)