摘要:
对stonedb子查询做性能分析
性能分析:
perf是一款Linux性能分析工具。Linux性能计数器是一个新的基于内核的子系统,它提供一个性能分析框架,比如硬件(CPU、PMU(Performance Monitoring Unit))功能和软件(软件计数器、tracepoint)功能。通过perf,应用程序可以利用PMU、tracepoint和内核中的计数器来进行性能统计。它不但可以分析指定应用程序的性能问题(per thread),也可以用来分析内核的性能问题,当然也可以同时分析应用程序和内核,从而全面理解应用程序中的性能瓶颈。
使用perf,可以分析程序运行期间发生的硬件事件,比如instructions retired、processor clock cycles等;也可以分析软件事件,比如page fault和进程切换。
火焰图:
调用堆栈:
(gdb) bt
#0 stonedb::core::FilterOnesIterator::FindOneInsidePack (this=0x7fd8b8005780) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/filter_iterators.cpp:259
#1 0x0000000002d5f2fb in stonedb::core::FilterOnesIterator::operator++ (this=0x7fd8b8005780) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/filter.h:366
#2 0x0000000002d5da3e in stonedb::core::FilterOnesIterator::NextPack (this=0x7fd8b8005780) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/filter_iterators.cpp:168
#3 0x0000000003138c7d in stonedb::core::DimensionGroupFilter::DGFilterIterator::NextPackrow (this=0x7fd8b8005770)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/dimension_group.h:198
#4 0x0000000003087c3d in stonedb::core::MIIterator::NextPackrow (this=0x7fdc801b4fc0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/mi_iterator.cpp:359
#5 0x0000000002e2321c in stonedb::core::TempTable::RoughAggregate (this=0x7fd8b8005a60, sender=0x0)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/temp_table_roughquery.cpp:413
#6 0x0000000002e21618 in stonedb::core::TempTable::RoughMaterialize (this=0x7fd8b8005a60, in_subq=true, sender=0x0, lazy=false)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/temp_table_roughquery.cpp:35
#7 0x0000000002dfded7 in stonedb::core::TempTableForSubquery::RoughMaterialize (this=0x7fd8b8005a60, in_subq=true, sender=0x0, lazy=false)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/temp_table.cpp:2218
#8 0x0000000002ea518d in stonedb::vcolumn::SubSelectColumn::RoughPrepareSubqCopy (this=0x7fd8b89e4bd0, mit=..., sot=stonedb::core::ROW_BASED)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/vc/subselect_column.cpp:415
#9 0x0000000002ea5823 in stonedb::vcolumn::SubSelectColumn::RoughIsEmpty (this=0x7fd8b89e4bd0, mit=..., sot=stonedb::core::ROW_BASED)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/vc/subselect_column.cpp:487
#10 0x0000000003055ec4 in stonedb::core::Descriptor::RoughCheckSubselectCondition (this=0x7fd8b8ad5dd0, mit=..., sot=stonedb::core::ROW_BASED)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/descriptor.cpp:1189
#11 0x00000000030527cc in stonedb::core::Descriptor::EvaluatePackImpl (this=0x7fd8b8ad5dd0, mit=...) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/descriptor.cpp:845
#12 0x0000000003052a3a in stonedb::core::Descriptor::EvaluatePack (this=0x7fd8b8ad5dd0, mit=...) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/descriptor.cpp:898
#13 0x00000000030b46c0 in stonedb::core::ParameterizedFilter::ApplyDescriptor (this=0x7fd8b8a40610, desc_number=1, limit=-1)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/parameterized_filter.cpp:1365
#14 0x00000000030b2b19 in stonedb::core::ParameterizedFilter::UpdateMultiIndex (this=0x7fd8b8a40610, count_only=false, limit=-1)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/parameterized_filter.cpp:1065
#15 0x0000000002d731f7 in stonedb::core::Query::Preexecute (this=0x7fdc801b6800, qu=..., sender=0x7fd8b89ed1d0, display_now=true)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/query.cpp:777
#16 0x0000000002d44a2e in stonedb::core::Engine::Execute (this=0x7dc9df0, thd=0x7fd8b80126f0, lex=0x7fd8b8014a18, result_output=0x7fd8b801bdd0, unit_for_union=0x0)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/engine_execute.cpp:421
#17 0x0000000002d43ce2 in stonedb::core::Engine::HandleSelect (this=0x7dc9df0, thd=0x7fd8b80126f0, lex=0x7fd8b8014a18, result=@0x7fdc801b6d18: 0x7fd8b801bdd0, setup_tables_done_option=0,
res=@0x7fdc801b6d14: 0, optimize_after_sdb=@0x7fdc801b6d0c: 1, sdb_free_join=@0x7fdc801b6d10: 1, with_insert=0)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/engine_execute.cpp:232
#18 0x0000000002e2c4c1 in stonedb::dbhandler::SDB_HandleSelect (thd=0x7fd8b80126f0, lex=0x7fd8b8014a18, result=@0x7fdc801b6d18: 0x7fd8b801bdd0, setup_tables_done_option=0, res=@0x7fdc801b6d14: 0,
optimize_after_sdb=@0x7fdc801b6d0c: 1, sdb_free_join=@0x7fdc801b6d10: 1, with_insert=0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/handler/ha_rcengine.cpp:82
#19 0x000000000246fe5a in execute_sqlcom_select (thd=0x7fd8b80126f0, all_tables=0x7fd8b800c980) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_:5182
#20 0x00000000024691de in mysql_execute_command (thd=0x7fd8b80126f0, first_level=true) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_:2831
#21 0x0000000002470e23 in mysql_parse (thd=0x7fd8b80126f0, parser_state=0x7fdc801b7eb0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_:5621
#22 0x00000000024660bb in dispatch_command (thd=0x7fd8b80126f0, com_data=0x7fdc801b8650, command=COM_QUERY) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_:1495
#23 0x0000000002464fe7 in do_command (thd=0x7fd8b80126f0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_:1034
#24 0x0000000002597c03 in handle_connection (arg=0x7dc3430) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/conn_handler/connection_handler_per_:313
#25 0x0000000002c7b834 in pfs_spawn_thread (arg=0x99ee3f0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/perfschema/:2197
#26 0x00007fdcd505eea5 in start_thread (arg=0x7fdc801b9700) at pthread_create.c:307
#27 0x00007fdcd3495b0d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
核心函数:
FilterOnesIterator::FindOneInsidePack
bool FilterOnesIterator::FindOneInsidePack() {
bool found = false;
// inter-block iteration
DEBUG_ASSERT(f->block_status[iterator_b] == f->FB_MIXED); // IteratorBpp() omits empty blocks
Filter::Block *cur_block = f->blocks[iterator_b];
int cb_no_obj = cur_block->no_obj;
if (iterator_b == static_cast<unsigned int>(prev_block)) {
ones_left_in_block--; // we already were in this block and the previous bit
// is after us
} else {
b = 0;
bitsLeft = 0;
lastn = -2;
bln = 0;
prev_block = iterator_b;
ones_left_in_block = cur_block->no_set_bits;
}
DEBUG_ASSERT(iterator_n < cb_no_obj || ones_left_in_block == 0);
if (iterator_n < cb_no_obj) {
// else leave "found == false", which will iterate to the next block
if (lastn + 1 == iterator_n) {
if (bitsLeft > 0) bitsLeft--;
b >>= 1;
} else {
bln = iterator_n >> 5;
int bitno = iterator_n & 0x1f;
b = cur_block->block_table[bln];
b >>= bitno;
bitsLeft = 32 - bitno;
}
// find bit == 1
while (!found && iterator_n < cb_no_obj) {
// first find a portion with 1
if (b == 0) {
iterator_n += bitsLeft;
if (++bln >= cur_block->block_size) break; // leave found == false
while (cur_block->block_table[bln] == 0) {
iterator_n += 32;
if (iterator_n >= cb_no_obj) break;
++bln;
}
if (iterator_n >= cb_no_obj) break;
b = cur_block->block_table[bln];
bitsLeft = 32;
}
while (iterator_n < cb_no_obj) {
// non-zero value found - process 32bit portion
int skip = cur_block->posOf1[b & 0xff];
if (skip > bitsLeft) {
// end of 32bit portion
iterator_n += bitsLeft;
break;
} else {
iterator_n += skip;
if (iterator_n >= cb_no_obj) break;
bitsLeft -= skip;
b >>= skip;
if (skip < 8) {
// found 1
lastn = iterator_n;
found = true;
break;
}
}
}
}
}
return found;
}