2022-04-26 18:14:09 +00:00
# pragma once
# include <Compression/ICompressionCodec.h>
# include <qpl/qpl.h>
2022-07-07 14:04:17 +00:00
2022-04-26 18:14:09 +00:00
namespace Poco
{
class Logger ;
}
namespace DB
{
2022-07-07 18:44:42 +00:00
/// DeflateJobHWPool is resource pool for provide the job objects which is required to save context infomation during offload asynchronous compression to IAA.
2022-04-26 18:14:09 +00:00
class DeflateJobHWPool
{
public :
DeflateJobHWPool ( ) ;
~ DeflateJobHWPool ( ) ;
static DeflateJobHWPool & instance ( ) ;
2022-07-07 16:10:06 +00:00
static constexpr auto JOB_POOL_SIZE = 1024 ;
2022-04-26 18:14:09 +00:00
static constexpr qpl_path_t PATH = qpl_path_hardware ;
2022-07-07 16:10:06 +00:00
static qpl_job * jobPool [ JOB_POOL_SIZE ] ;
static std : : atomic_bool jobLocks [ JOB_POOL_SIZE ] ;
2022-07-07 18:44:42 +00:00
bool job_pool_ready = false ;
2022-04-26 18:14:09 +00:00
2022-07-07 18:14:47 +00:00
bool jobPoolReady ( ) const
2022-06-08 15:47:44 +00:00
{
2022-07-07 18:44:42 +00:00
return job_pool_ready ;
2022-06-08 15:47:44 +00:00
}
2022-07-07 18:14:47 +00:00
2022-07-07 14:26:57 +00:00
qpl_job * acquireJob ( uint32_t * job_id )
2022-04-26 18:14:09 +00:00
{
2022-07-07 18:14:47 +00:00
if ( jobPoolReady ( ) )
2022-04-26 18:14:09 +00:00
{
2022-06-08 13:28:35 +00:00
uint32_t retry = 0 ;
2022-07-07 16:10:06 +00:00
auto index = random ( JOB_POOL_SIZE ) ;
2022-06-08 13:28:35 +00:00
while ( tryLockJob ( index ) = = false )
2022-04-26 18:14:09 +00:00
{
2022-07-07 16:10:06 +00:00
index = random ( JOB_POOL_SIZE ) ;
2022-06-08 13:28:35 +00:00
retry + + ;
2022-07-07 16:10:06 +00:00
if ( retry > JOB_POOL_SIZE )
2022-06-08 13:28:35 +00:00
{
return nullptr ;
}
2022-04-26 18:14:09 +00:00
}
2022-07-07 16:10:06 +00:00
* job_id = JOB_POOL_SIZE - index ;
2022-06-08 13:28:35 +00:00
return jobPool [ index ] ;
}
else
{
return nullptr ;
2022-04-26 18:14:09 +00:00
}
}
2022-07-07 18:14:47 +00:00
2022-07-07 14:26:57 +00:00
qpl_job * releaseJob ( uint32_t job_id )
2022-04-26 18:14:09 +00:00
{
2022-07-07 18:14:47 +00:00
if ( jobPoolReady ( ) )
2022-06-08 13:28:35 +00:00
{
2022-07-07 16:10:06 +00:00
uint32_t index = JOB_POOL_SIZE - job_id ;
2022-06-08 13:28:35 +00:00
ReleaseJobObjectGuard _ ( index ) ;
return jobPool [ index ] ;
}
else
{
return nullptr ;
}
2022-04-26 18:14:09 +00:00
}
2022-07-07 18:14:47 +00:00
2022-04-26 18:14:09 +00:00
private :
2022-07-07 18:14:47 +00:00
/// Returns true if Job pool initialization succeeded, otherwise false
bool initJobPool ( ) ;
2022-07-07 19:17:23 +00:00
static size_t random ( uint32_t pool_size )
2022-04-26 18:14:09 +00:00
{
size_t tsc = 0 ;
unsigned lo , hi ;
__asm__ volatile ( " rdtsc " : " =a " ( lo ) , " =d " ( hi ) : : ) ;
tsc = ( ( ( static_cast < uint64_t > ( hi ) ) < < 32 ) | ( static_cast < uint64_t > ( lo ) ) ) ;
return ( static_cast < size_t > ( ( tsc * 44485709377909ULL ) > > 4 ) ) % pool_size ;
}
2022-07-07 14:26:57 +00:00
bool tryLockJob ( size_t index )
2022-04-26 18:14:09 +00:00
{
bool expected = false ;
2022-07-07 16:10:06 +00:00
return jobLocks [ index ] . compare_exchange_strong ( expected , true ) ;
2022-04-26 18:14:09 +00:00
}
2022-07-07 14:26:57 +00:00
void destroyJobPool ( )
2022-04-26 18:14:09 +00:00
{
2022-07-07 18:44:42 +00:00
uint32_t size = 0 ;
qpl_get_job_size ( PATH , & size ) ;
2022-07-07 16:10:06 +00:00
for ( uint32_t i = 0 ; i < JOB_POOL_SIZE & & size > 0 ; + + i )
2022-04-26 18:14:09 +00:00
{
2022-07-07 18:44:42 +00:00
while ( tryLockJob ( i ) = = false ) ;
2022-04-26 18:14:09 +00:00
if ( jobPool [ i ] )
{
qpl_fini_job ( jobPool [ i ] ) ;
delete [ ] jobPool [ i ] ;
}
jobPool [ i ] = nullptr ;
2022-07-07 16:10:06 +00:00
jobLocks [ i ] . store ( false ) ;
2022-04-26 18:14:09 +00:00
}
}
struct ReleaseJobObjectGuard
{
uint32_t index ;
ReleaseJobObjectGuard ( ) = delete ;
public :
2022-07-07 14:26:57 +00:00
ReleaseJobObjectGuard ( const uint32_t i ) : index ( i )
2022-04-26 18:14:09 +00:00
{
}
2022-07-07 18:14:47 +00:00
2022-07-07 14:26:57 +00:00
~ ReleaseJobObjectGuard ( )
2022-04-26 18:14:09 +00:00
{
2022-07-07 16:10:06 +00:00
jobLocks [ index ] . store ( false ) ;
2022-04-26 18:14:09 +00:00
}
} ;
2022-06-08 15:47:44 +00:00
Poco : : Logger * log ;
} ;
2022-07-07 18:14:47 +00:00
2022-06-08 15:47:44 +00:00
class SoftwareCodecDeflate
{
public :
SoftwareCodecDeflate ( ) ;
~ SoftwareCodecDeflate ( ) ;
uint32_t doCompressData ( const char * source , uint32_t source_size , char * dest , uint32_t dest_size ) ;
void doDecompressData ( const char * source , uint32_t source_size , char * dest , uint32_t uncompressed_size ) ;
private :
2022-07-07 18:14:47 +00:00
qpl_job * jobSWPtr ;
2022-06-08 15:47:44 +00:00
std : : unique_ptr < uint8_t [ ] > jobSWbuffer ;
qpl_job * getJobCodecPtr ( ) ;
2022-04-26 18:14:09 +00:00
} ;
2022-06-08 15:47:44 +00:00
class HardwareCodecDeflate
{
public :
bool hwEnabled ;
HardwareCodecDeflate ( ) ;
~ HardwareCodecDeflate ( ) ;
uint32_t doCompressData ( const char * source , uint32_t source_size , char * dest , uint32_t dest_size ) const ;
uint32_t doDecompressData ( const char * source , uint32_t source_size , char * dest , uint32_t uncompressed_size ) const ;
uint32_t doDecompressDataReq ( const char * source , uint32_t source_size , char * dest , uint32_t uncompressed_size ) ;
2022-07-07 18:14:47 +00:00
void flushAsynchronousDecompressRequests ( ) ;
2022-06-08 15:47:44 +00:00
private :
std : : map < uint32_t , qpl_job * > jobDecompAsyncMap ;
Poco : : Logger * log ;
} ;
2022-04-26 18:14:09 +00:00
class CompressionCodecDeflate : public ICompressionCodec
{
public :
CompressionCodecDeflate ( ) ;
uint8_t getMethodByte ( ) const override ;
void updateHash ( SipHash & hash ) const override ;
protected :
bool isCompression ( ) const override
{
return true ;
}
2022-07-07 18:14:47 +00:00
2022-04-26 18:14:09 +00:00
bool isGenericCompression ( ) const override
{
return true ;
}
2022-07-07 18:14:47 +00:00
2022-04-26 18:14:09 +00:00
uint32_t doCompressData ( const char * source , uint32_t source_size , char * dest ) const override ;
void doDecompressData ( const char * source , uint32_t source_size , char * dest , uint32_t uncompressed_size ) const override ;
2022-07-07 18:14:47 +00:00
void flushAsynchronousDecompressRequests ( ) override ;
2022-04-26 18:14:09 +00:00
private :
uint32_t getMaxCompressedDataSize ( uint32_t uncompressed_size ) const override ;
2022-07-07 18:14:47 +00:00
std : : unique_ptr < HardwareCodecDeflate > hw_codec ;
std : : unique_ptr < SoftwareCodecDeflate > sw_codec ;
2022-04-26 18:14:09 +00:00
} ;
}