pmmp / ext-chunkutils2 Goto Github PK
View Code? Open in Web Editor NEWPHP extension in C++ implementing performance-sensitive parts of the PocketMine-MP chunk system
License: GNU Lesser General Public License v3.0
PHP extension in C++ implementing performance-sensitive parts of the PocketMine-MP chunk system
License: GNU Lesser General Public License v3.0
Converting YZX subchunks is currently 8% slower than converting XZY subchunks because we currently rotate the byte- and nibble-arrays of their legacy data to XZY order before converting them. This is wasteful and should be avoided by providing custom indexing functions to the conversion routine.
Currently, the way we process palette loading is comically inefficient.
We have to convert whatever data we have into a PHP array of integers, which is subsequently converted into a native array after a bunch of slow, non-vectorizable range checks are done on each of the values. In the end, we actually just want a uint32_t[], so we could just accept a raw byte string with a length of a multiple of 4 instead.
This would be significantly faster for FastChunkSerializer, which currently has to involve useless arrays. (It would need to be accompanied by a function to get the palette as a string directly to avoid using pack() and more array conversions.)
For loading from disk, the benefit would be less significant, as we have to build up an array of blockstate IDs from converting NBT anyway, but the benefit of avoiding a throwaway array and a bunch of unnecessary bounds checks would probably be beneficial nonetheless.
"word array" is very undescriptive and very confusing to new users. "palette offset table" or "palette offset array" might be better.
It might also be worth sealing the palette offset table handling inside its own class.
Hi, I wanted to know if a PR that adds build instructions to the readme would be merged
I, in fact, spent about 30 minutes trying to figure out how to build this
It's currently possible to load a palette offset table which contains offsets that don't exist in the palette. If this happens, an assert will be triggered in debug mode, and/or a value copied from uninitialized memory will be returned.
It may be costlier to validate palettes this way, but ensures users don't experience bugs resulting from corrupted data.
Example code:
require 'vendor/autoload.php';
$p = PalettedBlockArray::fromData(1, str_repeat("\xff", 512), [1]);
var_dump($p->get(0, 0, 0));
This dumps various uninitialized values when run.
$array = new PalettedBlockArray();
var_dump($array->get(0, 0, 0));
The result of get()
here will be uninitialized. This triggers an assertion failure in debug mode.
Conversion gets linearly slower the more unique blocks are in the palette because this code is executing 4096 times per subchunk.
While this is OK for random writes (random writes don't need to be superfast and the overhead of a map would be redundant for random writes), it's not OK for bulk writes of the like that happen during conversions.
This applies to both SubChunkConverter conversions and also to PalettedBlockArray garbage collection (not fastUpsize).
This doesn't cause any memory faults thanks to a lucky coincidence, but it will produce wrong outputs when subchunk coordinate is > 7, instead of throwing an exception.
The vast majority of devices and machines these days are little-endian, but this extension doesn't consider the possibility of being compiled and run on a big-endian platform. If it is run on a big-endian platform, then lots of unpleasant things could occur, like word array corruption, generated chunks having the wrong byte order, client crashes, and so on and so forth.
Initial tests (with extra hacks to stop client crashes) yield the following results:
Since both disk saves and network sends are little endian, it would probably be best to have some big-endian-specific conversion code to translate little-endian packed byte arrays to/from big-endian in-memory format on the interfaces. This would produce some minor performance loss for big-endian platforms, but I think those are rare enough that nobody should really care.
PalettedBlockArray objects are entirely unprepared for either of these circumstances, and as a result the internal state of such objects is uninitialized when unserializing or cloning occurs, resulting in a crash when they are accessed.
The serialization problem is particularly problematic for pthreads transferring data between threads.
ecalloc() will zero it out, and then one of 3 things will happen:
This useless zeroing accounts for 35% of the time taken during light_array_new()
.
Serializing palettes is one of the slowest parts of FastChunkSerializer, due to getPalette() building an array, and then passing the result into pack(), which has slow format code parsing and also has to validate every element to check that it's actually an integer.
We can bypass this entirely by implementing a native binary encoder for PalettedBlockArray, which would make FastChunkSerializer quite a bit faster.
ext-chunkutils2/lib/BlockArrayContainer.h
Line 94 in 5167fb8
:~/php-src-php-7.2.2/ext-chunkutils2# make
/bin/bash /root/php-src-php-7.2.2/ext-chunkutils2/libtool --mode=compile g++ -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++14 -fno-strict-aliasing -DGSL_THROW_ON_CONTRACT_VIOLATION=1 -I. -I/root/php-src-php-7.2.2/ext-chunkutils2 -DPHP_ATOM_INC -I/root/php-src-php-7.2.2/ext-chunkutils2/include -I/root/php-src-php-7.2.2/ext-chunkutils2/main -I/root/php-src-php-7.2.2/ext-chunkutils2 -I/etc/php7/include/php -I/etc/php7/include/php/main -I/etc/php7/include/php/TSRM -I/etc/php7/include/php/Zend -I/etc/php7/include/php/ext -I/etc/php7/include/php/ext/date/lib -I/root/php-src-php-7.2.2/ext-chunkutils2/. -I/root/php-src-php-7.2.2/ext-chunkutils2/gsl/include -DHAVE_CONFIG_H -g -O0 -c /root/php-src-php-7.2.2/ext-chunkutils2/chunkutils2.cpp -o chunkutils2.lo
mkdir .libs
g++ -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++14 -fno-strict-aliasing -DGSL_THROW_ON_CONTRACT_VIOLATION=1 -I. -I/root/php-src-php-7.2.2/ext-chunkutils2 -DPHP_ATOM_INC -I/root/php-src-php-7.2.2/ext-chunkutils2/include -I/root/php-src-php-7.2.2/ext-chunkutils2/main -I/root/php-src-php-7.2.2/ext-chunkutils2 -I/etc/php7/include/php -I/etc/php7/include/php/main -I/etc/php7/include/php/TSRM -I/etc/php7/include/php/Zend -I/etc/php7/include/php/ext -I/etc/php7/include/php/ext/date/lib -I/root/php-src-php-7.2.2/ext-chunkutils2/. -I/root/php-src-php-7.2.2/ext-chunkutils2/gsl/include -DHAVE_CONFIG_H -g -O0 -c /root/php-src-php-7.2.2/ext-chunkutils2/chunkutils2.cpp -fPIC -DPIC -o .libs/chunkutils2.o
/bin/bash /root/php-src-php-7.2.2/ext-chunkutils2/libtool --mode=compile g++ -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++14 -fno-strict-aliasing -DGSL_THROW_ON_CONTRACT_VIOLATION=1 -I. -I/root/php-src-php-7.2.2/ext-chunkutils2 -DPHP_ATOM_INC -I/root/php-src-php-7.2.2/ext-chunkutils2/include -I/root/php-src-php-7.2.2/ext-chunkutils2/main -I/root/php-src-php-7.2.2/ext-chunkutils2 -I/etc/php7/include/php -I/etc/php7/include/php/main -I/etc/php7/include/php/TSRM -I/etc/php7/include/php/Zend -I/etc/php7/include/php/ext -I/etc/php7/include/php/ext/date/lib -I/root/php-src-php-7.2.2/ext-chunkutils2/. -I/root/php-src-php-7.2.2/ext-chunkutils2/gsl/include -DHAVE_CONFIG_H -g -O0 -c /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp -o src/PhpPalettedBlockArray.lo
mkdir src/.libs
g++ -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -std=c++14 -fno-strict-aliasing -DGSL_THROW_ON_CONTRACT_VIOLATION=1 -I. -I/root/php-src-php-7.2.2/ext-chunkutils2 -DPHP_ATOM_INC -I/root/php-src-php-7.2.2/ext-chunkutils2/include -I/root/php-src-php-7.2.2/ext-chunkutils2/main -I/root/php-src-php-7.2.2/ext-chunkutils2 -I/etc/php7/include/php -I/etc/php7/include/php/main -I/etc/php7/include/php/TSRM -I/etc/php7/include/php/Zend -I/etc/php7/include/php/ext -I/etc/php7/include/php/ext/date/lib -I/root/php-src-php-7.2.2/ext-chunkutils2/. -I/root/php-src-php-7.2.2/ext-chunkutils2/gsl/include -DHAVE_CONFIG_H -g -O0 -c /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp -fPIC -DPIC -o src/.libs/PhpPalettedBlockArray.o
In file included from /etc/php7/include/php/Zend/zend_types.h:27:0,
from /etc/php7/include/php/Zend/zend.h:29,
from /etc/php7/include/php/main/php.h:35,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/ZendUtil.h:5,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:5:
/etc/php7/include/php/Zend/zend_operators.h: In function 'zend_long zend_dval_to_lval(double)':
./../main/php_config.h:2614:34: error: 'isfinite' was not declared in this scope
#define zend_finite(a) isfinite(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:114:18: note: in expansion of macro 'zend_finite'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
./../main/php_config.h:2614:34: note: suggested alternative:
#define zend_finite(a) isfinite(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:114:18: note: in expansion of macro 'zend_finite'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
In file included from /usr/include/c++/5/random:38:0,
from /usr/include/c++/5/bits/stl_algo.h:66,
from /usr/include/c++/5/algorithm:62,
from /root/php-src-php-7.2.2/ext-chunkutils2/gsl/include/gsl/span:24,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:2:
/usr/include/c++/5/cmath:601:5: note: 'std::isfinite'
isfinite(_Tp __x)
^
In file included from /etc/php7/include/php/Zend/zend_types.h:27:0,
from /etc/php7/include/php/Zend/zend.h:29,
from /etc/php7/include/php/main/php.h:35,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/ZendUtil.h:5,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:5:
./../main/php_config.h:2594:30: error: 'isnan' was not declared in this scope
#define zend_isnan(a) isnan(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:114:48: note: in expansion of macro 'zend_isnan'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
./../main/php_config.h:2594:30: note: suggested alternative:
#define zend_isnan(a) isnan(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:114:48: note: in expansion of macro 'zend_isnan'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
In file included from /usr/include/c++/5/random:38:0,
from /usr/include/c++/5/bits/stl_algo.h:66,
from /usr/include/c++/5/algorithm:62,
from /root/php-src-php-7.2.2/ext-chunkutils2/gsl/include/gsl/span:24,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:2:
/usr/include/c++/5/cmath:641:5: note: 'std::isnan'
isnan(_Tp __x)
^
In file included from /etc/php7/include/php/Zend/zend_types.h:27:0,
from /etc/php7/include/php/Zend/zend.h:29,
from /etc/php7/include/php/main/php.h:35,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/ZendUtil.h:5,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:5:
/etc/php7/include/php/Zend/zend_operators.h: In function 'zend_long zend_dval_to_lval_cap(double)':
./../main/php_config.h:2614:34: error: 'isfinite' was not declared in this scope
#define zend_finite(a) isfinite(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:125:18: note: in expansion of macro 'zend_finite'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
./../main/php_config.h:2614:34: note: suggested alternative:
#define zend_finite(a) isfinite(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:125:18: note: in expansion of macro 'zend_finite'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
In file included from /usr/include/c++/5/random:38:0,
from /usr/include/c++/5/bits/stl_algo.h:66,
from /usr/include/c++/5/algorithm:62,
from /root/php-src-php-7.2.2/ext-chunkutils2/gsl/include/gsl/span:24,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:2:
/usr/include/c++/5/cmath:601:5: note: 'std::isfinite'
isfinite(_Tp __x)
^
In file included from /etc/php7/include/php/Zend/zend_types.h:27:0,
from /etc/php7/include/php/Zend/zend.h:29,
from /etc/php7/include/php/main/php.h:35,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/ZendUtil.h:5,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:5:
./../main/php_config.h:2594:30: error: 'isnan' was not declared in this scope
#define zend_isnan(a) isnan(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:125:48: note: in expansion of macro 'zend_isnan'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
./../main/php_config.h:2594:30: note: suggested alternative:
#define zend_isnan(a) isnan(a)
^
/etc/php7/include/php/Zend/zend_portability.h:312:52: note: in definition of macro 'UNEXPECTED'
^
/etc/php7/include/php/Zend/zend_operators.h:125:48: note: in expansion of macro 'zend_isnan'
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
^
In file included from /usr/include/c++/5/random:38:0,
from /usr/include/c++/5/bits/stl_algo.h:66,
from /usr/include/c++/5/algorithm:62,
from /root/php-src-php-7.2.2/ext-chunkutils2/gsl/include/gsl/span:24,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:2:
/usr/include/c++/5/cmath:641:5: note: 'std::isnan'
isnan(_Tp __x)
^
In file included from /etc/php7/include/php/Zend/zend.h:29:0,
from /etc/php7/include/php/main/php.h:35,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/ZendUtil.h:5,
from /root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:5:
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray___construct(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:209:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_fromData(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:237:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 3, 3)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_get(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:297:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 3, 3)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_set(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:318:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_replace(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:337:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 2, 2)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_replaceAll(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:354:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 2, 2)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_collectGarbage(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:370:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 0, 1)
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp: In function 'void zim_PhpPalettedBlockArray_getExpectedWordArraySize(zend_execute_data*, zval*)':
/etc/php7/include/php/Zend/zend_types.h:362:22: error: invalid conversion from 'int' to 'zend_expected_type {aka _zend_expected_type}' [-fpermissive]
#define IS_UNDEF 0
^
/etc/php7/include/php/Zend/zend_API.h:736:39: note: in expansion of macro 'IS_UNDEF'
zend_expected_type _expected_type = IS_UNDEF;
^
/root/php-src-php-7.2.2/ext-chunkutils2/src/PhpPalettedBlockArray.cpp:386:2: note: in expansion of macro 'ZEND_PARSE_PARAMETERS_START_EX'
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1)
^
Makefile:196: recipe for target 'src/PhpPalettedBlockArray.lo' failed
make: *** [src/PhpPalettedBlockArray.lo] Error 1
Currently RuntimeException
is used in almost all cases. This is too generic.
In a sane world where block conversion is handled properly, we're almost never going to want the original block IDs that were contained in an anvil, mcregion or legacy leveldb chunk, so the palette will need to be converted in such cases. It would require less boilerplate code and be better for performance if the mappings for this could be injected directly into SubChunkConverter.
A newly converted block array won't need any GC. Right now PM wastes nearly 8% main thread CPU time during world conversion triggering unnecessary GC by calling SubChunk->isEmptyAuthoritative()
, which should be fast for this case and isn't.
We might be able to achieve better performance by either providing a mapping array directly, or using templates to try and get the mapper
inlined.
BlockArrayContainer->set() assumes that if there are 4096 entries in the palette, it must be safe to directly overwrite the palette index pointed to by that offset in the array, because every block in the array must be unique if there are 4096 entries. This assumption is flawed because there may be unused entries in the palette due to modification, which could lead to blockstate corruption in edge cases.
Bits-per-block can be inferred from the size of the offset table (or $words), meaning that having this parameter at all is completely redundant.
The only thing bpb is required for is to know how many bytes to read when decoding palettes from disk, which is not something this extension has to care about. It only needs to care that the provided data is valid. This useless parameter is just providing an extra avenue for potential bugs.
The conversion has to merge the id/meta into a single number in order to find unique entries. However, this results in it having to take the number apart again in order to pass it to the mapper, which is currently always flattenData
, which promptly proceeds to just put it straight back together again. Since the mapper isn't currently inlined, the compiler can't optimise away this useless crap which adds extra overhead.
https://github.com/pmmp/ext-chunkutils2/blob/master/lib/SubChunkConverter.h#L45-L46
https://github.com/pmmp/ext-chunkutils2/blob/master/src/PhpSubChunkConverter.cpp#L14
replaceAll() is not suitable for converting between different domains of IDs. This is problematic if we want to alter the subchunks returned by SubChunkConverter (e.g. to expand metadata size), because replaceAll() may replace new values as well as old ones.
This means that we're currently required to construct an entirely new PalettedBlockArray with the remapped palette instead of just altering the original, which wastes performance.
An alternative to this would be to allow providing a conversion callback to SubChunkConverter, but with the current implementation this would cause significant performance degradation, since the ID conversion callback is called for every block.
Plugin devs are not going to understand what's happening when an assert failure happens (or a segfault).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.