Maksim, database management systems developer.
1. Performance optimization basics.
2. Low-level optimizations.
3. Abstractions and Algorithms.
4. Tools.
5. Examples.
6. Sorting.
CI/CD Pipeline.
Performance Tests.
Introspection.
Libraries.
Latency numbers.
My presentation from CPP Russia 2022 ClickHouse performance optimization practices:
CI/CD Pipeline is required.
The more checks the better.
Functional, Integration tests. Fuzzers.
Performance tests.
Run all tests with all available sanitizers (ASAN, MSAN, UBSAN, TSAN).
Project specific tests. Example: custom stress tests, Jepsen tests.
Must be able to report about performance changes (improvement or regression).
Collect different statistics during each performance test run. Can be useful for later debugging:
1. Processor metrics (CPU cycles, cache misses same as perf-stat).
2. Project specific profile events (read bytes from disk, transferred bytes over network, etc).
Write test in special XML configuration.
<test>
<substitutions>
<substitution>
<name>func</name>
<values>
bitCount
bitNot
abs
...
</values>
</substitution>
<substitution>
<name>expr</name>
<values>
<value>number</value>
<value>toUInt32(number)</value>
...
</values>
</substitution>
</substitutions>
<query>SELECT {func}({expr}) FROM numbers(100000000) FORMAT Null</query>
</test>
It is not trivial to implement infrastructure for performance testing.
https://clickhouse.com/blog/testing-the-performance-of-click-house/
Helps find performance regressions.
Tool that can help to find places where performance can be improved:
1. Try different allocators, different libraries.
2. Try different compiler options (loop unrolling, inline threshold)
3. Enable AVX/AVX2/AVX512 for build.
Ideally collect as much information as possible in user space.
Important to check if something is improved because of your change, or to understand why there is some degradation.
Can be used as additional statistics that are collected during performance tests.
RealTimeMicroseconds, UserTimeMicroseconds, SystemTimeMicroseconds, SoftPageFaults, HardPageFaults using getrusage system call.
Collect :taskstats from procFS (Also support Netlink interface).
OSCPUVirtualTimeMicroseconds, OSCPUWaitMicroseconds (when /proc/thread-self/schedstat is available). OSIOWaitMicroseconds (when /proc/thread-self/stat is available). OSReadChars, OSWriteChars, OSReadBytes, OSWriteBytes (when /proc/thread-self/io is available)
Project specific profile events (read bytes from disk, transferred bytes over network, etc).
 In ClickHouse there are external libraries for:
1. Different algorithms for parsing floats, json (multiple libraries).
2. A lot of integrations.
3. Embedded storages.
4. LLVM for JIT compilation.
5. libcxx (C++ standard library).
One of the easiest method to try to improve something is to reuse generic components with components from highly optimized library:
1. Abseil. Example: Replace std::unordered_map with absl::flat_hash_map if you do not need pointer stability.
2. Folly.
3. Boost.
Do not use outdated libraries.
Latency Comparison Numbers ---------------------------------- L1 cache reference 0.5 ns Branch mispredict 5 ns L2 cache reference 7 ns 14x L1 cache Mutex lock/unlock 25 ns Main memory reference 100 ns 20x L2 cache, 200x L1 cache Compress 1K bytes with Zippy 3,000 ns 3 us Send 1K bytes over 1 Gbps network 10,000 ns 10 us Read 4K randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD Read 1 MB sequentially from memory 250,000 ns 250 us Round trip within same datacenter 500,000 ns 500 us
void plus(int64_t * __restrict a,
int64_t * __restrict b,
int64_t * __restrict c,
size_t size)
{
for (size_t i = 0; i < size; ++i) {
c[i] = b[i] + a[i];
}
}
If there is no __restrict modifier specified for pointers, the compiler may not vectorize the loop.
Or it will vectorize the loop but put a couple of runtime checks at the beginning of the function to make sure that the arrays do not overlap.
Compile program with AVX2 instruction set and -fno-unroll-loops.
$ /usr/bin/clang++-15 -mavx2 -fno-unroll-loops -O3 -S vectorization_example.cpp
In the final assembly, there are two loops. Vectorized loop that processes 4 elements at a time:
.LBB0_4: # =>This Inner Loop Header: Depth=1
vmovdqu (%rdi,%rax,8), %ymm0
vpaddq (%rsi,%rax,8), %ymm0, %ymm0
vmovdqu %ymm0, (%rdx,%rax,8)
addq $4, %rax
cmpq %rax, %r8
jne .LBB0_4
Scalar loop:
LBB0_6: # =>This Inner Loop Header: Depth=1
movq (%rdi,%r8,8), %rax
addq (%rsi,%r8,8), %rax
movq %rax, (%rdx,%r8,8)
incq %r8
cmpq %r8, %rcx
jne .LBB0_6
Additionally, if we compile this example without -fno-unroll-loops and look at the generated loop, we will see that compiler unrolled vectorized loop, which now processes 16 elements at a time.
.LBB0_4: # =>This Inner Loop Header: Depth=1
vmovdqu (%rdi,%rax,8), %ymm0
vmovdqu 32(%rdi,%rax,8), %ymm1
vmovdqu 64(%rdi,%rax,8), %ymm2
vmovdqu 96(%rdi,%rax,8), %ymm3
vpaddq (%rsi,%rax,8), %ymm0, %ymm0
vpaddq 32(%rsi,%rax,8), %ymm1, %ymm1
vpaddq 64(%rsi,%rax,8), %ymm2, %ymm2
vpaddq 96(%rsi,%rax,8), %ymm3, %ymm3
vmovdqu %ymm0, (%rdx,%rax,8)
vmovdqu %ymm1, 32(%rdx,%rax,8)
vmovdqu %ymm2, 64(%rdx,%rax,8)
vmovdqu %ymm3, 96(%rdx,%rax,8)
addq $16, %rax
cmpq %rax, %r8
jne .LBB0_4
There is a very useful tool that can help you identify places where the compiler does or does not perform vectorization to avoid assembly checking.
You can add -Rpass=loop-vectorize, -Rpass-missed=loop-vectorize and -Rpass-analysis=loop-vectorize options to clang. There are similar options for gcc.
$ /usr/bin/clang++-15 -mavx2 -Rpass=loop-vectorize -Rpass-missed=loop-vectorize
-Rpass-analysis=loop-vectorize -O3
vectorization_example.cpp:7:5: remark: vectorized loop (vectorization width: 4,
interleaved count: 4) [-Rpass=loop-vectorize]
for (size_t i = 0; i < size; ++i) {
class SumFunction
{
public:
void sumIf(int64_t * values, int8_t * filter, size_t size);
int64_t sum = 0;
};
void SumFunction::sumIf(int64_t * values, int8_t * filter, size_t size)
{
for (size_t i = 0; i < size; ++i) {
sum += filter[i] ? 0 : values[i];
}
}
/usr/bin/clang++-15 -mavx2 -O3 -Rpass-analysis=loop-vectorize -Rpass=loop-vectorize
-Rpass-missed=loop-vectorize -c vectorization_example.cpp
vectorization_example.cpp:31:13: remark: loop not vectorized: unsafe dependent
memory operations in loop. Use #pragma loop distribute(enable) to allow loop
distribution to attempt to isolate the offending operations into a separate loop
Unknown data dependence. Memory location is the same as accessed at
vectorization_example.cpp:31:13 [-Rpass-analysis=loop-vectorize]
sum += filter[i] ? 0 : values[i];
vectorization_example.cpp:28:9: remark: loop not vectorized
[-Rpass-missed=loop-vectorize]
for (size_t i = 0; i < size; ++i) {
Make local sum inside sumIf function:
class SumFunction
{
public:
void sumIf(int64_t * values, int8_t * filter, size_t size);
int64_t sum = 0;
};
void SumFunction::sumIf(int64_t * values, int8_t * filter, size_t size)
{
int64_t local_sum = 0;
for (size_t i = 0; i < size; ++i) {
local_sum += filter[i] ? 0 : values[i];
}
sum += local_sum;
}
/usr/bin/clang++-15 -mavx2 -O3 -Rpass-analysis=loop-vectorize -Rpass=loop-vectorize
-Rpass-missed=loop-vectorize -c vectorization_example.cpp
vectorization_example.cpp:31:5: remark: vectorized loop (vectorization width: 4,
interleaved count: 4) [-Rpass=loop-vectorize]
for (size_t i = 0; i < size; ++i) {
.LBB0_5: # =>This Inner Loop Header: Depth=1
vmovd (%rdx,%rax), %xmm5 # xmm5 = mem[0],zero,zero,zero
vmovd 4(%rdx,%rax), %xmm6 # xmm6 = mem[0],zero,zero,zero
vmovd 8(%rdx,%rax), %xmm7 # xmm7 = mem[0],zero,zero,zero
vmovd 12(%rdx,%rax), %xmm1 # xmm1 = mem[0],zero,zero,zero
vpcmpeqb %xmm5, %xmm8, %xmm5
vpmovsxbq %xmm5, %ymm5
vpcmpeqb %xmm6, %xmm8, %xmm6
vpmovsxbq %xmm6, %ymm6
vpcmpeqb %xmm7, %xmm8, %xmm7
vpmovsxbq %xmm7, %ymm7
vpcmpeqb %xmm1, %xmm8, %xmm1
vpmaskmovq -96(%r8,%rax,8), %ymm5, %ymm5
vpmovsxbq %xmm1, %ymm1
vpmaskmovq -64(%r8,%rax,8), %ymm6, %ymm6
vpaddq %ymm0, %ymm5, %ymm0
vpmaskmovq -32(%r8,%rax,8), %ymm7, %ymm5
vpaddq %ymm2, %ymm6, %ymm2
vpmaskmovq (%r8,%rax,8), %ymm1, %ymm1
vpaddq %ymm3, %ymm5, %ymm3
vpaddq %ymm4, %ymm1, %ymm4
addq $16, %rax
cmpq %rax, %r9
jne .LBB0_5
Each algorithm and data structure can be tuned using different low-level optimizations:
1. Remove unnecessary copying.
2. Decrease amount of virtual function calls.
3. Tune data layout.
4. Specializations for special cases.
5. CPU dispatch.
6. JIT compilation.
For example your binary distributed only with old instruction set SSE4.2.
For AVX, AVX2, AVX512 instructions need to use runtime instructions specialization using CPUID.
It is important that compilers can vectorize even complex loops. We can rely on this.
Blog post about CPU dispatch:
JIT compilation can transform dynamic configuration into static configuration.
Not all functions can be easily compiled, not all algorithms can be easily compiled.
Has its own costs (compilation time, memory, maintenance).
But can greatly improve performance in special cases.
Blog post about JIT in ClickHouse:
For high performance systems interfaces must be determined by data structures and algorithms.
Top-down approach does not work.
High-performance system must be designed concentrating on doing at least a single task efficiently.
Designed from hardware capabilities.
There is no silver bullet, or best algorithm for any task.
Try to choose the fastest possible algorithm/algorithms for your specific task.
Performance must be evaluated on real data.
Most of the algorithms are affected by data distribution.
Real time system and per-process resource (CPU, Memory) utilization - top, htop.
CPU per-process-function - perf top.
Performance counter statistics - perf stat.
CPU Profile - FlameGraphs, perf record.
Preparing and analyzing data - clickhouse-local.
IO/Network - iostat, dstat, sar.
High CPU utilization does not mean your program is fast. There can be several reasons:
1. Program is Memory/IO bound.
2. Inneficient algorithms, data structures.
3. Excessive copying.
perf top gives high level view of what program is doing during benchmark, and which functions cost most of the CPU.
Useful to check underlying assembly and try to figure out where the problem is.
But need to be aware that CPU can just wait memory.
In aggregation benchmark if we check the hottest function assembly we will see:
Underlying code:
namespace ZeroTraits
{
template <typename T>
bool check(const T x) { return x == T{}; } /// test %rax, %rax
}
static bool isZero(const Key & key, const State & /*state*/)
{
return ZeroTraits::check(key);
}
Program is memory bound.
Useful tool to check something in isolation.
Assume you want to improve performance of some critical data structure like hash table or algorithm like sorting.
Best way to do this, is to isolate this into separate small program and benchmark it.
Lets take a look of integer hash table benchmark.
perf stat integer_hash_tables_benchmark ch_hash_map UInt64 WatchID.bin 8873898
CH HashMap:
Elapsed: 0.604 (14688324.619 elem/sec.), map size: 8871741
Performance counter stats for 'integer_hash_tables_benchmark ch_hash_map UInt64 WatchID.bin 8873898':
683.90 msec task-clock # 0.968 CPUs utilized
124 context-switches # 181.313 /sec
0 cpu-migrations # 0.000 /sec
252,549 page-faults # 369.277 K/sec
2,948,142,592 cycles # 4.311 GHz (83.10%)
286,182,948 stalled-cycles-frontend # 9.71% frontend cycles idle (83.07%)
1,276,430,369 stalled-cycles-backend # 43.30% backend cycles idle (83.35%)
2,025,692,416 instructions # 0.69 insn per cycle
# 0.63 stalled cycles per insn (83.64%)
356,845,237 branches # 521.779 M/sec (83.65%)
21,268,813 branch-misses # 5.96% of all branches (83.20%)
0.706636444 seconds time elapsed
0.479112000 seconds user
0.203622000 seconds sys
Lets take a look of integer hash table benchmark.
perf stat integer_hash_tables_benchmark std_unordered_map UInt64 WatchID.bin 8873898
std::unordered_map:
Elapsed: 2.473 (3588276.141 elem/sec.), map size: 8871741
Performance counter stats for 'integer_hash_tables_benchmark std_unordered_map UInt64 WatchID.bin
8873898':
3,262.13 msec task-clock # 0.999 CPUs utilized
317 context-switches # 97.176 /sec
1 cpu-migrations # 0.307 /sec
142,567 page-faults # 43.704 K/sec
14,343,682,708 cycles # 4.397 GHz (83.33%)
258,005,531 stalled-cycles-frontend # 1.80% frontend cycles idle (83.33%)
12,555,340,086 stalled-cycles-backend # 87.53% backend cycles idle (83.34%)
4,104,335,191 instructions # 0.29 insn per cycle
# 3.06 stalled cycles per insn (83.33%)
735,241,554 branches # 225.387 M/sec (83.33%)
10,749,318 branch-misses # 1.46% of all branches (83.33%)
3.264492212 seconds time elapsed
3.060895000 seconds user
0.199797000 seconds sys
We see that standard hash map is much slower. Lets check cache misses and cache references.
perf stat -e cache-misses,cache-references integer_hash_tables_benchmark std_unordered_map
UInt64 WatchID.bin 8873898
std::unordered_map:
Elapsed: 2.484 (3572510.427 elem/sec.), map size: 8871741
Performance counter stats for 'integer_hash_tables_benchmark std_unordered_map UInt64 WatchID.bin
8873898':
124,089,032 cache-misses # 35.893 % of all cache refs
345,719,343 cache-references
3.296088157 seconds time elapsed
3.117693000 seconds user
0.175644000 seconds sys
perf stat -e cache-misses,cache-references integer_hash_tables_benchmark ch_hash_map
UInt64 WatchID.bin 8873898
CH HashMap:
Elapsed: 0.580 (15306059.985 elem/sec.), map size: 8871741
Performance counter stats for 'integer_hash_tables_benchmark ch_hash_map UInt64 WatchID.bin
8873898':
32,774,660 cache-misses # 28.599 % of all cache refs
114,602,476 cache-references
0.654290201 seconds time elapsed
0.452424000 seconds user
0.200187000 seconds sys
ClickHouse Hash Table performs 3.8 times less cache misses.
There are a lot of additional things that you can tune to reduce perf variations. Example:
1. Bind program to specific CPUs.
2. Use tmpfs.
Can be build for CPU, Memory.
git clone https://github.com/brendangregg/FlameGraph
cd FlameGraph
perf record -F 99 -a -g or perf record -F 99 -a -g -p process_pid
perf script | ./stackcollapse-perf.pl > out.perf-folded
./flamegraph.pl out.perf-folded > perf.svg
By default perf uses frame-pointer stack unwinding, so to see all traces your program must be compiled with -fno-omit-frame-pointer.
Example of broken Flame Graph:
Use DWARF stack unwinding:
perf record -F 99 -a -g -p 32238 -g --call-graph=dwarf
I use clickhouse-local almost every day:
1. Preprocess data for benchmarks.
2. Analyze data for benchmarks.
3. Analyze benchmark results.
4. Analyze output of different tools.
Amount of non vectorized loops in ClickHouse AggregateFunctions, after compile with -Rpass=loop-vectorize, -Rpass-missed=loop-vectorize and -Rpass-analysis=loop-vectorize.
SELECT count() FROM (SELECT splitByChar(' ', line)[1] AS file_with_line
FROM file("out.txt", LineAsString)
WHERE line LIKE '%loop not vectorized%'
AND line LIKE '%ClickHouseClang/src/AggregateFunctions/%'
GROUP BY file_with_line
);
┌─count()─┐
│ 403 │
└─────────┘
Background pool produce a lot of calls to wait with timeout for Poco::NotificationQueue.
Such calls are also visible on flame graphs and for some benchmarks can take 15-20% of CPU time.
This timeout was added long time ago to avoid rare deadlock with Poco::NotificationQueue.
Solution was to replace Poco::NotificationQueue to conditional variable and queue.
INSERT INTO FUNCTION file('test_file_{_partition_id}', 'TSV',
'partition_id UInt64, value1 UInt64, value2 UInt64, value3 UInt64,
value4 UInt64, value5 UInt64') PARTITION BY partition_id
SELECT
number % 5 AS partition_id,
number,
number,
number,
number,
number
FROM numbers(100000000);
Split chunk into multiple chunks.
void PartitionedSink::consume(Chunk chunk)
{
...
std::unordered_map<String, size_t> partition_id_to_chunk_index;
IColumn::Selector chunk_row_index_to_partition_index;
for (size_t row = 0; row < chunk.getNumRows(); ++row)
{
auto value = column->getDataAt(row);
auto [it, inserted] = partition_id_to_chunk_index.emplace(value,
partition_id_to_chunk_index.size());
chunk_row_index_to_partition_index.push_back(it->second);
}
...
}
Use HashMapWithSavedHash<StringRef, size_t> instead of std::unordered_map<String, size_t>.
Store hash table and arena as class member, to reuse them between consume calls.
void PartitionedSink::consume(Chunk chunk)
{
...
size_t chunk_rows = chunk.getNumRows();
chunk_row_index_to_partition_index.resize(chunk_rows);
partition_id_to_chunk_index.clear();
for (size_t row = 0; row < chunk_rows; ++row)
{
auto partition_key = partition_by_result_column->getDataAt(row);
auto [it, inserted] = partition_id_to_chunk_index.insert(
makePairNoInit(partition_key, partition_id_to_chunk_index.size()));
if (inserted)
it->value.first = copyStringInArena(partition_keys_arena, partition_key);
chunk_row_index_to_partition_index[row] = it->getMapped();
}
...
}
INSERT INTO FUNCTION file('test_file_{_partition_id}', 'TSV',
'partition_id UInt64, value1 UInt64, value2 UInt64, value3 UInt64,
value4 UInt64, value5 UInt64') PARTITION BY partition_id
SELECT
number % 5 AS partition_id,
number,
number,
number,
number,
number
FROM numbers(100000000);
Was: 9.714 sec (10.36 million rows/s., 82.90 MB/s.)
Now: 2.868 sec (35.10 million rows/s., 280.76 MB/s.)
Assume that we have interface that provide some generic methods for working with object. For example in ClickHouse there is IColumn interface that provide a lot of methods for working with columns (filter, getPermutation, compareAt).
Sometimes we need to write complex logic that is implemented on top of such interface.
The problem is that if this logic will be implemented in terms of small virtual methods like compareAt there will be a lot of virtual function calls.
In most of the cases we use CRTP (The Curiously Reccuring Template Pattern).
Also we can use just standalone template function.
class IAggregateFunction
{
...
virtual ~IAggregateFunction() = default;
virtual void add(
AggregateDataPtr place,
const IColumn ** columns,
size_t row_num,
Arena * arena) const = 0;
virtual void addBatch(
size_t row_begin,
size_t row_end,
AggregateDataPtr * places,
size_t place_offset,
const IColumn ** columns,
Arena * arena,
ssize_t if_argument_pos = -1) const = 0;
...
}
template <typename Derived>
class IAggregateFunctionHelper : public IAggregateFunction
{
void addBatch(size_t row_begin, size_t row_end, AggregateDataPtr * places,
size_t place_offset, const IColumn ** columns, Arena * arena,
ssize_t if_argument_pos = -1) const override
{
if (if_argument_pos >= 0)
{
auto * column = columns[if_argument_pos];
const auto & flags = assert_cast<const ColumnUInt8 &>(*column).getData();
for (size_t i = row_begin; i < row_end; ++i)
{
if (flags[i] && places[i])
static_cast<const Derived *>(this)->add(places[i] + place_offset,
columns, i, arena);
}
}
{
for (size_t i = row_begin; i < row_end; ++i)
if (places[i])
static_cast<const Derived *>(this)->add(places[i] + place_offset,
columns, i, arena);
}
}
}
template <typename T, typename Derived>
class IAggregateFunctionDataHelper : public IAggregateFunctionHelper<Derived>
{
...
}
class AggregateFunctionCount final : public IAggregateFunctionDataHelper<AggregateFunctionCountData,
AggregateFunctionCount>
{
void add(AggregateDataPtr __restrict place, const IColumn **, size_t, Arena *) const override
{
++data(place).count;
}
}
class IColumn
{
...
virtual int compareAt(size_t n, size_t m, const IColumn & rhs,
int nan_direction_hint) const = 0;
virtual void compareColumn(const IColumn & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes,
PaddedPODArray<Int8> & compare_results,
int direction, int nan_direction_hint) const = 0;
...
}
class IColumn
{
...
protected:
template <typename Derived, bool reversed, bool use_indexes>
void compareImpl(const Derived & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes,
PaddedPODArray<Int8> & compare_results,
int nan_direction_hint) const;
template <typename Derived>
void doCompareColumn(const Derived & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes,
PaddedPODArray<Int8> & compare_results,
int direction, int nan_direction_hint) const;
...
}
template <is_decimal T>
void ColumnDecimal<T>::compareColumn(const IColumn & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes,
PaddedPODArray<Int8> & compare_results,
int direction, int nan_direction_hint) const
{
return this->template doCompareColumn<ColumnDecimal<T>>(
static_cast<const Self &>(rhs),
rhs_row_num,
row_indexes,
compare_results,
direction,
nan_direction_hint);
}
Compile time dispatch:
template <typename Derived>
void IColumn::doCompareColumn(const Derived & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes,
PaddedPODArray<Int8> & compare_results,
int direction, int nan_direction_hint) const
{
if (direction < 0)
{
if (row_indexes)
compareImpl<Derived, true, true>(rhs, rhs_row_num, row_indexes,
compare_results, nan_direction_hint);
else
compareImpl<Derived, true, false>(rhs, rhs_row_num, row_indexes,
compare_results, nan_direction_hint);
}
else
{
if (row_indexes)
compareImpl<Derived, false, true>(rhs, rhs_row_num, row_indexes,
compare_results, nan_direction_hint);
else
compareImpl<Derived, false, false>(rhs, rhs_row_num, row_indexes,
compare_results, nan_direction_hint);
}
}
template <typename Derived, bool reversed, bool use_indexes>
void IColumn::compareImpl(const Derived & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes [[maybe_unused]],
PaddedPODArray<Int8> & compare_results,
int nan_direction_hint) const
{
for (size_t i = 0; i < num_indexes; ++i)
{
UInt64 row = i;
if constexpr (use_indexes)
row = indexes[i];
int res = compareAt(row, rhs_row_num, rhs, nan_direction_hint);
assert(res == 1 || res == -1 || res == 0);
compare_results[row] = static_cast<Int8<(res);
if constexpr (reversed)
compare_results[row] = -compare_results[row];
if constexpr (use_indexes)
{
if (compare_results[row] == 0)
{
*next_index = row;
++next_index;
}
}
}
}
template <typename Derived, bool reversed, bool use_indexes>
void IColumn::compareImpl(const Derived & rhs, size_t rhs_row_num,
PaddedPODArray<UInt64> * row_indexes [[maybe_unused]],
PaddedPODArray<Int8> & compare_results,
int nan_direction_hint) const
{
for (size_t i = 0; i < num_indexes; ++i)
{
UInt64 row = i;
if constexpr (use_indexes)
row = indexes[i];
int res = static_cast<const Derived *>(this)->compareAt(row, rhs_row_num, rhs,
nan_direction_hint);
assert(res == 1 || res == -1 || res == 0);
compare_results[row] = static_cast<Int8<(res);
if constexpr (reversed)
compare_results[row] = -compare_results[row];
if constexpr (use_indexes)
{
if (compare_results[row] == 0)
{
*next_index = row;
++next_index;
}
}
}
}
Result performance improvements:
How Sorting in ClickHouse works. Let first take a look at pipeline:
EXPLAIN PIPELINE SELECT WatchID FROM hits_100m_single
ORDER BY WatchID, CounterID;
┌─explain──────────────────────────────────┐
│ (Expression) │
│ ExpressionTransform │
│ (Sorting) │
│ MergingSortedTransform 16 → 1 │
│ MergeSortingTransform × 16 │
│ LimitsCheckingTransform × 16 │
│ PartialSortingTransform × 16 │
│ (Expression) │
│ ExpressionTransform × 16 │
│ (SettingQuotaAndLimits) │
│ (ReadFromMergeTree) │
│ MergeTreeThread × 16 0 → 1 │
└──────────────────────────────────────────┘
In physical query plan we have multiple transform that work together to perform sorting:
PartialSortingTransform — sort single block, apply special optimization if LIMIT is specified.
MergeSortingTransform — sort multiple blocks using k-way-merge algorithm, output of this transform is a stream of sorted blocks.
MergingSortedTransform — sort multiple streams of sorted blocks using k-way-merge algorithm.
Sort of single block in PartialSortingTransform, can be performed in batch, without indirections. There is getPermutation, updatePermutaion methods in IColumn that returns or update permutation.
This permutation can later be applied efficiently to any column using permute method.
The problem is with MergeSortingTransform and MergingSortedTransform. They must perform k-way-merge algorithm, and this algorithm operates on single rows instead of columns.
In the worst case, we will apply ORDER BY WatchID, CounterID comparator to each row N * log(N) * 2 times during our MergeSortingTransform, MergingSortedTransform.
SELECT WatchID FROM hits_100m_obfuscated
ORDER BY WatchID FORMAT Null;
struct SortCursor : SortCursorHelper<SortCursor>
{
using SortCursorHelper<SortCursor>::SortCursorHelper;
/// The specified row of this cursor is greater than the specified
/// row of another cursor.
bool greaterAt(const SortCursor & rhs, size_t lhs_pos, size_t rhs_pos) const
{
for (size_t i = 0; i < impl->sort_columns_size; ++i)
{
const auto & sort_description = impl->desc[i];
int direction = sort_description.direction;
int nulls_direction = sort_description.nulls_direction;
int res = direction * impl->sort_columns[i]->compareAt(lhs_pos, rhs_pos,
*(rhs.impl->sort_columns[i]), nulls_direction);
if (res > 0)
return true;
if (res < 0)
return false;
}
return impl->order > rhs.impl->order;
}
};
Worst thing for column DBMS is to process elements in rows.
The biggest problem here is that for each column specified in the ORDER BY comparator, we call compareAt method N * log(N) * 2 times.
The most common case of sorting in databases is sorting by single column.
SELECT WatchID FROM hits_100m_obfuscated
ORDER BY WatchID FORMAT Null;
Lets write specialization.
template <typename ColumnType>
struct SpecializedSingleColumnSortCursor : SortCursorHelper<
SpecializedSingleColumnSortCursor<ColumnType>>
{
bool ALWAYS_INLINE greaterAt(
const SortCursorHelper<SpecializedSingleColumnSortCursor> & rhs,
size_t lhs_pos, size_t rhs_pos) const
{
auto & lhs_columns = this->impl->sort_columns;
auto & rhs_columns = rhs.impl->sort_columns;
const auto & lhs_column = assert_cast<const ColumnType &>(*lhs_columns[0]);
const auto & rhs_column = assert_cast<const ColumnType &>(*rhs_columns[0]);
const auto & desc = this->impl->desc[0];
int res = desc.direction * lhs_column.compareAt(lhs_pos, rhs_pos,
rhs_column, desc.nulls_direction);
if (res > 0)
return true;
if (res < 0)
return false;
return this->impl->order > rhs.impl->order;
}
};
SELECT WatchID FROM hits_100m_obfuscated
ORDER BY WatchID FORMAT Null;
Was: 5.401 sec (18.51 million rows/s., 148.11 MB/s)
Now: 4.363 sec (22.92 million rows/s., 183.35 MB/s.)
For multiple columns in comparator we applied JIT compilation.
We fused multiple compareAt methods in a single function to avoid unnecessary indirections and decrease the number of virtual function calls if multiple columns are specified in the comparator.
SELECT WatchID FROM hits_100m_single
ORDER BY WatchID, CounterID
SETTINGS compile_sort_description=0;
— 0 rows in set. Elapsed: 6.408 sec. Processed 100.00 million rows, 1.20 GB (15.60 million rows/s., 187.26 MB/s.)
SELECT WatchID FROM hits_100m_single
ORDER BY WatchID, CounterID
SETTINGS compile_sort_description=1;
— 0 rows in set. Elapsed: 5.300 sec. Processed 100.00 million rows, 1.20 GB (18.87 million rows/s., 226.40 MB/s.)
— +20% performance improvement!
Another problem with MergeSortingTransform and MergingSortedTransform and k-way-merge algorithm, is that during merge we insert only single row into our result.
During row insertion we need to perform number_of_columns virtual calls.
Maybe we can choose data structure that performs minimum amount of comparisons and can help to minimize amount of virtual calls during row insertion ?
K - number of cursors that we want to merge.
N - total number of elements that are in all cursors.
There are 3 data structures that can be used:
1. Heap. Performs around N * log(K) * 1.5 comparisons in worst case.
2. Self balansing BST (AVL, Red-Black). Performs around N * log(K) * constant_factor comparisons.
3. Tournament Tree. Performs N * log(K) comparisons in worst case.
The biggest issue with tournament tree is that this data structure always performs N * log(N) comparisons, even for low cardinality data, because all tournament must be replayed.
Theoretically tournament tree should make less comparisons for data with high cardinality. But on real data heap can avoid a lot of comparisons because next minimum cursor is still greater than current minimum cursor.
We can choose between heap and tournament tree in runtime using for example bandits approach similar to lz4 optimization, or using statistics to understand if column has high cardinality or low cardinality.
Also there are tournament tree modifications that can allow to store minimum cursor and next minimum cursor.
But for now we decided to use heap property, but improve it with batch interface.
The idea is simple, if current minimum cursor in heap is less than next minimum cursor, we compare them, until next mininum cursor is greater, each time we increase batch size.
That way we can insert multiple rows into result, if we sort data that does not have high cardinality (contains duplicates).
On real data we can see 2x-10x performance improvement, after replacing heap with batch heap.
SELECT DISTINCT Age FROM hits_100m_obfuscated;
┌─Age─┐
│ 0 │
│ 50 │
│ 31 │
│ 55 │
│ 22 │
│ 28 │
└─────
SELECT WatchID FROM hits_100m_obfuscated ORDER BY Age FORMAT Null;
Was: 4.154 sec (24.07 million rows/s., 216.64 MB/s.)
Now: 0.482 sec (207.47 million rows/s., 1.87 GB/s.)
1. CI/CD infrastructure, especially performance tests, must be the core component of a high performance system.
2. Without deep introspection it is hard to investigate issues with performance.
3. For high performance systems interfaces must be determined by algorithms and data structures.
4. Use tools to profile, benchmark and check how your program works under load.
5. Avoid virtual function calls.
6. Always evaluate algorithms and data structures on real data.


featkeeper
Closed
In Progress
Client:
Priority:
Target date:
Ticket URL:
Product area:
Agent name:
Edit
Close
×
Add Feature Request
Title
Description
Client
Client A
Client B
Client C
Priority
Target date
Product area
Policies
Billing
Claims
Reports
Agent
×
Edit Feature Request
Title
Description
Priority
Target date
Product area
Policies
Billing
Claims
Reports


Dual points, lines, polygons and curves
Alex Townsend, August 2011
(Chebfun example geom/DualCurves.m)
function DualCurves
In geometry many statements have an equally valid dual statement [1,2]. For example, "Two non-parallel lines intersect at exactly one point" is dual to "Two distinct points are joined by exactly one line" and "Three points lie on a line iff they are collinear" is dual to "Three lines meet at a point iff they are concurrent".
The dual of a point is a line: the point (a,b) is the dual to the line with gradient -a/b going through (-a/(a^2+b^2),-b/(a^2+b^2)). Conversely, the dual of a line is a point: the line y=mx+c is dual to the point (m/c,-1/c).
FS = 'FontSize'; MS = 'MarkerSize'; a = 1; b = pi/3; dual = chebfun(@(x) -(a/b)*x-1/b,[-inf,inf]); plot(a,b,'x',MS,16), hold on, plot(dual,'r'), grid on axis([-10 10 -10 10]), title('A point and its dual',FS,16), hold off
A polygon consists of edges (lines) and vertices (points). The dual of an edge is a point and the dual of a vertex is a line. Hence the dual of a polygon is also a polygon. In particular, odd-sided regular polygons are self-dual.
t = chebfun('x',[0,1]); vertices = [-2-1i 0-1i 2+1i 0+1i]; polygon = (1-t)*vertices + t*circshift(vertices',-1)'; plot(polygon,'b'), hold on, axis equal, grid on dual = DualOfPolygon(vertices); plot(dual,'r') title('A polygon and its dual',FS,16), hold off
A curve is the limit of piecewise linear curves, so we can extend the definition of dual to curves. Given any curve C, the dual curve is the set of points which are dual to the tangent lines of C. Given any parameterised curve, there is a simple formula to compute its dual curve. Here is the dual of a smoothed heart-shaped curve.
t = chebfun('x',[0,2*pi]); x = 2*sin(t); y = 2*cos(t)-(1/2)*cos(2*t)-(1/4)*cos(3*t)-(1/8)*cos(4*t); plot(x+1i*y), hold on, axis equal, plot(DualOfCurve(x+1i*y),'r'); title('A curve and its dual',FS,16)
Here are the functions which were used to compute the duals:
function g = DualOfPolygon(v) %DUALOFPOLYGON(V), computes dual polygon. v is array of complex-valued %vertices of the polygon. g is a chebfun parameterising the dual %polygon. w = circshift(v',-1)'; gradient = (imag(v)-imag(w))./(real(v)-real(w)); intercept = imag(v)-gradient.*real(v); poly = (1./intercept).*(gradient-1i); %If edge is vertical replace NaN/Inf with dual point. poly(isnan(poly)) = -real(v(isnan(poly))); poly(isinf(poly)) = -real(v(isinf(poly))); %Add in final edge of polygon. poly = [poly, poly(1)]; s = chebfun('x',[0,1]); p = (1-s)*poly + s*circshift(poly',-1)'; %Concatenate chebfuns together. g = p(:,1); for k=2:length(poly)-1, g=[g;p(:,k)]; end end function g = DualOfCurve(f) %DUALOFCURVE(F), computes dual curve. % f is complex-valued chebfun parameterising a smooth curve. g is a % chebfun parameterising the dual curve. rl = real(f); im = imag(f); %Calculate parameterisation for dual curve. p = -diff(im)./(diff(rl).*im-rl.*diff(im)); q = diff(rl)./(diff(im).*rl-im.*diff(rl)); g = p+1i*q; end
References
[1] Wikipedia, "Dual curve", http://en.wikipedia.org/wiki/Dual_curve
[2] Wikipedia, "Dual polygon", http://en.wikipedia.org/wiki/Dual_polygon
end


RT @jruby: Ruby installers: please use https://s3.amazonaws.com/jruby.org for secure downloads of JRuby releases. See http://jruby.org links. Th…
10/24/2014, 12:23:52 PM
Favs: 0
Retweets: 0
link--- layout: tweet ---
RT @jruby: Ruby installers: please use https://s3.amazonaws.com/jruby.org for secure downloads of JRuby releases. See http://jruby.org links. Th…
10/24/2014, 12:23:52 PM
Favs: 0
Retweets: 0
link


Selenium
TestRunner
Execute Tests
Fast
Slow
Highlight elements
Elapsed:
00.00
Tests
Commands
0
run
0
passed
0
failed
0
failed
0
incomplete
Tools
View DOM
Show Log
Tellurium Log


new BitmapData(game, key, width, height)
A BitmapData object contains a Canvas element to which you can draw anything you like via normal Canvas context operations. A single BitmapData can be used as the texture for one or many Images / Sprites. So if you need to dynamically create a Sprite texture then they are a good choice.
Important note: Every BitmapData creates its own Canvas element. Because BitmapData's are now Game Objects themselves, and don't live on the display list, they are NOT automatically cleared when you change State. Therefore you must call BitmapData.destroy in your State's shutdown method if you wish to free-up the resources the BitmapData used, it will not happen for you.
Parameters:
| Name | Type | Argument | Default | Description |
|---|---|---|---|---|
game |
Phaser.Game | A reference to the currently running game. |
||
key |
string | Internal Phaser reference key for the BitmapData. |
||
width |
number |
<optional> |
256 | The width of the BitmapData in pixels. If undefined or zero it's set to a default value. |
height |
number |
<optional> |
256 | The height of the BitmapData in pixels. If undefined or zero it's set to a default value. |
- Source - gameobjects/BitmapData.js, line 23
Members
-
baseTexture :PIXI.BaseTexture
-
The PIXI.BaseTexture.
- Source - gameobjects/BitmapData.js, line 117
-
canvas :HTMLCanvasElement
-
The canvas to which this BitmapData draws.
- Source - gameobjects/BitmapData.js, line 52
-
context :CanvasRenderingContext2D
-
The 2d context of the canvas.
- Source - gameobjects/BitmapData.js, line 58
-
ctx :CanvasRenderingContext2D
-
A reference to BitmapData.context.
- Source - gameobjects/BitmapData.js, line 63
-
data :Uint8ClampedArray
-
A Uint8ClampedArray view into BitmapData.buffer. Note that this is unavailable in some browsers (such as Epic Browser due to its security restrictions)
- Source - gameobjects/BitmapData.js, line 77
-
dirty :boolean
-
If dirty this BitmapData will be re-rendered.
- Source - gameobjects/BitmapData.js, line 147
-
disableTextureUpload :boolean
-
If disableTextureUpload is true this BitmapData will never send its image data to the GPU when its dirty flag is true.
- Source - gameobjects/BitmapData.js, line 142
-
game :Phaser.Game
-
A reference to the currently running game.
- Source - gameobjects/BitmapData.js, line 31
-
height :number
-
The height of the BitmapData in pixels.
- Source - gameobjects/BitmapData.js, line 46
-
imageData :ImageData
-
The context image data. Please note that a call to BitmapData.draw() or BitmapData.copy() does not update immediately this property for performance reason. Use BitmapData.update() to do so. This property is updated automatically after the first game loop, according to the dirty flag property.
- Source - gameobjects/BitmapData.js, line 70
-
key :string
-
The key of the BitmapData in the Cache, if stored there.
- Source - gameobjects/BitmapData.js, line 36
-
pixels :Uint32Array
-
An Uint32Array view into BitmapData.buffer.
- Source - gameobjects/BitmapData.js, line 87
-
texture :PIXI.Texture
-
The PIXI.Texture.
- Source - gameobjects/BitmapData.js, line 123
-
textureFrame :Phaser.Frame
-
The Frame this BitmapData uses for rendering.
- Source - gameobjects/BitmapData.js, line 129
-
type :number
-
The const type of this object.
- Source - gameobjects/BitmapData.js, line 137
-
width :number
-
The width of the BitmapData in pixels.
- Source - gameobjects/BitmapData.js, line 41
Methods
-
<static> getTransform(translateX, translateY, scaleX, scaleY, skewX, skewY) → {object}
-
Gets a JavaScript object that has 6 properties set that are used by BitmapData in a transform.
Parameters:
Name Type Description translateX
number The x translate value.
translateY
number The y translate value.
scaleX
number The scale x value.
scaleY
number The scale y value.
skewX
number The skew x value.
skewY
number The skew y value.
Returns:
object -A JavaScript object containing all of the properties BitmapData needs for transforms.
- Source - gameobjects/BitmapData.js, line 2246
-
add(object) → {Phaser.BitmapData}
-
Updates the given objects so that they use this BitmapData as their texture. This will replace any texture they will currently have set.
Parameters:
Name Type Description object
Phaser.Sprite | Array.<Phaser.Sprite> | Phaser.Image | Array.<Phaser.Image> Either a single Sprite/Image or an Array of Sprites/Images.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 381
-
addToWorld(x, y, anchorX, anchorY, scaleX, scaleY) → {Phaser.Image}
-
Creates a new Phaser.Image object, assigns this BitmapData to be its texture, adds it to the world then returns it.
Parameters:
Name Type Argument Default Description x
number <optional>
0 The x coordinate to place the Image at.
y
number <optional>
0 The y coordinate to place the Image at.
anchorX
number <optional>
0 Set the x anchor point of the Image. A value between 0 and 1, where 0 is the top-left and 1 is bottom-right.
anchorY
number <optional>
0 Set the y anchor point of the Image. A value between 0 and 1, where 0 is the top-left and 1 is bottom-right.
scaleX
number <optional>
1 The horizontal scale factor of the Image. A value of 1 means no scaling. 2 would be twice the size, and so on.
scaleY
number <optional>
1 The vertical scale factor of the Image. A value of 1 means no scaling. 2 would be twice the size, and so on.
Returns:
The newly added Image object.
- Source - gameobjects/BitmapData.js, line 1167
-
alphaMask(source, mask, sourceRect, maskRect) → {Phaser.BitmapData}
-
Draws the image onto this BitmapData using an image as an alpha mask.
Parameters:
Name Type Argument Description source
Phaser.Sprite | Phaser.Image | Phaser.Text | Phaser.BitmapData | Image | HTMLCanvasElement | string The source to copy from. If you give a string it will try and find the Image in the Game.Cache first. This is quite expensive so try to provide the image itself.
mask
Phaser.Sprite | Phaser.Image | Phaser.Text | Phaser.BitmapData | Image | HTMLCanvasElement | string <optional>
The object to be used as the mask. If you give a string it will try and find the Image in the Game.Cache first. This is quite expensive so try to provide the image itself. If you don't provide a mask it will use this BitmapData as the mask.
sourceRect
Phaser.Rectangle <optional>
A Rectangle where x/y define the coordinates to draw the Source image to and width/height define the size.
maskRect
Phaser.Rectangle <optional>
A Rectangle where x/y define the coordinates to draw the Mask image to and width/height define the size.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1569
-
blendAdd() → {Phaser.BitmapData}
-
Sets the blend mode to 'lighter'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1996
-
blendColor() → {Phaser.BitmapData}
-
Sets the blend mode to 'color'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2178
-
blendColorBurn() → {Phaser.BitmapData}
-
Sets the blend mode to 'color-burn'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2087
-
blendColorDodge() → {Phaser.BitmapData}
-
Sets the blend mode to 'color-dodge'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2074
-
blendDarken() → {Phaser.BitmapData}
-
Sets the blend mode to 'darken'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2048
-
blendDestinationAtop() → {Phaser.BitmapData}
-
Sets the blend mode to 'destination-atop'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1970
-
blendDestinationIn() → {Phaser.BitmapData}
-
Sets the blend mode to 'destination-in'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1944
-
blendDestinationOut() → {Phaser.BitmapData}
-
Sets the blend mode to 'destination-out'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1957
-
blendDestinationOver() → {Phaser.BitmapData}
-
Sets the blend mode to 'destination-over'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1931
-
blendDifference() → {Phaser.BitmapData}
-
Sets the blend mode to 'difference'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2126
-
blendExclusion() → {Phaser.BitmapData}
-
Sets the blend mode to 'exclusion'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2139
-
blendHardLight() → {Phaser.BitmapData}
-
Sets the blend mode to 'hard-light'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2100
-
blendHue() → {Phaser.BitmapData}
-
Sets the blend mode to 'hue'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2152
-
blendLighten() → {Phaser.BitmapData}
-
Sets the blend mode to 'lighten'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2061
-
blendLuminosity() → {Phaser.BitmapData}
-
Sets the blend mode to 'luminosity'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2191
-
blendMultiply() → {Phaser.BitmapData}
-
Sets the blend mode to 'multiply'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2009
-
blendOverlay() → {Phaser.BitmapData}
-
Sets the blend mode to 'overlay'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2035
-
blendReset() → {Phaser.BitmapData}
-
Resets the blend mode (effectively sets it to 'source-over')
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1866
-
blendSaturation() → {Phaser.BitmapData}
-
Sets the blend mode to 'saturation'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2165
-
blendScreen() → {Phaser.BitmapData}
-
Sets the blend mode to 'screen'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2022
-
blendSoftLight() → {Phaser.BitmapData}
-
Sets the blend mode to 'soft-light'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 2113
-
blendSourceAtop() → {Phaser.BitmapData}
-
Sets the blend mode to 'source-atop'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1918
-
blendSourceIn() → {Phaser.BitmapData}
-
Sets the blend mode to 'source-in'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1892
-
blendSourceOut() → {Phaser.BitmapData}
-
Sets the blend mode to 'source-out'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1905
-
blendSourceOver() → {Phaser.BitmapData}
-
Sets the blend mode to 'source-over'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1879
-
blendXor() → {Phaser.BitmapData}
-
Sets the blend mode to 'xor'
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1983
-
circle(x, y, radius, fillStyle) → {Phaser.BitmapData}
-
Draws a filled Circle to the BitmapData at the given x, y coordinates and radius in size.
Parameters:
Name Type Argument Description x
number The x coordinate to draw the Circle at. This is the center of the circle.
y
number The y coordinate to draw the Circle at. This is the center of the circle.
radius
number The radius of the Circle in pixels. The radius is half the diameter.
fillStyle
string <optional>
If set the context fillStyle will be set to this value before the circle is drawn.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1720
-
clear(x, y, width, height) → {Phaser.BitmapData}
-
Clears the BitmapData context using a clearRect.
You can optionally define the area to clear. If the arguments are left empty it will clear the entire canvas.
You may need to call BitmapData.update after this in order to clear out the pixel data, but Phaser will not do this automatically for you.
Parameters:
Name Type Argument Default Description x
number <optional>
0 The x coordinate of the top-left of the area to clear.
y
number <optional>
0 The y coordinate of the top-left of the area to clear.
width
number <optional>
The width of the area to clear. If undefined it will use BitmapData.width.
height
number <optional>
The height of the area to clear. If undefined it will use BitmapData.height.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 451
-
cls()
-
Clears the BitmapData context using a clearRect.
- Source - gameobjects/BitmapData.js, line 445
-
copy(source, x, y, width, height, tx, ty, newWidth, newHeight, rotate, anchorX, anchorY, scaleX, scaleY, alpha, blendMode, roundPx) → {Phaser.BitmapData}
-
Copies a rectangular area from the source object to this BitmapData. If you give
null
as the source it will copy from itself. You can optionally resize, translate, rotate, scale, alpha or blend as it's drawn. All rotation, scaling and drawing takes place around the regions center point by default, but can be changed with the anchor parameters. Note that the source image can also be this BitmapData, which can create some interesting effects.This method has a lot of parameters for maximum control. You can use the more friendly methods like
copyRect
anddraw
to avoid having to remember them all.Parameters:
Name Type Argument Default Description source
Phaser.Sprite | Phaser.Image | Phaser.Text | Phaser.BitmapData | Image | HTMLCanvasElement | string <optional>
The source to copy from. If you give a string it will try and find the Image in the Game.Cache first. This is quite expensive so try to provide the image itself.
x
number <optional>
0 The x coordinate representing the top-left of the region to copy from the source image.
y
number <optional>
0 The y coordinate representing the top-left of the region to copy from the source image.
width
number <optional>
The width of the region to copy from the source image. If not specified it will use the full source image width.
height
number <optional>
The height of the region to copy from the source image. If not specified it will use the full source image height.
tx
number <optional>
The x coordinate to translate to before drawing. If not specified it will default to the
x
parameter. Ifnull
andsource
is a Display Object, it will default tosource.x
.ty
number <optional>
The y coordinate to translate to before drawing. If not specified it will default to the
y
parameter. Ifnull
andsource
is a Display Object, it will default tosource.y
.newWidth
number <optional>
The new width of the block being copied. If not specified it will default to the
width
parameter.newHeight
number <optional>
The new height of the block being copied. If not specified it will default to the
height
parameter.rotate
number <optional>
0 The angle in radians to rotate the block to before drawing. Rotation takes place around the center by default, but can be changed with the
anchor
parameters.anchorX
number <optional>
0 The anchor point around which the block is rotated and scaled. A value between 0 and 1, where 0 is the top-left and 1 is bottom-right.
anchorY
number <optional>
0 The anchor point around which the block is rotated and scaled. A value between 0 and 1, where 0 is the top-left and 1 is bottom-right.
scaleX
number <optional>
1 The horizontal scale factor of the block. A value of 1 means no scaling. 2 would be twice the size, and so on.
scaleY
number <optional>
1 The vertical scale factor of the block. A value of 1 means no scaling. 2 would be twice the size, and so on.
alpha
number <optional>
1 The alpha that will be set on the context before drawing. A value between 0 (fully transparent) and 1, opaque.
blendMode
string <optional>
null The composite blend mode that will be used when drawing. The default is no blend mode at all. This is a Canvas globalCompositeOperation value such as 'lighter' or 'xor'.
roundPx
boolean <optional>
false Should the x and y values be rounded to integers before drawing? This prevents anti-aliasing in some instances.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1193
-
copyRect(source, area, x, y, alpha, blendMode, roundPx) → {Phaser.BitmapData}
-
Copies the area defined by the Rectangle parameter from the source image to this BitmapData at the given location.
Parameters:
Name Type Argument Default Description source
Phaser.Sprite | Phaser.Image | Phaser.Text | Phaser.BitmapData | Image | string The Image to copy from. If you give a string it will try and find the Image in the Game.Cache.
area
Phaser.Rectangle The Rectangle region to copy from the source image.
x
number The destination x coordinate to copy the image to.
y
number The destination y coordinate to copy the image to.
alpha
number <optional>
1 The alpha that will be set on the context before drawing. A value between 0 (fully transparent) and 1, opaque.
blendMode
string <optional>
null The composite blend mode that will be used when drawing. The default is no blend mode at all. This is a Canvas globalCompositeOperation value such as 'lighter' or 'xor'.
roundPx
boolean <optional>
false Should the x and y values be rounded to integers before drawing? This prevents anti-aliasing in some instances.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1391
-
destroy()
-
Destroys this BitmapData and puts the canvas it was using back into the canvas pool for re-use.
- Source - gameobjects/BitmapData.js, line 1853
-
draw(source, x, y, width, height, blendMode, roundPx) → {Phaser.BitmapData}
-
Draws the given Phaser.Sprite, Phaser.Image or Phaser.Text to this BitmapData at the coordinates specified. You can use the optional width and height values to 'stretch' the sprite as it is drawn. This uses drawImage stretching, not scaling. When drawing it will take into account the Sprites rotation, scale and alpha values.
Parameters:
Name Type Argument Default Description source
Phaser.Sprite | Phaser.Image | Phaser.Text The Sprite, Image or Text object to draw onto this BitmapData.
x
number <optional>
0 The x coordinate to translate to before drawing. If not specified it will default to
source.x
.y
number <optional>
0 The y coordinate to translate to before drawing. If not specified it will default to
source.y
.width
number <optional>
The new width of the Sprite being copied. If not specified it will default to
source.width
.height
number <optional>
The new height of the Sprite being copied. If not specified it will default to
source.height
.blendMode
string <optional>
null The composite blend mode that will be used when drawing. The default is no blend mode at all. This is a Canvas globalCompositeOperation value such as 'lighter' or 'xor'.
roundPx
boolean <optional>
false Should the x and y values be rounded to integers before drawing? This prevents anti-aliasing in some instances.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1410
-
drawFull(parent, blendMode, roundPx) → {Phaser.BitmapData}
-
Draws the Game Object or Group to this BitmapData and then recursively iterates through all of its children.
If a child has an
exists
property then it (and its children) will be only be drawn if exists istrue
.The children will be drawn at their
x
andy
world space coordinates. If this is outside the bounds of the BitmapData they won't be drawn. Depending on your requirements you may need to resize the BitmapData in advance to match the bounds of the top-level Game Object.When drawing it will take into account the child's world rotation, scale and alpha values.
It's perfectly valid to pass in
game.world
as the parent object, and it will iterate through the entire display list.Note: If you are trying to grab your entire game at the start of a State then you should ensure that at least 1 full update has taken place before doing so, otherwise all of the objects will render with incorrect positions and scales. You can trigger an update yourself by calling
stage.updateTransform()
before callingdrawFull
.Parameters:
Name Type Argument Default Description parent
Phaser.World | Phaser.Group | Phaser.Sprite | Phaser.Image | Phaser.Text | Phaser.BitmapText The Game Object to draw onto this BitmapData and then recursively draw all of its children.
blendMode
string <optional>
null The composite blend mode that will be used when drawing. The default is no blend mode at all. This is a Canvas globalCompositeOperation value such as 'lighter' or 'xor'.
roundPx
boolean <optional>
false Should the x and y values be rounded to integers before drawing? This prevents anti-aliasing in some instances.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1481
-
drawGroup(group, blendMode, roundPx) → {Phaser.BitmapData}
-
Draws the immediate children of a Phaser.Group to this BitmapData. Children are only drawn if they have their
exists
property set totrue
and have image based Textures. The children will be drawn at theirx
andy
world space coordinates. If this is outside the bounds of the BitmapData they won't be drawn. When drawing it will take into account the child's rotation, scale and alpha values. No iteration takes place. Groups nested inside other Groups will not be iterated through.Parameters:
Name Type Argument Default Description group
Phaser.Group The Group to draw onto this BitmapData.
blendMode
string <optional>
null The composite blend mode that will be used when drawing. The default is no blend mode at all. This is a Canvas globalCompositeOperation value such as 'lighter' or 'xor'.
roundPx
boolean <optional>
false Should the x and y values be rounded to integers before drawing? This prevents anti-aliasing in some instances.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1432
-
extract(destination, r, g, b, a, resize, r2, g2, b2) → {Phaser.BitmapData}
-
Scans this BitmapData for all pixels matching the given r,g,b values and then draws them into the given destination BitmapData. The original BitmapData remains unchanged. The destination BitmapData must be large enough to receive all of the pixels that are scanned unless the 'resize' parameter is true. Although the destination BitmapData is returned from this method, it's actually modified directly in place, meaning this call is perfectly valid:
picture.extract(mask, r, g, b)
You can specify optional r2, g2, b2 color values. If given the pixel written to the destination bitmap will be of the r2, g2, b2 color. If not given it will be written as the same color it was extracted. You can provide one or more alternative colors, allowing you to tint the color during extraction.Parameters:
Name Type Argument Default Description destination
Phaser.BitmapData The BitmapData that the extracted pixels will be drawn to.
r
number The red color component, in the range 0 - 255.
g
number The green color component, in the range 0 - 255.
b
number The blue color component, in the range 0 - 255.
a
number <optional>
255 The alpha color component, in the range 0 - 255 that the new pixel will be drawn at.
resize
boolean <optional>
false Should the destination BitmapData be resized to match this one before the pixels are copied?
r2
number <optional>
An alternative red color component to be written to the destination, in the range 0 - 255.
g2
number <optional>
An alternative green color component to be written to the destination, in the range 0 - 255.
b2
number <optional>
An alternative blue color component to be written to the destination, in the range 0 - 255.
Returns:
The BitmapData that the extract pixels were drawn on.
- Source - gameobjects/BitmapData.js, line 1603
-
fill(r, g, b, a) → {Phaser.BitmapData}
-
Fills the BitmapData with the given color.
Parameters:
Name Type Argument Default Description r
number The red color value, between 0 and 0xFF (255).
g
number The green color value, between 0 and 0xFF (255).
b
number The blue color value, between 0 and 0xFF (255).
a
number <optional>
1 The alpha color value, between 0 and 1.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 482
-
generateTexture(key) → {PIXI.Texture}
-
Creates a new Image element by converting this BitmapDatas canvas into a dataURL.
The image is then stored in the image Cache using the key given.
Finally a PIXI.Texture is created based on the image and returned.
You can apply the texture to a sprite or any other supporting object by using either the key or the texture. First call generateTexture:
var texture = bitmapdata.generateTexture('ball');
Then you can either apply the texture to a sprite:
game.add.sprite(0, 0, texture);
or by using the string based key:
game.add.sprite(0, 0, 'ball');
Parameters:
Name Type Description key
string The key which will be used to store the image in the Cache.
Returns:
The newly generated texture.
- Source - gameobjects/BitmapData.js, line 504
-
getBounds(rect) → {Phaser.Rectangle}
-
Scans the BitmapData and calculates the bounds. This is a rectangle that defines the extent of all non-transparent pixels. The rectangle returned will extend from the top-left of the image to the bottom-right, excluding transparent pixels.
Parameters:
Name Type Argument Description rect
Phaser.Rectangle <optional>
If provided this Rectangle object will be populated with the bounds, otherwise a new object will be created.
Returns:
A Rectangle whose dimensions encompass the full extent of non-transparent pixels in this BitmapData.
- Source - gameobjects/BitmapData.js, line 1139
-
getFirstPixel(direction) → {object}
-
Scans the BitmapData, pixel by pixel, until it encounters a pixel that isn't transparent (i.e. has an alpha value > 0). It then stops scanning and returns an object containing the color of the pixel in r, g and b properties and the location in the x and y properties.
The direction parameter controls from which direction it should start the scan:
0 = top to bottom 1 = bottom to top 2 = left to right 3 = right to left
Parameters:
Name Type Argument Default Description direction
number <optional>
0 The direction in which to scan for the first pixel. 0 = top to bottom, 1 = bottom to top, 2 = left to right and 3 = right to left.
Returns:
object -Returns an object containing the color of the pixel in the
r
,g
andb
properties and the location in thex
andy
properties.- Source - gameobjects/BitmapData.js, line 1056
-
getPixel(x, y, out) → {object}
-
Get the color of a specific pixel in the context into a color object. If you have drawn anything to the BitmapData since it was created you must call BitmapData.update to refresh the array buffer, otherwise this may return out of date color values, or worse - throw a run-time error as it tries to access an array element that doesn't exist.
Parameters:
Name Type Argument Description x
number The x coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
y
number The y coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
out
object <optional>
An object into which 4 properties will be created: r, g, b and a. If not provided a new object will be created.
Returns:
object -An object with the red, green, blue and alpha values set in the r, g, b and a properties.
- Source - gameobjects/BitmapData.js, line 973
-
getPixel32(x, y) → {number}
-
Get the color of a specific pixel including its alpha value. If you have drawn anything to the BitmapData since it was created you must call BitmapData.update to refresh the array buffer, otherwise this may return out of date color values, or worse - throw a run-time error as it tries to access an array element that doesn't exist. Note that on little-endian systems the format is 0xAABBGGRR and on big-endian the format is 0xRRGGBBAA.
Parameters:
Name Type Description x
number The x coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
y
number The y coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
Returns:
number -A native color value integer (format: 0xAARRGGBB)
- Source - gameobjects/BitmapData.js, line 1004
-
getPixelRGB(x, y, out, hsl, hsv) → {object}
-
Get the color of a specific pixel including its alpha value as a color object containing r,g,b,a and rgba properties. If you have drawn anything to the BitmapData since it was created you must call BitmapData.update to refresh the array buffer, otherwise this may return out of date color values, or worse - throw a run-time error as it tries to access an array element that doesn't exist.
Parameters:
Name Type Argument Default Description x
number The x coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
y
number The y coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
out
object <optional>
An object into which 3 properties will be created: r, g and b. If not provided a new object will be created.
hsl
boolean <optional>
false Also convert the rgb values into hsl?
hsv
boolean <optional>
false Also convert the rgb values into hsv?
Returns:
object -An object with the red, green and blue values set in the r, g and b properties.
- Source - gameobjects/BitmapData.js, line 1024
-
getPixels(rect) → {ImageData}
-
Gets all the pixels from the region specified by the given Rectangle object.
Parameters:
Name Type Description rect
Phaser.Rectangle The Rectangle region to get.
Returns:
ImageData -Returns a ImageData object containing a Uint8ClampedArray data property.
- Source - gameobjects/BitmapData.js, line 1043
-
line(x1, y1, x2, y2, color, width) → {Phaser.BitmapData}
-
Draws a line between the coordinates given in the color and thickness specified.
Parameters:
Name Type Argument Default Description x1
number The x coordinate to start the line from.
y1
number The y coordinate to start the line from.
x2
number The x coordinate to draw the line to.
y2
number The y coordinate to draw the line to.
color
string <optional>
'#fff' The stroke color that the line will be drawn in.
width
number <optional>
1 The line thickness.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1749
-
load(source) → {Phaser.BitmapData}
-
Takes the given Game Object, resizes this BitmapData to match it and then draws it into this BitmapDatas canvas, ready for further processing. The source game object is not modified by this operation. If the source object uses a texture as part of a Texture Atlas or Sprite Sheet, only the current frame will be used for sizing. If a string is given it will assume it's a cache key and look in Phaser.Cache for an image key matching the string.
Parameters:
Name Type Description source
Phaser.Sprite | Phaser.Image | Phaser.Text | Phaser.BitmapData | Image | HTMLCanvasElement | string The object that will be used to populate this BitmapData. If you give a string it will try and find the Image in the Game.Cache first.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 410
-
move(x, y, wrap) → {Phaser.BitmapData}
-
Shifts the contents of this BitmapData by the distances given.
The image will wrap-around the edges on all sides if the wrap argument is true (the default).
Parameters:
Name Type Argument Default Description x
integer The amount of pixels to horizontally shift the canvas by. Use a negative value to shift to the left, positive to the right.
y
integer The amount of pixels to vertically shift the canvas by. Use a negative value to shift up, positive to shift down.
wrap
boolean <optional>
true Wrap the content of the BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 228
-
moveH(distance, wrap) → {Phaser.BitmapData}
-
Shifts the contents of this BitmapData horizontally.
The image will wrap-around the sides if the wrap argument is true (the default).
Parameters:
Name Type Argument Default Description distance
integer The amount of pixels to horizontally shift the canvas by. Use a negative value to shift to the left, positive to the right.
wrap
boolean <optional>
true Wrap the content of the BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 255
-
moveV(distance, wrap) → {Phaser.BitmapData}
-
Shifts the contents of this BitmapData vertically.
The image will wrap-around the sides if the wrap argument is true (the default).
Parameters:
Name Type Argument Default Description distance
integer The amount of pixels to vertically shift the canvas by. Use a negative value to shift up, positive to shift down.
wrap
boolean <optional>
true Wrap the content of the BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 318
-
processPixel(callback, callbackContext, x, y, width, height) → {Phaser.BitmapData}
-
Scans through the area specified in this BitmapData and sends the color for every pixel to the given callback along with its x and y coordinates. Whatever value the callback returns is set as the new color for that pixel, unless it returns the same color, in which case it's skipped. Note that the format of the color received will be different depending on if the system is big or little endian. It is expected that your callback will deal with endianess. If you'd rather Phaser did it then use processPixelRGB instead. The callback will also be sent the pixels x and y coordinates respectively.
Parameters:
Name Type Argument Default Description callback
function The callback that will be sent each pixel color to be processed.
callbackContext
object The context under which the callback will be called.
x
number <optional>
0 The x coordinate of the top-left of the region to process from.
y
number <optional>
0 The y coordinate of the top-left of the region to process from.
width
number <optional>
The width of the region to process.
height
number <optional>
The height of the region to process.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 688
-
processPixelRGB(callback, callbackContext, x, y, width, height) → {Phaser.BitmapData}
-
Scans through the area specified in this BitmapData and sends a color object for every pixel to the given callback. The callback will be sent a color object with 6 properties:
{ r: number, g: number, b: number, a: number, color: number, rgba: string }
. Where r, g, b and a are integers between 0 and 255 representing the color component values for red, green, blue and alpha. Thecolor
property is an Int32 of the full color. Note the endianess of this will change per system. Thergba
property is a CSS style rgba() string which can be used with context.fillStyle calls, among others. The callback will also be sent the pixels x and y coordinates respectively. The callback must return eitherfalse
, in which case no change will be made to the pixel, or a new color object. If a new color object is returned the pixel will be set to the r, g, b and a color values given within it.Parameters:
Name Type Argument Default Description callback
function The callback that will be sent each pixel color object to be processed.
callbackContext
object The context under which the callback will be called.
x
number <optional>
0 The x coordinate of the top-left of the region to process from.
y
number <optional>
0 The y coordinate of the top-left of the region to process from.
width
number <optional>
The width of the region to process.
height
number <optional>
The height of the region to process.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 630
-
rect(x, y, width, height, fillStyle) → {Phaser.BitmapData}
-
Draws a filled Rectangle to the BitmapData at the given x, y coordinates and width / height in size.
Parameters:
Name Type Argument Description x
number The x coordinate of the top-left of the Rectangle.
y
number The y coordinate of the top-left of the Rectangle.
width
number The width of the Rectangle.
height
number The height of the Rectangle.
fillStyle
string <optional>
If set the context fillStyle will be set to this value before the rect is drawn.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1656
-
render() → {Phaser.BitmapData}
-
If the game is running in WebGL this will push the texture up to the GPU if it's dirty. This is called automatically if the BitmapData is being used by a Sprite, otherwise you need to remember to call it in your render function. If you wish to suppress this functionality set BitmapData.disableTextureUpload to
true
.Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1833
-
replaceRGB(r1, g1, b1, a1, r2, g2, b2, a2, region) → {Phaser.BitmapData}
-
Replaces all pixels matching one color with another. The color values are given as two sets of RGBA values. An optional region parameter controls if the replacement happens in just a specific area of the BitmapData or the entire thing.
Parameters:
Name Type Argument Description r1
number The red color value to be replaced. Between 0 and 255.
g1
number The green color value to be replaced. Between 0 and 255.
b1
number The blue color value to be replaced. Between 0 and 255.
a1
number The alpha color value to be replaced. Between 0 and 255.
r2
number The red color value that is the replacement color. Between 0 and 255.
g2
number The green color value that is the replacement color. Between 0 and 255.
b2
number The blue color value that is the replacement color. Between 0 and 255.
a2
number The alpha color value that is the replacement color. Between 0 and 255.
region
Phaser.Rectangle <optional>
The area to perform the search over. If not given it will replace over the whole BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 742
-
resize(width, height) → {Phaser.BitmapData}
-
Resizes the BitmapData. This changes the size of the underlying canvas and refreshes the buffer.
Parameters:
Name Type Description width
integer The new width of the BitmapData.
height
integer The new height of the BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 540
-
setHSL(h, s, l, region) → {Phaser.BitmapData}
-
Sets the hue, saturation and lightness values on every pixel in the given region, or the whole BitmapData if no region was specified.
Parameters:
Name Type Argument Default Description h
number <optional>
null The hue, in the range 0 - 1.
s
number <optional>
null The saturation, in the range 0 - 1.
l
number <optional>
null The lightness, in the range 0 - 1.
region
Phaser.Rectangle <optional>
The area to perform the operation on. If not given it will run over the whole BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 792
-
setPixel(x, y, red, green, blue, immediate) → {Phaser.BitmapData}
-
Sets the color of the given pixel to the specified red, green and blue values.
Parameters:
Name Type Argument Default Description x
number The x coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
y
number The y coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
red
number The red color value, between 0 and 0xFF (255).
green
number The green color value, between 0 and 0xFF (255).
blue
number The blue color value, between 0 and 0xFF (255).
immediate
boolean <optional>
true If
true
the context.putImageData will be called and the dirty flag set.Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 955
-
setPixel32(x, y, red, green, blue, alpha, immediate) → {Phaser.BitmapData}
-
Sets the color of the given pixel to the specified red, green, blue and alpha values.
Parameters:
Name Type Argument Default Description x
number The x coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
y
number The y coordinate of the pixel to be set. Must lay within the dimensions of this BitmapData.
red
number The red color value, between 0 and 0xFF (255).
green
number The green color value, between 0 and 0xFF (255).
blue
number The blue color value, between 0 and 0xFF (255).
alpha
number The alpha color value, between 0 and 0xFF (255).
immediate
boolean <optional>
true If
true
the context.putImageData will be called and the dirty flag set.Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 916
-
shadow(color, blur, x, y) → {Phaser.BitmapData}
-
Sets the shadow properties of this BitmapDatas context which will affect all draw operations made to it. You can cancel an existing shadow by calling this method and passing no parameters. Note: At the time of writing (October 2014) Chrome still doesn't support shadowBlur used with drawImage.
Parameters:
Name Type Argument Default Description color
string The color of the shadow, given in a CSS format, i.e.
#000000
orrgba(0,0,0,1)
. Ifnull
orundefined
the shadow will be reset.blur
number <optional>
5 The amount the shadow will be blurred by. Low values = a crisp shadow, high values = a softer shadow.
x
number <optional>
10 The horizontal offset of the shadow in pixels.
y
number <optional>
10 The vertical offset of the shadow in pixels.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1539
-
shiftHSL(h, s, l, region) → {Phaser.BitmapData}
-
Shifts any or all of the hue, saturation and lightness values on every pixel in the given region, or the whole BitmapData if no region was specified. Shifting will add the given value onto the current h, s and l values, not replace them. The hue is wrapped to keep it within the range 0 to 1. Saturation and lightness are clamped to not exceed 1.
Parameters:
Name Type Argument Default Description h
number <optional>
null The amount to shift the hue by.
s
number <optional>
null The amount to shift the saturation by.
l
number <optional>
null The amount to shift the lightness by.
region
Phaser.Rectangle <optional>
The area to perform the operation on. If not given it will run over the whole BitmapData.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 853
-
text(text, x, y, font, color, shadow) → {Phaser.BitmapData}
-
Draws text to the BitmapData in the given font and color. The default font is 14px Courier, so useful for quickly drawing debug text. If you need to do a lot of font work to this BitmapData we'd recommend implementing your own text draw method.
Parameters:
Name Type Argument Default Description text
string The text to write to the BitmapData.
x
number The x coordinate of the top-left of the text string.
y
number The y coordinate of the top-left of the text string.
font
string <optional>
'14px Courier' The font. This is passed directly to Context.font, so anything that can support, this can.
color
string <optional>
'rgb(255,255,255)' The color the text will be drawn in.
shadow
boolean <optional>
true Draw a single pixel black shadow below the text (offset by text.x/y + 1)
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1680
-
textureLine(line, image, repeat) → {Phaser.BitmapData}
-
Takes the given Line object and image and renders it to this BitmapData as a repeating texture line.
Parameters:
Name Type Argument Default Description line
Phaser.Line A Phaser.Line object that will be used to plot the start and end of the line.
image
string | Image The key of an image in the Phaser.Cache to use as the texture for this line, or an actual Image.
repeat
string <optional>
'repeat-x' The pattern repeat mode to use when drawing the line. Either
repeat
,repeat-x
orno-repeat
.Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 1783
-
update(x, y, width, height) → {Phaser.BitmapData}
-
This re-creates the BitmapData.imageData from the current context. It then re-builds the ArrayBuffer, the data Uint8ClampedArray reference and the pixels Int32Array. If not given the dimensions defaults to the full size of the context.
Warning: This is a very expensive operation, so use it sparingly.
Parameters:
Name Type Argument Default Description x
number <optional>
0 The x coordinate of the top-left of the image data area to grab from.
y
number <optional>
0 The y coordinate of the top-left of the image data area to grab from.
width
number <optional>
1 The width of the image data area.
height
number <optional>
1 The height of the image data area.
Returns:
This BitmapData object for method chaining.
- Source - gameobjects/BitmapData.js, line 584


NOTE: This review contains information that some may consider to be spoilerish, and those who are yet to see this film and want to know as little about it as possible before doing so are advised not to read any further.
-------------------------------- Alien Resurrection (aka Alien 4) -------------------------------- Starring Sigourney Weaver, Winona Ryder Directed by Jean-Pierre Jeunet
In resurrecting the character of Ellen Ripley (Sigorney Weaver), lead character of the Alien-series, the writers of Alien Resurrection fully intend to have their cake and eat it. Presumably thinking that, since audiences will have to suspend their disbelief anyway to allow them to bring back the deceased heroine, they should also be able to swallow that the Ripley clone is, for all plot-purposes, in the same state as she was in before she died: not only still pregnant with an alien queen but also, with help of the shared hive-mind of the alien DNA that she carries inside her she also has most of her pre-death memories (s-t-r-e-t-c-h) .
Scietists of an organization that is in actuality The Company from the previous installments in all but name (to make it believable that the film takes place 200 years after the third episode, you'll understand the writers at least had to change a few tags) have succeeded, on board of their huge space-lab (that despite its enormous size employs only 49 people) not only in creating a clone of Ripley, but more importantly, in getting ahold of that alien queen that has eluded their equally evil predecessors for so many decades. Living, human cryo-stored host bodies are smuggled in, unscrupulously impregnated by the "face hugging" aliens that emerge from the queen's eggs, and soon enough, a dozen of fully-grown creatures are ready for action. Needless to say, the monsters escape their cages, and once again Ripley, this time accompanied by the motley crew of smugglers that unsuspectingly delivered the host bodies to the scientists, can clean up the mess.
The first Alien film was an undisputed classic, the second a spectacular and tremendously enjoyable film, one of the few sequels that approach the original's quality, even surpassing it in some areas. So after the bleak, empty failure that was the third installment, 20th Century Fox had a lot riding on Alien Resurrection: it had to work, or the once mighty franchise was as good as dead. Fortunatly, the filmmakers, headed up by director Jean-Pierre Jeunet (City of the Lost Children) made this important installment with a keen eye for what went wrong in the third one. And to give credit where credit's due, they do manage to fix most of the problems that plaqued its predecessor. Unfortunatly, they forget to do much else.
Perhaps Alien3's most destructive failure was that its human characters were so incredibly dull and uninteresting that no-one could be bothered to tell them apart, let alone care whether or not they lived or died. In Alien 4, this problem is corrected, but unfortunatly it is done with so much zeal that the heroes of Alien Resurrection are the other end of a very large scale: every single character now has a gimmick, a trick, a neat twist, and as such they seem too "assembled"; more like the pixellated champions of a computer game like Street Fighter II than the champions of an installment of a classic movie-series. Granted, they may have bags of instant-character, but they are seriously shallow as well: the robotic mechanic Call (an adequate Winona Ryder), for example, can't hold a candle to female characters from Alien and Aliens in terms of depth and ability to hold audience interest. Nevertheless, characterization remains undeniably an improvement over Alien3. Certainly, Ripley's character remains interesting; Alien DNA now mixed with her own, she has animal instincts and even more of an attitude than usual. The lead scientist (a good turn by genre-actor Brad Dourif) says it best when he refers to her as "something of a predator" and Weaver certainly plays her 'new' role adequately.
But rather than focusing on what went wrong in part 3 and fixing that, it would have been nice if the filmmakers would have looked at what went right in parts 1 and 2 and had expanded on that. The first two films were filled with original, exciting action-and suspense sequences. Alien Resurrection has only one that's comparable to the best of those: a beautiful underwater-chase and subsequent sweaty-palmed ladder-encounter. And even that scene has a disappointing climax, with one of the Street Fighters falling a few feet down into the water but, inexplicably, never resurfacing. Oh, and in the meantime, Ripley is also briefly attacked by an impregnating "face hugger" alien -- possibly a nice lead-in for episode number five.
Other scenes that, while not classic, are not at all bad include a short sequence in which the cryo-stored human hosts are impregnated under authorization of the very evil scientists, the evacuation of the station when the alien menace first breaks loose, and a sequence near the end in which the (otherwise decidedly lacklustre) villain scientist is killed by an impregnated surviving host that's about to "chest-burst". Other than these, the film seriously lacks in the all-important department of great action: it has a few other contrived sequences but nothing particularly memorable. The aliens themselves aren't particularly threatening, strenuously holding back whenever the script needs them to, and since it needs them to so very often, they loose almost all of their punch -- for a lesson in How To, Jeunet could have looked not only to the originals, but also to Steven Spielberg's Jurassic Park, in which the velociraptors were consistantly threatening, and the film therefore consistently suspenseful (how embarrasing that an Alien film would be outclassed by a PG-rated Spielberg outing in terms of sheer horror). And I won't give away the climax of Alien 4, not merely because I don't want to spoil it for those who are yet to see the film, but rather because it's so ridiculous in every fashion that it's just not worth talking about.
There *are* some interesting scenes in Alien 4, but they are mostly the non-exciting ones. The scenes showing learning process of both the aliens and Ripley (yes, she *has* forgotten a few trivial things that she needs to re-learn -- like language) are well done, as is an intriguing (albeit somewhat oddly inserted) encounter between Ripley and her clone 'sisters': apparently, the new Ripley was the eighth attempt at a clone, and the ones among the first seven failures that we get to see are decidedly Geiger-esque (despite him having little to do with their design) and look horrifyingly great (production design is high overall: the huge lab-ship is impressive, the sleek smuggler's ship has a lovely japanimation-look). Another scene, in which Ripley shows that she can now play a mean game of basketball, goes a long way in establishing not only her 'new' character, but also that of her fellow street fighters. All these scenes can't conceal, though, that the plot is incredibly thin, despite attempts at a a 'different', more artistic Alien film, with 'kinky' moments and a ham-handed underlying mommy-and-child theme.
All in all, it sounds pretty terrible, doesn't it? Then let's sum up the strengths again: nice new characters which are well acted (Ron Perlman's tough guy Johner being my personal favorite, with Micheal Wincott -- as smuggler leader Eldyn -- also managing to impress in his short time on screen), some beautiful design (obviously, a lot of money was spent here), and a handful of pretty good scenes. Other than that, though, Alien 4 is an enjoyable but decidedly unspectacular and very shallow alien-battle romp, scarcely better than the far less pretensious (if more clichéd) Alien rip-off 'The Relic' of yesteryear. As such, it's much more entertaining than the third one, and certainly worth seeing for the starving fans of the sci-fi horror genre, but it is ultimately nothing more than a B-movie in fancy big budget clothing, and as such does the fans of the series few favors.
Ripley may have her full memory back, she's nevertheless appearing in a very forgetable film -- a film that's not bad in its own right, but in not exceeding mediocrity still fails to bring the series back on track. Yes, Fox can rest assured that Alien Resurrection doesn't immediatly kill the weakened franchise like another bad Alien film would have, but surely that franchise must now be considered to be living on borrowed time. One more outing like this and it's dead beyond resurrection.
Gerthein Boersma
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


This book is not meant to serve as an introduction to algorithms and data structures, nor is there any coherence in the sequence of the chapters. Instead, it is like visiting an adventure park where each ride explores fascinating and lesser-known worlds of algorithms and data structures. I have selected these rides simply because I love them, and I hope that you will find them enjoyable too.
| Chapter | Description |
| KHyperLogLog | An algorithm based on approximate counting techniques that can estimate certain privacy risks of very large databases using linear runtime and minimal memory. |
| Odd Sketches | A data structure that offers a more precise estimation of Jaccard similarity compared to b-bit minhashing, while also reducing the space complexity significantly compared to standard minhashing techniques. |
| GADDAG | A data structure for efficiently generating moves in Scrabble using a modified directed acyclic word graph. |
Eight.
I am hopeful that I will finish writing all the drafts by late-2024. Then, I plan on typesetting the book in LaTeX.
Excalidraw.
I got this breathtaking picture from Jared Rice, who took this image in Yucatan, Mexico. In one of his image descriptions, he wrote:
The feeling of this place is like a dream, I have never felt like I was transported to a different world quite like this. Walking out onto the edge of this walkway you lose the distraction of the outside world, you are forced to focus on the silence; all you can hear is the soft sounds of water moving over your feet.  The water is ever bit this teal color and the sun ray illuminates this underground cenote. I can see why the mayans viewed these places as sacred.This image is licensed under the Unsplash license.


Nick's Famous Pizza
Please enter your Name:
Please select a pizza size:
Small
Medium
Large
Extra large
Nick's Special Jumbo
Please select your toppings:
Cheese
Pepperoni
Mushrooms
Chicken
add another pizza
Go to Checkout


Toggle navigation
Suman Raj Venkatesan
Skills
Resume
Contact
Suman Raj
Mobile, Full-stack Web Developer - Cricket, Badminton Lover
"Enthusiastic and energetic software engineer building products that makes millions of users happy."
I'm Good At
Mobile Apps
Leadership
Web Apps
Frontend
Backend
User Experience
Testing
Open Source
Contact me
srajvenkat[at]icloud.com
+1-415-767-6538
@srajv
sraj
in/srajvenkat
San Francisco, California