Compare commits

...

16 Commits

Author SHA1 Message Date
karmvs 192c653064 Implementing changes for Varchar vector 2021-02-26 13:38:24 -05:00
liaodenghong 18f62408b4 !613 hash agg operator related changes
* use omni runtime get results method
* Merge branch 'omni-cache-integration' of https://gitee.com/gravitys169…
* Merge branch 'omni-cache-integration' of https://gitee.com/openlookeng…
* add TestHashAggregationOmniOperator
* Merge remote-tracking branch 'origin/omni-cache-integration' into omni…
*  This is a combination of 2 commits.
* add HashAggregationOmniWork
* !574 fix vec
* !571 omni cache with olk-fix bug
* Merge remote-tracking branch 'origin/omni-cache-integration' into omni…
* multiple pages omni support
* !569 omni cache with olk-fix bug
* multiple pages omni support
* !567 omni cache with olk
* !565 support new shuffle framework
2021-02-18 15:46:29 +08:00
Haochen Ding 060d9aa8fb Use OmniRuntime.getResults() instead of OmniRuntime.execute() to get processed results from OmniCache 2021-02-16 23:20:44 -05:00
Haochen Ding 2e664319d0 Fix issues after revoming generics from Omni Vectors 2021-02-15 18:28:23 -05:00
gravitys169 403db25390 add HashAggregationOmniWork before merge olk omni integration 2021-02-15 17:41:22 -05:00
gravitys169 f21318dfce add HashAggregationOmniWork 2021-02-15 17:41:22 -05:00
Haochen Ding 944d9b359b Added DoubleArrayBlock and using DoubleVec from OmniCache directly 2021-02-15 17:41:22 -05:00
liaodenghong 5db57ae57a !574 fix vec
* fix some issues
* multiple pages omni support
2021-02-15 17:41:22 -05:00
liaodenghong 5319205e30 !571 omni cache with olk-fix bug
* Merge branch 'omni-cache-integration' of gitee.com:openlookeng/hetu-co…
* Merge remote-tracking branch 'origin/omni-cache-integration' into omni…
* multiple pages omni support
* multiple pages omni support
2021-02-15 17:41:22 -05:00
liaodenghong cc4130fc0d !569 omni cache with olk-fix bug
* multiple pages omni support
2021-02-15 17:41:22 -05:00
liaodenghong 20236a7771 !567 omni cache with olk
* Merge branch 'omni-cache-integration' of gitee.com:openlookeng/hetu-co…
* multiple pages omni support
* working on the multiple page 2
* working on the multiple page
* 0.fix the codestyle
2021-02-15 17:41:15 -05:00
Arven 70ca802271 !561 Integrate OmniVector with Integer, Double, Float, Date blocks
Merge pull request !561 from Arven/omni-cache
2021-01-29 11:37:18 +08:00
Haochen Ding bad3f729aa Integrate Omni Vector with Integer, Double, Float columns 2021-01-28 16:52:02 -05:00
Haochen Ding 7266a1e2ec Fix class loader violation in presto-spi and resolved some merge conflicts 2021-01-25 18:28:02 -05:00
karmvs 55722a5cba LongArrayBlock changes 2021-01-25 17:42:22 -05:00
Haochen Ding 173e5bbd2a Use OmniVector to build LongArrayBlock 2021-01-22 11:16:52 -05:00
59 changed files with 2422 additions and 237 deletions

View File

@ -48,7 +48,7 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5-og1.0.1</version>
<version>42.2.5</version>
</dependency>
<dependency>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -28,7 +28,7 @@
<properties>
<air.main.basedir>${project.basedir}</air.main.basedir>
<air.check.skip-all>true</air.check.skip-all>
<air.check.skip-spotbugs>true</air.check.skip-spotbugs>
<air.check.skip-pmd>true</air.check.skip-pmd>
<air.check.skip-jacoco>true</air.check.skip-jacoco>
@ -140,7 +140,7 @@
<module>hetu-sql-migration-tool</module>
<module>hetu-transport</module>
<module>hetu-server</module>
<module>hetu-server-rpm</module>
<!-- <module>hetu-server-rpm</module>-->
<module>hetu-common</module>
<module>hetu-hazelcast</module>
</modules>

View File

@ -98,6 +98,7 @@ public abstract class AbstractBenchmark
}
for (int i = 0; i < measuredIterations; i++) {
Map<String, Long> results = runOnce();
System.out.println("output_rows: " + results.get("output_rows") + " | output_bytes: " + results.get("output_bytes"));
if (benchmarkResultHook != null) {
benchmarkResultHook.addResults(results);
}

View File

@ -128,6 +128,11 @@ public abstract class AbstractOperatorBenchmark
new AllowAllAccessControl());
}
private static List<Split> getNextBatch(SplitSource splitSource)
{
return getFutureValue(splitSource.getNextBatch(NOT_PARTITIONED, Lifespan.taskWide(), 1000)).getSplits();
}
@Override
protected void tearDown()
{
@ -200,7 +205,7 @@ public abstract class AbstractOperatorBenchmark
};
}
private Split getLocalQuerySplit(Session session, TableHandle handle)
Split getLocalQuerySplit(Session session, TableHandle handle)
{
SplitSource splitSource = localQueryRunner.getSplitManager().getSplits(session, handle, UNGROUPED_SCHEDULING, null, Optional.empty(), Collections.emptyMap(), ImmutableSet.of(), false);
List<Split> splits = new ArrayList<>();
@ -211,11 +216,6 @@ public abstract class AbstractOperatorBenchmark
return splits.get(0);
}
private static List<Split> getNextBatch(SplitSource splitSource)
{
return getFutureValue(splitSource.getNextBatch(NOT_PARTITIONED, Lifespan.taskWide(), 1000)).getSplits();
}
protected final OperatorFactory createHashProjectOperator(int operatorId, PlanNodeId planNodeId, List<Type> types)
{
SymbolAllocator symbolAllocator = new SymbolAllocator();
@ -256,14 +256,17 @@ public abstract class AbstractOperatorBenchmark
protected Map<String, Long> execute(TaskContext taskContext)
{
List<Driver> drivers = createDrivers(taskContext);
long peakMemory = 0;
boolean done = false;
while (!done) {
boolean processed = false;
for (Driver driver : drivers) {
if (!driver.isFinished()) {
long start1 = System.currentTimeMillis();
driver.process();
long end1 = System.currentTimeMillis();
System.out.println("driver ID: "+driver.getDriverContext().getDriverId()+" execute time: " + (end1 - start1));
long lastPeakMemory = peakMemory;
peakMemory = (long) taskContext.getTaskStats().getUserMemoryReservation().getValue(BYTE);
if (peakMemory <= lastPeakMemory) {
@ -274,6 +277,7 @@ public abstract class AbstractOperatorBenchmark
}
done = !processed;
}
return ImmutableMap.of("peak_memory", peakMemory);
}

View File

@ -0,0 +1,231 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.benchmark;
import com.google.common.collect.ImmutableList;
import io.prestosql.operator.DriverContext;
import io.prestosql.operator.HashAggregationOmniOperator;
import io.prestosql.operator.Operator;
import io.prestosql.operator.OperatorContext;
import io.prestosql.operator.OperatorFactory;
import io.prestosql.operator.PageSourceOperator;
import io.prestosql.operator.aggregation.InternalAggregationFunction;
import io.prestosql.spi.Page;
import io.prestosql.spi.PageBuilder;
import io.prestosql.spi.block.BlockBuilder;
import io.prestosql.spi.connector.ConnectorPageSource;
import io.prestosql.spi.function.Signature;
import io.prestosql.spi.type.Type;
import io.prestosql.sql.planner.plan.PlanNodeId;
import io.prestosql.testing.LocalQueryRunner;
import nova.hetu.omnicache.runtime.OmniRuntime;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
import static io.prestosql.benchmark.BenchmarkQueryRunner.createLocalQueryRunner;
import static io.prestosql.spi.function.FunctionKind.AGGREGATE;
import static io.prestosql.spi.type.BigintType.BIGINT;
public class HashAggregationOmniBenchmark
extends AbstractSimpleOperatorBenchmark
{
public static Page inputPage;
public static Iterator<Page> inputPagesIterator;
private final InternalAggregationFunction longSum;
public HashAggregationOmniBenchmark(LocalQueryRunner localQueryRunner)
{
super(localQueryRunner, "hash_agg", 0, 1);
longSum = localQueryRunner.getMetadata().getAggregateFunctionImplementation(
new Signature("sum", AGGREGATE, BIGINT.getTypeSignature(), BIGINT.getTypeSignature()));
}
public static void builderPage()
{
List<Type> dataTypes = new ArrayList<>();
dataTypes.add(BIGINT);
dataTypes.add(BIGINT);
dataTypes.add(BIGINT);
dataTypes.add(BIGINT);
PageBuilder pb = PageBuilder.withMaxPageSize(Integer.MAX_VALUE, dataTypes);
BlockBuilder group1 = pb.getBlockBuilder(0);
BlockBuilder group2 = pb.getBlockBuilder(1);
BlockBuilder sum1 = pb.getBlockBuilder(2);
BlockBuilder sum2 = pb.getBlockBuilder(3);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
group1.writeLong(i);
group2.writeLong(j);
sum1.writeLong(i);
sum2.writeLong(j);
pb.declarePosition();
}
}
inputPage = pb.build();
List<Page> inputPages = new ArrayList<>();
for (int i = 0; i < 3; i++) {
inputPages.add(inputPage);
}
inputPagesIterator = inputPages.iterator();
}
public static void main(String[] args)
{
builderPage();
LocalQueryRunner localQueryRunner = createLocalQueryRunner();
new HashAggregationOmniBenchmark(localQueryRunner).runBenchmark(new SimpleLineBenchmarkResultWriter(System.out));
}
OperatorFactory createOmniCacheTableScanOperator(int operatorId, PlanNodeId planNodeId, String tableName, String... columnNames)
{
checkArgument(session.getCatalog().isPresent(), "catalog not set");
checkArgument(session.getSchema().isPresent(), "schema not set");
// // look up the table
// Metadata metadata = localQueryRunner.getMetadata();
// QualifiedObjectName qualifiedTableName = new QualifiedObjectName(session.getCatalog().get(), session.getSchema().get(), tableName);
// TableHandle tableHandle = metadata.getTableHandle(session, qualifiedTableName).orElse(null);
// checkArgument(tableHandle != null, "Table %s does not exist", qualifiedTableName);
//
// // lookup the columns
// Map<String, ColumnHandle> allColumnHandles = metadata.getColumnHandles(session, tableHandle);
// ImmutableList.Builder<ColumnHandle> columnHandlesBuilder = ImmutableList.builder();
// for (String columnName : columnNames) {
// ColumnHandle columnHandle = allColumnHandles.get(columnName);
// checkArgument(columnHandle != null, "Table %s does not have a column %s", tableName, columnName);
// columnHandlesBuilder.add(columnHandle);
// }
// List<ColumnHandle> columnHandles = columnHandlesBuilder.build();
//
// // get the split for this table
// Split split = getLocalQuerySplit(session, tableHandle);
return new OperatorFactory()
{
@Override
public Operator createOperator(DriverContext driverContext)
{
OperatorContext operatorContext = driverContext.addOperatorContext(operatorId, planNodeId, "BenchmarkSource");
ConnectorPageSource pageSource = createOmniCachePageSource();//localQueryRunner.getPageSourceManager().createPageSource(session, split, tableHandle, columnHandles, Optional.empty());
return new PageSourceOperator(pageSource, operatorContext);
}
@Override
public void noMoreOperators()
{
}
@Override
public OperatorFactory duplicate()
{
throw new UnsupportedOperationException();
}
};
}
private ConnectorPageSource createOmniCachePageSource()
{
return new ConnectorPageSource()
{
boolean isFinished = false;
@Override
public long getCompletedBytes()
{
return 0;
}
@Override
public long getReadTimeNanos()
{
return 0;
}
@Override
public boolean isFinished()
{
return isFinished;
}
@Override
public Page getNextPage()
{
if (inputPagesIterator.hasNext()) {
Page next = inputPagesIterator.next();
return next;
}
isFinished = true;
return null;
}
@Override
public long getSystemMemoryUsage()
{
return 0;
}
@Override
public void close()
throws IOException
{
}
};
}
@Override
protected List<? extends OperatorFactory> createOperatorFactories()
{
OperatorFactory tableScanOperator = createOmniCacheTableScanOperator(0, new PlanNodeId("test"), "orders", "orderstatus", "totalprice");
String compileID;
OmniRuntime omniRuntime;
//omni
long start = System.currentTimeMillis();
omniRuntime = new OmniRuntime();
// String code = "|k:vec[i64],v:vec[i64]|" +
// "let rs = tovec(result(for(zip(k,v),dictmerger[i64,i64,+],|b,i,n| merge(b,{n.$0,n.$1}))));" +
// "let k = result(for(rs,appender[i64],|b,i,n| merge(b,n.$0)));" +
// "let v = result(for(rs,appender[i64],|b,i,n| merge(b,n.$1)));" +
//// "{k,v}";
// String code = "|v0 :vec[vec[i64]], v1: vec[vec[i64]], v2: vec[vec[f64]], v3: vec[vec[f64]]|let sum_dict_ = for(zip(v0, v1, v2, v3), dictmerger[{i64,i64}, {f64, f64},+], |b,i,n|for(zip(n.0,n.1, n.2,n.3), b, |b_, i_, m|merge(b, {{m.0,m.1}, {m.2,m.3}})));let dict_0_1 = tovec(result(sum_dict_));let k0 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.0.0)));let k1 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.0.1)));let sum_1 = result(for(dict_0_1, appender[f64], |b, i, n| merge(b, n.1.0)));let sum_2 = result(for(dict_0_1, appender[f64], |b, i, n| merge(b, n.1.1)));{k0, k1, sum_1, sum_2}";
String code = "|v0 :vec[vec[i64]], v1: vec[vec[i64]], v2: vec[vec[f64]], v3: vec[vec[f64]]|" +
"let sum_dict_ = for(zip(v0, v1, v2, v3), dictmerger[{i64,i64}, {f64, f64},+], |b,i,n| " +
"for(zip(n.$0, n.$1, n.$2, n.$3), b, |b_, i_, m|" +
"merge(b, {{m.$0, m.$1}, {m.$2, m.$3}})));" +
"let dict_0_1 = tovec(result(sum_dict_));" +
"let k0 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$0.$0)));" +
"let k1 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$0.$1)));" +
"let sum_1 = result( for (dict_0_1, appender[f64], |b, i, n | merge(b, n.$1.$0)));" +
"let sum_2 = result( for (dict_0_1, appender[f64], |b, i, n | merge(b, n.$1.$1)));" +
"{k0, k1, sum_1, sum_2}";
compileID = omniRuntime.compile(code);
long end = System.currentTimeMillis();
System.out.println("omni compile time: " + (end - start));
HashAggregationOmniOperator.HashAggregationOmniOperatorFactory aggregationOperator = new HashAggregationOmniOperator.HashAggregationOmniOperatorFactory(1, new PlanNodeId("1"), omniRuntime, Collections.singletonList(compileID));
System.out.println("create hash op fac execute time: " + (System.currentTimeMillis() - start));
return ImmutableList.of(tableScanOperator, aggregationOperator);
}
}

View File

@ -68,7 +68,7 @@ import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@ThreadSafe
class StatementClientV1
public class StatementClientV1
implements StatementClient
{
private static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain; charset=utf-8");
@ -123,6 +123,26 @@ class StatementClientV1
processResponse(response.getHeaders(), response.getValue());
}
private static String urlEncode(String value)
{
try {
return URLEncoder.encode(value, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
private static String urlDecode(String value)
{
try {
return URLDecoder.decode(value, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
private Request buildQueryRequest(ClientSession session, String query)
{
HttpUrl url = HttpUrl.get(session.getServer());
@ -515,26 +535,6 @@ class StatementClientV1
}
}
private static String urlEncode(String value)
{
try {
return URLEncoder.encode(value, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
private static String urlDecode(String value)
{
try {
return URLDecoder.decode(value, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
private enum State
{
/**

View File

@ -23,6 +23,7 @@ import io.prestosql.spi.block.BlockEncoding;
import io.prestosql.spi.block.BlockEncodingSerde;
import io.prestosql.spi.block.ByteArrayBlockEncoding;
import io.prestosql.spi.block.DictionaryBlockEncoding;
import io.prestosql.spi.block.DoubleArrayBlockEncoding;
import io.prestosql.spi.block.Int128ArrayBlockEncoding;
import io.prestosql.spi.block.IntArrayBlockEncoding;
import io.prestosql.spi.block.LazyBlockEncoding;
@ -53,6 +54,7 @@ public final class ExternalBlockEncodingSerde
.put(ByteArrayBlockEncoding.NAME, new ByteArrayBlockEncoding())
.put(ShortArrayBlockEncoding.NAME, new ShortArrayBlockEncoding())
.put(IntArrayBlockEncoding.NAME, new IntArrayBlockEncoding())
.put(DoubleArrayBlockEncoding.NAME, new DoubleArrayBlockEncoding())
.put(LongArrayBlockEncoding.NAME, new LongArrayBlockEncoding())
.put(Int128ArrayBlockEncoding.NAME, new Int128ArrayBlockEncoding())
.put(DictionaryBlockEncoding.NAME, new DictionaryBlockEncoding())

View File

@ -1,4 +0,0 @@
connector.name=dc
connection-url=http://localhost:8090
connection-user=root
connection-password=

View File

@ -1,9 +0,0 @@
#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used
# in production. For example configuration, see the Presto documentation.
#
connector.name=hive-hadoop2
hive.metastore.uri=thrift://localhost:9083

View File

@ -1,8 +0,0 @@
#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used
# in production. For example configuration, see the Presto documentation.
#
connector.name=jmx

View File

@ -1,9 +0,0 @@
#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used
# in production. For example configuration, see the Presto documentation.
#
connector.name=localfile
presto-logs.http-request-log.pattern=http-request.log*

View File

@ -1 +1,2 @@
connector.name=memory
memory.max-data-per-node=4GB

View File

@ -1,4 +0,0 @@
connector.name=postgresql
connection-url=jdbc:postgresql://postgres:15432/test
connection-user=swarm
connection-password=swarm

View File

@ -1,4 +0,0 @@
connector.name=sqlserver
connection-url=jdbc:sqlserver://localhost:1433
connection-user=sa
connection-password=sa

View File

@ -1,9 +0,0 @@
#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used
# in production. For example configuration, see the Presto documentation.
#
connector.name=presto-thrift
presto.thrift.client.addresses=127.0.0.1:1234

View File

@ -12,6 +12,8 @@ http-server.http.port=8080
http-server.max-request-header-size=64kB
http-server.max-response-header-size=64kB
#omnicache
stack-trace-visible=true
#To enable SSL
#http-server.https.enabled=true
@ -51,17 +53,15 @@ query.client.timeout=5m
query.min-expire-age=30m
plugin.bundles=\
../presto-tpch/pom.xml, \
../presto-resource-group-managers/pom.xml,\
../presto-memory/pom.xml,\
../presto-jmx/pom.xml,\
../presto-hive-hadoop2/pom.xml,\
../presto-example-http/pom.xml,\
../presto-kafka/pom.xml, \
../presto-tpch/pom.xml, \
../presto-local-file/pom.xml, \
../presto-mysql/pom.xml,\
../hetu-datacenter/pom.xml,\
../hetu-oracle/pom.xml, \
../presto-sqlserver/pom.xml, \
../presto-postgresql/pom.xml, \
../presto-thrift/pom.xml, \
@ -70,7 +70,11 @@ plugin.bundles=\
../hetu-seed-store/pom.xml,\
../hetu-listener/pom.xml,\
../hetu-filesystem-client/pom.xml,\
../hetu-heuristic-index/pom.xml
# ../hetu-oracle/pom.xml, \
# ../hetu-datacenter/pom.xml,\
# ../hetu-heuristic-index/pom.xml
presto.version=testversion
node-scheduler.include-coordinator=true
shuffle-service.host=192.168.0.202

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -16,6 +16,13 @@
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.ning/async-http-client -->
<dependency>
<groupId>com.ning</groupId>
<artifactId>async-http-client</artifactId>
<version>1.8.8</version>
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>

View File

@ -149,6 +149,7 @@ public final class SystemSessionProperties
public static final String REUSE_TABLE_SCAN = "reuse_table_scan";
public static final String SPILL_REUSE_TABLESCAN = "spill_reuse_tablescan";
public static final String SPILL_THRESHOLD_REUSE_TABLESCAN = "spill_threshold_reuse_tablescan";
public static final String OMNI_CACHE_ENABLED = "omni_cache_enabled";
private final List<PropertyMetadata<?>> sessionProperties;
@ -166,6 +167,11 @@ public final class SystemSessionProperties
HetuConfig hetuConfig)
{
sessionProperties = ImmutableList.of(
booleanProperty(
"omni_cache_enabled",
"omni cache enabled",
true,
false),
stringProperty(
EXECUTION_POLICY,
"Policy used for scheduling query tasks",
@ -687,11 +693,6 @@ public final class SystemSessionProperties
false));
}
public List<PropertyMetadata<?>> getSessionProperties()
{
return sessionProperties;
}
public static boolean isCrossRegionDynamicFilterEnabled(Session session)
{
return session.getSystemProperty(ENABLE_CROSS_REGION_DYNAMIC_FILTER, Boolean.class);
@ -1207,4 +1208,14 @@ public final class SystemSessionProperties
{
return session.getSystemProperty(SPILL_THRESHOLD_REUSE_TABLESCAN, Integer.class);
}
public static Boolean getOmniCacheEnabled(Session session)
{
return session.getSystemProperty(OMNI_CACHE_ENABLED, Boolean.class);
}
public List<PropertyMetadata<?>> getSessionProperties()
{
return sessionProperties;
}
}

View File

@ -50,6 +50,10 @@ public class TaskId
this.fullId = fullId;
}
public String getFullId(){
return fullId;
}
public QueryId getQueryId()
{
return new QueryId(QueryId.parseDottedId(fullId, 3, "taskId").get(0));

View File

@ -34,6 +34,7 @@ import io.prestosql.spi.block.BlockEncoding;
import io.prestosql.spi.block.BlockEncodingSerde;
import io.prestosql.spi.block.ByteArrayBlockEncoding;
import io.prestosql.spi.block.DictionaryBlockEncoding;
import io.prestosql.spi.block.DoubleArrayBlockEncoding;
import io.prestosql.spi.block.Int128ArrayBlockEncoding;
import io.prestosql.spi.block.IntArrayBlockEncoding;
import io.prestosql.spi.block.LazyBlockEncoding;
@ -189,6 +190,7 @@ public final class MetadataManager
addBlockEncoding(new ByteArrayBlockEncoding());
addBlockEncoding(new ShortArrayBlockEncoding());
addBlockEncoding(new IntArrayBlockEncoding());
addBlockEncoding(new DoubleArrayBlockEncoding());
addBlockEncoding(new LongArrayBlockEncoding());
addBlockEncoding(new Int128ArrayBlockEncoding());
addBlockEncoding(new DictionaryBlockEncoding());

View File

@ -0,0 +1,181 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.operator;
import com.google.common.util.concurrent.ListenableFuture;
import io.prestosql.execution.Lifespan;
import io.prestosql.spi.Page;
import io.prestosql.sql.planner.plan.PlanNodeId;
import nova.hetu.omnicache.runtime.OmniRuntime;
import nova.hetu.omnicache.vector.LongVec;
import nova.hetu.omnicache.vector.Vec;
import java.util.List;
import java.util.UUID;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
public class HashAggregationOmniOperator
implements Operator
{
OperatorContext operatorContext;
//omni
List<String> compileID;
OmniRuntime omniRuntime;
private boolean finishing;
private boolean finished;
// for yield when memory is not available
// private Work<?> unfinishedWork;
HashAggregationOmniWork<Object> omniWork;
private String omniKey;
public HashAggregationOmniOperator(OperatorContext operatorContext, OmniRuntime omniRuntime, List<String> compileID)
{
this.operatorContext = operatorContext;
this.omniKey= UUID.randomUUID().toString()+"-"+operatorContext.getDriverContext().getPipelineContext().getTaskId();
this.omniRuntime = omniRuntime;
this.compileID = compileID;
}
@Override
public OperatorContext getOperatorContext()
{
return this.operatorContext;
}
@Override
public void finish()
{
finishing = true;
}
@Override
public boolean isFinished()
{
return finished;
}
@Override
public void close()
throws Exception
{
}
@Override
public boolean needsInput()
{
if (finishing) {
return false;
}
if (omniWork != null && !omniWork.isFinished()) {
return false;
}
return true;
}
@Override
public void addInput(Page page)
{
checkState(!finishing, "Operator is already finishing");
requireNonNull(page, "page is null");
if (omniWork == null) {
omniWork = new HashAggregationOmniWork(page, omniRuntime, compileID, omniKey);
}
else {
omniWork.updatePages(page);
}
omniWork.process();
}
@Override
public Page getOutput()
{
if (finished) {
return null;
}
if (finishing) {
if (omniWork == null) {
finished = true;
return null;
}
if (omniWork != null && omniWork.isFinished()) {
finished = true;
return omniWork.getResult();
}
}
return null;
}
@Override
public ListenableFuture<?> startMemoryRevoke()
{
return null;
}
@Override
public void finishMemoryRevoke()
{
}
public static class HashAggregationOmniOperatorFactory
implements OperatorFactory
{
OmniRuntime omniRuntime;
List<String> compileID;
int operatorId;
PlanNodeId planNodeId;
public HashAggregationOmniOperatorFactory(int operatorId, PlanNodeId planNodeId, OmniRuntime omniRuntime, List<String> compileID)
{
this.operatorId = operatorId;
this.planNodeId = planNodeId;
this.omniRuntime = omniRuntime;
this.compileID = compileID;
}
@Override
public Operator createOperator(DriverContext driverContext)
{
OperatorContext operatorContext = driverContext.addOperatorContext(operatorId, planNodeId, HashAggregationOmniOperator.class.getSimpleName());
HashAggregationOmniOperator hashAggregationOperator = new HashAggregationOmniOperator(operatorContext, omniRuntime, compileID);
return hashAggregationOperator;
}
@Override
public void noMoreOperators()
{
}
@Override
public void noMoreOperators(Lifespan lifespan)
{
}
@Override
public OperatorFactory duplicate()
{
return null;
}
}
}

View File

@ -0,0 +1,125 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.operator;
import io.prestosql.spi.Page;
import io.prestosql.spi.block.Block;
import io.prestosql.spi.block.DoubleArrayBlock;
import io.prestosql.spi.block.LongArrayBlock;
import io.prestosql.spi.type.BigintType;
import io.prestosql.spi.type.DoubleType;
import io.prestosql.spi.type.Type;
import nova.hetu.omnicache.runtime.OmniOpStep;
import nova.hetu.omnicache.runtime.OmniRuntime;
import nova.hetu.omnicache.vector.DoubleVec;
import nova.hetu.omnicache.vector.IntVec;
import nova.hetu.omnicache.vector.LongVec;
import nova.hetu.omnicache.vector.Vec;
import nova.hetu.omnicache.vector.VecType;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkState;
public final class HashAggregationOmniWork<O>
implements Work<Page>
{
OmniRuntime omniRuntime;
List<String> compileID;
private boolean finished;
private Vec[] result;
private Page page;
String omniKey;
VecType[] outTypes;
public HashAggregationOmniWork(Page page, OmniRuntime omniRuntime, List<String> compileID, String omniKey)
{
this.page = page;
this.omniRuntime = omniRuntime;
this.compileID = compileID;
this.omniKey = omniKey;
}
@Override
public boolean process()
{
int channelCount = page.getChannelCount();
Vec[] inputData = new Vec[channelCount];
for (int i = 0; i < channelCount; i++) {
inputData[i] = page.getBlock(i).getValues();
}
// LongVec
//
int rowNum = page.getPositionCount();
outTypes = new VecType[] {VecType.LONG, VecType.LONG, VecType.LONG, VecType.LONG};
if (inputData[channelCount - 1] instanceof LongVec) {
omniRuntime.execute(compileID.get(0), omniKey, inputData, rowNum, outTypes, OmniOpStep.INTERMEDIATE);
}
else {
omniRuntime.execute(compileID.get(1), omniKey, inputData, rowNum, outTypes, OmniOpStep.INTERMEDIATE);
}
finished = true;
return true;
}
@Override
public Page getResult()
{
checkState(finished, "process has not finished");
result = (Vec[]) omniRuntime.getResults(omniKey, outTypes);
return toResult(result);
}
public Page toResult(Vec[] omniExecutionResult)
{
int positionCount = omniExecutionResult[0].size();
int chanelCount = omniExecutionResult.length;
boolean[] valueIsNull = new boolean[positionCount];
for (int i = 0; i < positionCount; i++) {
valueIsNull[i] = false;
}
Block[] blocks = new Block[chanelCount];
for (int i = 0; i < chanelCount; i++) {
if (omniExecutionResult[i] instanceof DoubleVec) {
blocks[i] = new DoubleArrayBlock(positionCount, Optional.of(valueIsNull), ((DoubleVec) omniExecutionResult[i]));
}
else {
blocks[i] = new LongArrayBlock(positionCount, Optional.of(valueIsNull), (LongVec) omniExecutionResult[i]);
}
}
Page page = new Page(blocks);
return page;
}
public boolean isFinished()
{
return finished;
}
public void updatePages(Page page)
{
this.page = page;
}
}

View File

@ -0,0 +1,94 @@
///*
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//package io.prestosql.operator;
//
//import com.google.common.util.concurrent.ListenableFuture;
//import io.prestosql.spi.Page;
//import nova.hetu.omnicache.runtime.OmniRuntime;
//import nova.hetu.omnicache.vector.Vec;
//import nova.hetu.omnicache.vector.VecType;
//
//import static com.google.common.base.Preconditions.checkState;
//
//public final class HashAggregationOmniWorkProcessor<T>
// implements WorkProcessor<T>
//{
//
// OmniRuntime omniRuntime;
// String compileID;
// private boolean finished;
// private Vec<?>[] result;
// private Page page;
//
// public HashAggregationOmniWorkProcessor(Page page,OmniRuntime omniRuntime, String compileID)
// {
// this.page=page;
// this.omniRuntime = omniRuntime;
// this.compileID = compileID;
// }
//
// @Override
// public boolean process()
// {
// Vec[] inputData = new Vec[2];
//// inputData[0] = (LongVec) page.getBlock(0).getValuesVec();
//// inputData[1] = (LongVec) page.getBlock(1).getValuesVec();
//
// for (int i = 0; i < inputData[0].size(); i++) {
// System.out.println("block0 before omni:" + inputData[0].get(i));
// System.out.println("block1 before omni:" + inputData[1].get(i));
// }
//
// int rowNum = page.getPositionCount();
//
// VecType[] outTypes = {VecType.LONG, VecType.LONG};
// long start1 = System.currentTimeMillis();
//
// result = omniRuntime.execute(compileID, inputData, rowNum, outTypes);
// Vec<?>[] vecs = (Vec<?>[]) result;
//
// for (int i = 0; i < vecs[0].size(); i++) {
// System.out.println("block0 after omni:" + vecs[0].get(i));
// System.out.println("block1 after omni:" + vecs[1].get(i));
// }
//
// long end1 = System.currentTimeMillis();
// System.out.println("omni execute time: " + (end1 - start1));
// finished = true;
// return true;
// }
//
// @Override
// public boolean isBlocked()
// {
// return false;
// }
//
// @Override
// public ListenableFuture<?> getBlockedFuture()
// {
// return null;
// }
//
// @Override
// public T getResult()
// {
// checkState(finished, "process has not finished");
// return result;
// }
//
// public boolean isFinished(){
// return finished;
// }
//}

View File

@ -19,6 +19,8 @@ import io.prestosql.operator.Work;
import io.prestosql.operator.WorkProcessor;
import io.prestosql.spi.Page;
import java.util.Optional;
public interface HashAggregationBuilder
extends AutoCloseable
{
@ -38,4 +40,8 @@ public interface HashAggregationBuilder
ListenableFuture<?> startMemoryRevoke();
void finishMemoryRevoke();
default WorkProcessor<Page> getOmniExecuteResult() {return null;}
default void setOmniExecuteResult(Optional<Object> o) {}
}

View File

@ -143,6 +143,15 @@ public class InMemoryHashAggregationBuilder
for (Aggregator aggregator : aggregators) {
aggregator.processPage(groupByIdBlock, page);
}
long l = 20000L;
for (long i = 1; i < l; i++) {
if (i % 5000==0) {
System.out.println(i);
}
for (long i1 = 1; i1 < l; i1++) {
long x = i / i1;
}
}
// we do not need any output from TransformWork for this case
return null;
});
@ -274,6 +283,16 @@ public class InMemoryHashAggregationBuilder
pageBuilder.reset();
// long l = 20000L;
// for (long i = 1; i < l; i++) {
// if (i % 4000==0) {
// System.out.println(i);
// }
// for (long i1 = 1; i1 < l; i1++) {
// long x = i / i1;
// }
// }
List<Type> types = groupByHash.getTypes();
while (!pageBuilder.isFull() && groupIds.hasNext()) {
int groupId = groupIds.nextInt();

View File

@ -46,7 +46,6 @@ import static java.lang.Math.max;
public class SpillableHashAggregationBuilder
implements HashAggregationBuilder
{
private InMemoryHashAggregationBuilder hashAggregationBuilder;
private final SpillerFactory spillerFactory;
private final List<AccumulatorFactory> accumulatorFactories;
private final AggregationNode.Step step;
@ -59,12 +58,12 @@ public class SpillableHashAggregationBuilder
private final LocalMemoryContext localRevocableMemoryContext;
private final long memoryLimitForMerge;
private final long memoryLimitForMergeWithMemory;
private final JoinCompiler joinCompiler;
private InMemoryHashAggregationBuilder hashAggregationBuilder;
private Optional<Spiller> spiller = Optional.empty();
private Optional<MergingHashAggregationBuilder> merger = Optional.empty();
private Optional<MergeHashSort> mergeHashSort = Optional.empty();
private ListenableFuture<?> spillInProgress = immediateFuture(null);
private final JoinCompiler joinCompiler;
// todo get rid of that and only use revocable memory
private long emptyHashAggregationBuilderSize;

View File

@ -86,6 +86,7 @@ public class PluginManager
.add("io.hete.core.type.")
.add("io.hete.core.util.")
.add("io.prestosql.sql.tree.")
.add("nova.hetu.omnicache.vector.")
.build();
private static final Logger log = Logger.get(PluginManager.class);

View File

@ -55,6 +55,7 @@ import io.prestosql.operator.ExchangeOperator.ExchangeOperatorFactory;
import io.prestosql.operator.ExplainAnalyzeOperator.ExplainAnalyzeOperatorFactory;
import io.prestosql.operator.FilterAndProjectOperator;
import io.prestosql.operator.GroupIdOperator;
import io.prestosql.operator.HashAggregationOmniOperator;
import io.prestosql.operator.HashAggregationOperator.HashAggregationOperatorFactory;
import io.prestosql.operator.HashBuilderOperator.HashBuilderOperatorFactory;
import io.prestosql.operator.HashSemiJoinOperator.HashSemiJoinOperatorFactory;
@ -206,6 +207,7 @@ import io.prestosql.sql.tree.SymbolReference;
import io.prestosql.statestore.StateStoreProvider;
import io.prestosql.statestore.listener.StateStoreListenerManager;
import io.prestosql.type.FunctionType;
import nova.hetu.omnicache.runtime.OmniRuntime;
import javax.inject.Inject;
@ -244,6 +246,7 @@ import static io.prestosql.SystemSessionProperties.getDynamicFilteringMaxPerDriv
import static io.prestosql.SystemSessionProperties.getDynamicFilteringWaitTime;
import static io.prestosql.SystemSessionProperties.getFilterAndProjectMinOutputPageRowCount;
import static io.prestosql.SystemSessionProperties.getFilterAndProjectMinOutputPageSize;
import static io.prestosql.SystemSessionProperties.getOmniCacheEnabled;
import static io.prestosql.SystemSessionProperties.getSpillOperatorThresholdReuseExchange;
import static io.prestosql.SystemSessionProperties.getTaskConcurrency;
import static io.prestosql.SystemSessionProperties.getTaskWriterCount;
@ -2969,6 +2972,7 @@ public class LocalExecutionPlanner
Optional<DataSize> maxPartialAggregationMemorySize,
boolean useSystemMemory)
{
List<Symbol> aggregationOutputSymbols = new ArrayList<>();
List<AccumulatorFactory> accumulatorFactories = new ArrayList<>();
for (Map.Entry<Symbol, Aggregation> entry : aggregations.entrySet()) {
@ -3019,6 +3023,59 @@ public class LocalExecutionPlanner
}
else {
Optional<Integer> hashChannel = hashSymbol.map(channelGetter(source));
if (getOmniCacheEnabled(session)) {
List<String> compileID = new ArrayList<>();
OmniRuntime omniRuntime;
long start = System.currentTimeMillis();
omniRuntime = new OmniRuntime();
ArrayList<String> codes = new ArrayList<>();
//two group by and two sum
codes.add("|v0 :vec[vec[i64]], v1: vec[vec[i64]], v2: vec[vec[i64]], v3: vec[vec[i64]]|" +
"let sum_dict_ = for(zip(v0, v1, v2, v3), dictmerger[{i64,i64}, {i64, i64},+], |b,i,n| " +
"for(zip(n.$0, n.$1, n.$2, n.$3), b, |b_, i_, m|" +
"merge(b, {{m.$0, m.$1}, {m.$2, m.$3}})));" +
"let dict_0_1 = tovec(result(sum_dict_));" +
"let k0 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$0.$0)));" +
"let k1 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$0.$1)));" +
"let sum_1 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$1.$0)));" +
"let sum_2 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$1.$1)));" +
"{k0, k1, sum_1, sum_2}");
// sum and avg--using DoubleArrayBlock
// codes.add("|v0 :vec[vec[i64]], v1: vec[vec[i64]], v2: vec[vec[i64]], v3: vec[vec[i64]]|" +
// "let sum_dict_2 = for(zip(v0, v1, v2), dictmerger[{i64,i64}, i64,+], |b,i,n| " +
// "for(zip(n.$0, n.$1, n.$2), b, |b_, i_, m|" +
// "merge(b, {{m.$0, m.$1}, m.$2})));" +
// "let dict_0_1 = tovec(result(sum_dict_2));" +
// "let k0 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.$0.$0)));" +
// "let k1 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.$0.$1)));" +
// "let sum_2 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.$1)));" +
// "let avg_sum_3 = for(zip(v0, v1, v3), dictmerger[{i64,i64}, {i64, i64}, +], |b,i,n| " +
// "for(zip(n.$0, n.$1, n.$2), b, |b_, i_, m|" +
// "merge(b, {{m.$0, m.$1}, {m.$2, i64(1)}})));" +
// "let avg_3 = result(for(tovec(result(avg_sum_3)), appender[f64], |b, i, n| merge(b, f64(n.$1.$0) / f64(n.$1.$1))));" +
// "{k0, k1, sum_2, avg_3}");
// codes.add("|v0 :vec[vec[i64]], v1: vec[vec[i64]], v2: vec[vec[i64]], v3: vec[vec[f64]]|" +
// "let sum_dict_2 = for(zip(v0, v1, v2), dictmerger[{i64,i64}, i64,+], |b,i,n| " +
// "for(zip(n.$0, n.$1, n.$2), b, |b_, i_, m|" +
// "merge(b, {{m.$0, m.$1}, m.$2})));" +
// "let dict_0_1 = tovec(result(sum_dict_2));" +
// "let k0 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.$0.$0)));" +
// "let k1 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.$0.$1)));" +
// "let sum_2 = result(for(dict_0_1, appender[i64], |b, i, n| merge(b, n.$1)));" +
// "let avg_sum_3 = for(zip(v0, v1, v3), dictmerger[{i64,i64}, {f64, f64}, +], |b,i,n| " +
// "for(zip(n.$0, n.$1, n.$2), b, |b_, i_, m|" +
// "merge(b, {{m.$0, m.$1}, {m.$2, 1.0}})));" +
// "let avg_3 = result(for(tovec(result(avg_sum_3)), appender[f64], |b, i, n| merge(b, f64(n.$1.$0) / f64(n.$1.$1))));" +
// "{k0, k1, sum_2, avg_3}");
for (String code : codes) {
compileID.add(omniRuntime.compile(code));
}
log.info("omni compile time: %s",System.currentTimeMillis()-start);
return new HashAggregationOmniOperator.HashAggregationOmniOperatorFactory(context.getNextOperatorId(), planNodeId, omniRuntime, compileID);
}
return new HashAggregationOperatorFactory(
context.getNextOperatorId(),
planNodeId,

View File

@ -126,6 +126,37 @@ public class TestAggregationOperator
assertEquals(driverContext.getMemoryUsage(), 0);
}
@Test
public void testAggregation1()
{
List<Page> input = rowPagesBuilder(VARCHAR, BIGINT, VARCHAR, BIGINT, REAL, DOUBLE, VARCHAR)
.addSequencePage(100000000, 0, 0, 300, 500, 400, 500, 500)
.build();
long start = System.currentTimeMillis();
OperatorFactory operatorFactory = new AggregationOperatorFactory(
0,
new PlanNodeId("test"),
Step.SINGLE,
ImmutableList.of(
LONG_SUM.bind(ImmutableList.of(1), Optional.empty())
),
false);
DriverContext driverContext = createTaskContext(executor, scheduledExecutor, TEST_SESSION)
.addPipelineContext(0, true, true, false)
.addDriverContext();
MaterializedResult expected = resultBuilder(driverContext.getSession(), BIGINT)
.row(4999999950000000L)
.build();
assertOperatorEquals(operatorFactory, driverContext, input, expected);
long end = System.currentTimeMillis() - start;
System.out.println("presto takes: " + end + " ms");
assertEquals(driverContext.getSystemMemoryUsage(), 0);
assertEquals(driverContext.getMemoryUsage(), 0);
}
@Test
public void testMemoryTracking()
throws Exception

View File

@ -0,0 +1,282 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.operator;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import io.prestosql.memory.context.AggregatedMemoryContext;
import io.prestosql.metadata.Metadata;
import io.prestosql.operator.aggregation.InternalAggregationFunction;
import io.prestosql.operator.aggregation.builder.HashAggregationBuilder;
import io.prestosql.operator.aggregation.builder.InMemoryHashAggregationBuilder;
import io.prestosql.spi.Page;
import io.prestosql.spi.PageBuilder;
import io.prestosql.spi.block.BlockBuilder;
import io.prestosql.spi.function.Signature;
import io.prestosql.spi.type.Type;
import io.prestosql.spiller.Spiller;
import io.prestosql.spiller.SpillerFactory;
import io.prestosql.sql.gen.JoinCompiler;
import io.prestosql.sql.planner.plan.PlanNodeId;
import io.prestosql.testing.MaterializedResult;
import io.prestosql.testing.TestingTaskContext;
import nova.hetu.omnicache.runtime.OmniRuntime;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static io.airlift.concurrent.Threads.daemonThreadsNamed;
import static io.airlift.units.DataSize.succinctBytes;
import static io.prestosql.SessionTestUtils.TEST_SESSION;
import static io.prestosql.metadata.MetadataManager.createTestMetadataManager;
import static io.prestosql.operator.OperatorAssertion.assertPagesEqualIgnoreOrder;
import static io.prestosql.operator.OperatorAssertion.toPages;
import static io.prestosql.spi.function.FunctionKind.AGGREGATE;
import static io.prestosql.spi.type.BigintType.BIGINT;
import static io.prestosql.spi.type.DoubleType.DOUBLE;
import static io.prestosql.spi.type.VarcharType.VARCHAR;
import static io.prestosql.testing.MaterializedResult.resultBuilder;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
@Test(singleThreaded = true)
public class TestHashAggregationOmniOperator
{
private static final Metadata metadata = createTestMetadataManager();
private static final InternalAggregationFunction LONG_AVERAGE = metadata.getAggregateFunctionImplementation(
new Signature("avg", AGGREGATE, DOUBLE.getTypeSignature(), BIGINT.getTypeSignature()));
private static final InternalAggregationFunction LONG_SUM = metadata.getAggregateFunctionImplementation(
new Signature("sum", AGGREGATE, BIGINT.getTypeSignature(), BIGINT.getTypeSignature()));
private static final InternalAggregationFunction COUNT = metadata.getAggregateFunctionImplementation(
new Signature("count", AGGREGATE, BIGINT.getTypeSignature()));
private static final int MAX_BLOCK_SIZE_IN_BYTES = 64 * 1024;
private ExecutorService executor;
private ScheduledExecutorService scheduledExecutor;
private JoinCompiler joinCompiler = new JoinCompiler(createTestMetadataManager());
private DummySpillerFactory spillerFactory;
String weldIR = "|v0 :vec[vec[i64]], v1: vec[vec[i64]], v2: vec[vec[f64]], v3: vec[vec[f64]]|" +
"let sum_dict_ = for(zip(v0, v1, v2, v3), dictmerger[{i64,i64}, {f64, f64},+], |b,i,n| " +
"for(zip(n.$0, n.$1, n.$2, n.$3), b, |b_, i_, m|" +
"merge(b, {{m.$0, m.$1}, {m.$2, m.$3}})));" +
"let dict_0_1 = tovec(result(sum_dict_));" +
"let k0 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$0.$0)));" +
"let k1 = result( for (dict_0_1, appender[i64], |b, i, n | merge(b, n.$0.$1)));" +
"let sum_1 = result( for (dict_0_1, appender[f64], |b, i, n | merge(b, n.$1.$0)));" +
"let sum_2 = result( for (dict_0_1, appender[f64], |b, i, n | merge(b, n.$1.$1)));" +
"{k0, k1, sum_1, sum_2}";
@BeforeMethod
public void setUp()
{
executor = newCachedThreadPool(daemonThreadsNamed("test-executor-%s"));
scheduledExecutor = newScheduledThreadPool(2, daemonThreadsNamed("test-scheduledExecutor-%s"));
spillerFactory = new DummySpillerFactory();
}
@DataProvider(name = "hashEnabled")
public static Object[][] hashEnabled()
{
return new Object[][] {{true}, {false}};
}
@DataProvider(name = "hashEnabledAndMemoryLimitForMergeValues")
public static Object[][] hashEnabledAndMemoryLimitForMergeValuesProvider()
{
return new Object[][] {
{true, true, true, 8, Integer.MAX_VALUE},
{true, true, false, 8, Integer.MAX_VALUE},
{false, false, false, 0, 0},
{false, true, true, 0, 0},
{false, true, false, 0, 0},
{false, true, true, 8, 0},
{false, true, false, 8, 0},
{false, true, true, 8, Integer.MAX_VALUE},
{false, true, false, 8, Integer.MAX_VALUE}};
}
@DataProvider
public Object[][] dataType()
{
return new Object[][] {{VARCHAR}, {BIGINT}};
}
@AfterMethod(alwaysRun = true)
public void tearDown()
{
spillerFactory = null;
executor.shutdownNow();
scheduledExecutor.shutdownNow();
}
private List<Page> builderPage()
{
List<Type> dataTypes = new ArrayList<>();
dataTypes.add(BIGINT);
dataTypes.add(BIGINT);
dataTypes.add(BIGINT);
dataTypes.add(BIGINT);
PageBuilder pb = PageBuilder.withMaxPageSize(Integer.MAX_VALUE, dataTypes);
BlockBuilder group1 = pb.getBlockBuilder(0);
BlockBuilder group2 = pb.getBlockBuilder(1);
BlockBuilder sum1 = pb.getBlockBuilder(2);
BlockBuilder sum2 = pb.getBlockBuilder(3);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < pageRows; j++) {
group1.writeLong(i);
group2.writeLong(i);
sum1.writeLong(1);
sum2.writeLong(1);
pb.declarePosition();
}
}
Page build = pb.build();
List<Page> inputPages = new ArrayList<>();
for (int i = 0; i < totalPageCount; i++) {
inputPages.add(build);
}
return inputPages;
}
int pageRows = 10;
int totalPageCount = 1000;
@Test(invocationCount = 20)
public void testHashAggregation()
{
int threadNum = 100;
List<Page> input = builderPage();
OmniRuntime omniRuntime = new OmniRuntime();
String compileID = omniRuntime.compile(weldIR);
DriverContext driverContext = createDriverContext(Integer.MAX_VALUE);
MaterializedResult.Builder expectedBuilder = resultBuilder(driverContext.getSession(), BIGINT, BIGINT, BIGINT, BIGINT);
long sum = totalPageCount * pageRows;
expectedBuilder.row(0L, 0L, sum, sum);
expectedBuilder.row(1L, 1L, sum, sum);
MaterializedResult expected = expectedBuilder.build();
ExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(threadNum));
ArrayList<ListenableFuture<List<Page>>> futureArrayList = new ArrayList<>();
List<List<Page>> pagesList = new ArrayList<>();
for (int i = 0; i < threadNum; i++) {
final int x = i;
ListenableFuture<List<Page>> submit = (ListenableFuture<List<Page>>) service.submit(() -> toPages(new HashAggregationOmniOperator.HashAggregationOmniOperatorFactory(x, new PlanNodeId(String.valueOf(x)), omniRuntime, Collections.singletonList(compileID)), driverContext, input, false));
submit.addListener(() -> {
List<Page> pages = null;
try {
pages = submit.get();
}
catch (InterruptedException|ExecutionException e) {
e.printStackTrace();
}
pagesList.add(pages);
}, MoreExecutors.directExecutor());
futureArrayList.add(submit);
}
while (!futureArrayList.isEmpty()) {
Iterator<ListenableFuture<List<Page>>> iterator = futureArrayList.iterator();
while (iterator.hasNext()) {
ListenableFuture<List<Page>> next = iterator.next();
if (next.isDone()) {
if (futureArrayList.size()%10==0) {
System.out.println("thread i finsished: " + futureArrayList.size());
}
iterator.remove();
}
}
}
assertNotEquals(0, pagesList.size());
for (int i = 0; i < pagesList.size(); i++) {
assertPagesEqualIgnoreOrder(driverContext, pagesList.get(i), expected, false, Optional.empty());
}
}
private DriverContext createDriverContext()
{
return createDriverContext(Integer.MAX_VALUE);
}
private DriverContext createDriverContext(long memoryLimit)
{
return TestingTaskContext.builder(executor, scheduledExecutor, TEST_SESSION)
.setMemoryPoolSize(succinctBytes(memoryLimit))
.build()
.addPipelineContext(0, true, true, false)
.addDriverContext();
}
private int getHashCapacity(Operator operator)
{
assertTrue(operator instanceof HashAggregationOperator);
HashAggregationBuilder aggregationBuilder = ((HashAggregationOperator) operator).getAggregationBuilder();
if (aggregationBuilder == null) {
return 0;
}
assertTrue(aggregationBuilder instanceof InMemoryHashAggregationBuilder);
return ((InMemoryHashAggregationBuilder) aggregationBuilder).getCapacity();
}
private static class FailingSpillerFactory
implements SpillerFactory
{
@Override
public Spiller create(List<Type> types, SpillContext spillContext, AggregatedMemoryContext memoryContext)
{
return new Spiller()
{
@Override
public ListenableFuture<?> spill(Iterator<Page> pageIterator)
{
return immediateFailedFuture(new IOException("Failed to spill"));
}
@Override
public List<Iterator<Page>> getSpills()
{
return ImmutableList.of();
}
@Override
public void close()
{
}
};
}
}
}

View File

@ -108,17 +108,9 @@ public class TestHashAggregationOperator
private ExecutorService executor;
private ScheduledExecutorService scheduledExecutor;
private JoinCompiler joinCompiler = new JoinCompiler(createTestMetadataManager());
private final JoinCompiler joinCompiler = new JoinCompiler(createTestMetadataManager());
private DummySpillerFactory spillerFactory;
@BeforeMethod
public void setUp()
{
executor = newCachedThreadPool(daemonThreadsNamed("test-executor-%s"));
scheduledExecutor = newScheduledThreadPool(2, daemonThreadsNamed("test-scheduledExecutor-%s"));
spillerFactory = new DummySpillerFactory();
}
@DataProvider(name = "hashEnabled")
public static Object[][] hashEnabled()
{
@ -140,6 +132,21 @@ public class TestHashAggregationOperator
{false, true, false, 8, Integer.MAX_VALUE}};
}
@DataProvider(name = "hashEnabledAndMemoryLimitForMergeValues1")
public static Object[][] hashEnabledAndMemoryLimitForMergeValuesProvider1()
{
return new Object[][] {
{true, true, true, 8, Integer.MAX_VALUE}};
}
@BeforeMethod
public void setUp()
{
executor = newCachedThreadPool(daemonThreadsNamed("test-executor-%s"));
scheduledExecutor = newScheduledThreadPool(2, daemonThreadsNamed("test-scheduledExecutor-%s"));
spillerFactory = new DummySpillerFactory();
}
@DataProvider
public Object[][] dataType()
{
@ -158,7 +165,7 @@ public class TestHashAggregationOperator
public void testHashAggregation(boolean hashEnabled, boolean spillEnabled, boolean revokeMemoryWhenAddingPages, long memoryLimitForMerge, long memoryLimitForMergeWithMemory)
{
// make operator produce multiple pages during finish phase
int numberOfRows = 40_000;
int numberOfRows = 10;
Metadata metadata = createTestMetadataManager();
InternalAggregationFunction countVarcharColumn = metadata.getAggregateFunctionImplementation(
new Signature("count", AGGREGATE, parseTypeSignature(StandardTypes.BIGINT), parseTypeSignature(StandardTypes.VARCHAR)));
@ -170,8 +177,8 @@ public class TestHashAggregationOperator
RowPagesBuilder rowPagesBuilder = rowPagesBuilder(hashEnabled, hashChannels, VARCHAR, VARCHAR, VARCHAR, BIGINT, BOOLEAN);
List<Page> input = rowPagesBuilder
.addSequencePage(numberOfRows, 100, 0, 100_000, 0, 500)
.addSequencePage(numberOfRows, 100, 0, 200_000, 0, 500)
.addSequencePage(numberOfRows, 100, 0, 300_000, 0, 500)
// .addSequencePage(numberOfRows, 100, 0, 200_000, 0, 500)
// .addSequencePage(numberOfRows, 100, 0, 300_000, 0, 500)
.build();
HashAggregationOperatorFactory operatorFactory = new HashAggregationOperatorFactory(
@ -190,7 +197,7 @@ public class TestHashAggregationOperator
countBooleanColumn.bind(ImmutableList.of(4), Optional.empty())),
rowPagesBuilder.getHashChannel(),
Optional.empty(),
100_000,
2,
Optional.of(new DataSize(16, MEGABYTE)),
spillEnabled,
succinctBytes(memoryLimitForMerge),
@ -208,12 +215,64 @@ public class TestHashAggregationOperator
MaterializedResult expected = expectedBuilder.build();
List<Page> pages = toPages(operatorFactory, driverContext, input, revokeMemoryWhenAddingPages);
assertGreaterThan(pages.size(), 1, "Expected more than one output page");
// assertGreaterThan(pages.size(), 1, "Expected more than one output page");
assertPagesEqualIgnoreOrder(driverContext, pages, expected, hashEnabled, Optional.of(hashChannels.size()));
assertTrue(spillEnabled == (spillerFactory.getSpillsCount() > 0), format("Spill state mismatch. Expected spill: %s, spill count: %s", spillEnabled, spillerFactory.getSpillsCount()));
}
@Test(dataProvider = "hashEnabledAndMemoryLimitForMergeValues1")
public void testHashAggregation1(boolean hashEnabled, boolean spillEnabled, boolean revokeMemoryWhenAddingPages, long memoryLimitForMerge, long memoryLimitForMergeWithMemory)
{
// make operator produce multiple pages during finish phase
int numberOfRows = 100000000;
Metadata metadata = createTestMetadataManager();
List<Integer> hashChannels = Ints.asList(0);
RowPagesBuilder rowPagesBuilder = rowPagesBuilder(hashEnabled, hashChannels, VARCHAR, BIGINT);
List<Page> input = rowPagesBuilder
.addSequencePage(numberOfRows, 0, 0)
// .addSequencePage(numberOfRows, 0)
// .addSequencePage(numberOfRows, 0)
.build();
DriverContext driverContext = createDriverContext(memoryLimitForMerge);
MaterializedResult.Builder expectedBuilder = resultBuilder(driverContext.getSession(), VARCHAR, BIGINT);
for (int i = 0; i < numberOfRows; ++i) {
expectedBuilder.row(Integer.toString(i), (long) i);
}
MaterializedResult expected = expectedBuilder.build();
long start = System.currentTimeMillis();
HashAggregationOperatorFactory operatorFactory = new HashAggregationOperatorFactory(
0,
new PlanNodeId("test"),
ImmutableList.of(VARCHAR),
hashChannels,
ImmutableList.of(),
Step.SINGLE,
false,
ImmutableList.of(
LONG_SUM.bind(ImmutableList.of(1), Optional.empty())
),
rowPagesBuilder.getHashChannel(),
Optional.empty(),
1,
Optional.of(new DataSize(16, MEGABYTE)),
spillEnabled,
succinctBytes(memoryLimitForMerge),
succinctBytes(memoryLimitForMergeWithMemory),
spillerFactory,
joinCompiler,
false);
List<Page> pages = toPages(operatorFactory, driverContext, input, revokeMemoryWhenAddingPages);
long end = System.currentTimeMillis() - start;
System.out.println("presto takes: " + end + " ms");
// assertGreaterThan(pages.size(), 1, "Expected more than one output page");
assertPagesEqualIgnoreOrder(driverContext, pages, expected, hashEnabled, Optional.of(hashChannels.size()));
// assertTrue(spillEnabled == (spillerFactory.getSpillsCount() > 0), format("Spill state mismatch. Expected spill: %s, spill count: %s", spillEnabled, spillerFactory.getSpillsCount()));
}
@Test(dataProvider = "hashEnabledAndMemoryLimitForMergeValues")
public void testHashAggregationWithGlobals(boolean hashEnabled, boolean spillEnabled, boolean revokeMemoryWhenAddingPages, long memoryLimitForMerge, long memoryLimitForMergeWithMemory)
{

View File

@ -188,6 +188,18 @@
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>io.hetu.core</groupId>
<artifactId>omni-cache</artifactId>
<version>1.2.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>

View File

@ -365,7 +365,6 @@ public class OrcWriteValidation
requireNonNull(name, "name is null");
requireNonNull(actualColumnStatistics, "actualColumnStatistics is null");
requireNonNull(expectedColumnStatistics, "expectedColumnStatistics is null");
if (actualColumnStatistics.getNumberOfValues() != expectedColumnStatistics.getNumberOfValues()) {
throw new OrcCorruptionException(orcDataSourceId, "Write validation failed: unexpected number of values in %s statistics", name);
}

View File

@ -24,10 +24,11 @@ import io.prestosql.orc.stream.DoubleInputStream;
import io.prestosql.orc.stream.InputStreamSource;
import io.prestosql.orc.stream.InputStreamSources;
import io.prestosql.spi.block.Block;
import io.prestosql.spi.block.LongArrayBlock;
import io.prestosql.spi.block.DoubleArrayBlock;
import io.prestosql.spi.block.RunLengthEncodedBlock;
import io.prestosql.spi.type.DoubleType;
import io.prestosql.spi.type.Type;
import nova.hetu.omnicache.vector.DoubleVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
@ -42,14 +43,14 @@ import static io.airlift.slice.SizeOf.sizeOf;
import static io.prestosql.orc.metadata.Stream.StreamKind.DATA;
import static io.prestosql.orc.metadata.Stream.StreamKind.PRESENT;
import static io.prestosql.orc.reader.ReaderUtils.minNonNullValueSize;
import static io.prestosql.orc.reader.ReaderUtils.unpackLongNulls;
import static io.prestosql.orc.reader.ReaderUtils.unpackDoubleNulls;
import static io.prestosql.orc.reader.ReaderUtils.verifyStreamType;
import static io.prestosql.orc.stream.MissingInputStreamSource.missingStreamSource;
import static io.prestosql.spi.type.DoubleType.DOUBLE;
import static java.util.Objects.requireNonNull;
public class DoubleColumnReader
implements ColumnReader<Long>
implements ColumnReader<Double>
{
private static final int INSTANCE_SIZE = ClassLayout.parseClass(DoubleColumnReader.class).instanceSize();
@ -69,7 +70,7 @@ public class DoubleColumnReader
private boolean rowGroupOpen;
private long[] nonNullValueTemp = new long[0];
private double[] nonNullValueTemp = new double[0];
private final LocalMemoryContext systemMemoryContext;
@ -147,9 +148,9 @@ public class DoubleColumnReader
throws IOException
{
verify(dataStream != null);
long[] values = new long[nextBatchSize];
dataStream.next(values, nextBatchSize);
return new LongArrayBlock(nextBatchSize, Optional.empty(), values);
DoubleVec doubleVec = new DoubleVec(nextBatchSize);
dataStream.next(doubleVec, nextBatchSize);
return new DoubleArrayBlock(nextBatchSize, Optional.empty(), doubleVec);
}
private Block readNullBlock(boolean[] isNull, int nonNullCount)
@ -158,15 +159,15 @@ public class DoubleColumnReader
verify(dataStream != null);
int minNonNullValueSize = minNonNullValueSize(nonNullCount);
if (nonNullValueTemp.length < minNonNullValueSize) {
nonNullValueTemp = new long[minNonNullValueSize];
nonNullValueTemp = new double[minNonNullValueSize];
systemMemoryContext.setBytes(sizeOf(nonNullValueTemp));
}
dataStream.next(nonNullValueTemp, nonNullCount);
long[] result = unpackLongNulls(nonNullValueTemp, isNull);
DoubleVec result = unpackDoubleNulls(nonNullValueTemp, isNull);
return new LongArrayBlock(isNull.length, Optional.of(isNull), result);
return new DoubleArrayBlock(isNull.length, Optional.of(isNull), result);
}
private void openRowGroup()
@ -230,12 +231,12 @@ public class DoubleColumnReader
}
@Override
public boolean filterTest(TupleDomainFilter filter, Long value)
public boolean filterTest(TupleDomainFilter filter, Double value)
{
if (value == null) {
return filter.testNull();
}
return filter.testDouble(Double.longBitsToDouble(value));
return filter.testDouble(value);
}
}

View File

@ -28,6 +28,7 @@ import io.prestosql.spi.block.IntArrayBlock;
import io.prestosql.spi.block.RunLengthEncodedBlock;
import io.prestosql.spi.type.RealType;
import io.prestosql.spi.type.Type;
import nova.hetu.omnicache.vector.IntVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
@ -146,9 +147,9 @@ public class FloatColumnReader
throws IOException
{
verify(dataStream != null);
int[] values = new int[nextBatchSize];
dataStream.next(values, nextBatchSize);
return new IntArrayBlock(nextBatchSize, Optional.empty(), values);
IntVec intVec = new IntVec(nextBatchSize);
dataStream.next(intVec, nextBatchSize);
return new IntArrayBlock(nextBatchSize, Optional.empty(), intVec);
}
private Block readNullBlock(boolean[] isNull, int nonNullCount)
@ -163,7 +164,7 @@ public class FloatColumnReader
dataStream.next(nonNullValueTemp, nonNullCount);
int[] result = ReaderUtils.unpackIntNulls(nonNullValueTemp, isNull);
IntVec result = ReaderUtils.unpackIntNulls(nonNullValueTemp, isNull);
return new IntArrayBlock(isNull.length, Optional.of(isNull), result);
}

View File

@ -22,6 +22,7 @@ import io.prestosql.spi.block.IntArrayBlock;
import io.prestosql.spi.block.RunLengthEncodedBlock;
import io.prestosql.spi.type.IntegerType;
import io.prestosql.spi.type.Type;
import nova.hetu.omnicache.vector.IntVec;
import org.openjdk.jol.info.ClassLayout;
import java.io.IOException;
@ -41,6 +42,7 @@ public class IntegerColumnReader
/**
* FIXME: KEN: why do we need to pass in type? isn't it implied already?
*
* @param column
* @param systemMemoryContext
* @throws OrcCorruptionException
@ -108,9 +110,9 @@ public class IntegerColumnReader
throws IOException
{
verify(dataStream != null);
int[] values = new int[nextBatchSize];
dataStream.next(values, nextBatchSize);
return new IntArrayBlock(nextBatchSize, Optional.empty(), values);
IntVec intVec = new IntVec(nextBatchSize);
dataStream.next(intVec, nextBatchSize);
return new IntArrayBlock(nextBatchSize, Optional.empty(), intVec);
}
protected Block readNullBlock(boolean[] isNull, int nonNullCount)
@ -131,7 +133,7 @@ public class IntegerColumnReader
dataStream.next(intNonNullValueTemp, nonNullCount);
int[] result = unpackIntNulls(intNonNullValueTemp, isNull);
IntVec result = unpackIntNulls(intNonNullValueTemp, isNull);
return new IntArrayBlock(nextBatchSize, Optional.of(isNull), result);
}

View File

@ -22,6 +22,7 @@ import io.prestosql.spi.block.LongArrayBlock;
import io.prestosql.spi.block.RunLengthEncodedBlock;
import io.prestosql.spi.type.BigintType;
import io.prestosql.spi.type.Type;
import nova.hetu.omnicache.vector.LongVec;
import org.openjdk.jol.info.ClassLayout;
import java.io.IOException;
@ -30,7 +31,7 @@ import java.util.Optional;
import static com.google.common.base.Verify.verify;
import static io.airlift.slice.SizeOf.sizeOf;
import static io.prestosql.orc.reader.ReaderUtils.minNonNullValueSize;
import static io.prestosql.orc.reader.ReaderUtils.unpackLongNulls;
import static io.prestosql.orc.reader.ReaderUtils.unpackLongNullsVec;
public class LongColumnReader
extends AbstractNumericColumnReader<Long>
@ -107,9 +108,10 @@ public class LongColumnReader
throws IOException
{
verify(dataStream != null);
long[] values = new long[nextBatchSize];
dataStream.next(values, nextBatchSize);
return new LongArrayBlock(nextBatchSize, Optional.empty(), values);
// long[] values = new long[nextBatchSize];
LongVec longVec = new LongVec(nextBatchSize);
dataStream.next(longVec, nextBatchSize);
return new LongArrayBlock(nextBatchSize, Optional.empty(), longVec);
}
private Block readNullBlock(boolean[] isNull, int nonNullCount)
@ -130,7 +132,7 @@ public class LongColumnReader
dataStream.next(longNonNullValueTemp, nonNullCount);
long[] result = unpackLongNulls(longNonNullValueTemp, isNull);
LongVec result = unpackLongNullsVec(longNonNullValueTemp, isNull);
return new LongArrayBlock(nextBatchSize, Optional.of(isNull), result);
}

View File

@ -16,6 +16,9 @@ package io.prestosql.orc.reader;
import io.prestosql.orc.OrcColumn;
import io.prestosql.orc.OrcCorruptionException;
import io.prestosql.spi.type.Type;
import nova.hetu.omnicache.vector.DoubleVec;
import nova.hetu.omnicache.vector.IntVec;
import nova.hetu.omnicache.vector.LongVec;
import java.util.function.Predicate;
@ -73,13 +76,13 @@ final class ReaderUtils
return result;
}
public static int[] unpackIntNulls(int[] values, boolean[] isNull)
public static IntVec unpackIntNulls(int[] values, boolean[] isNull)
{
int[] result = new int[isNull.length];
IntVec result = new IntVec(isNull.length);
int position = 0;
for (int i = 0; i < isNull.length; i++) {
result[i] = values[position];
result.set(i, values[position]);
if (!isNull[i]) {
position++;
}
@ -101,6 +104,34 @@ final class ReaderUtils
return result;
}
public static LongVec unpackLongNullsVec(long[] values, boolean[] isNull)
{
LongVec result = new LongVec(isNull.length);
int position = 0;
for (int i = 0; i < isNull.length; i++) {
result.set(i, values[position]);
if (!isNull[i]) {
position++;
}
}
return result;
}
public static DoubleVec unpackDoubleNulls(double[] values, boolean[] isNull)
{
DoubleVec result = new DoubleVec(isNull.length);
int position = 0;
for (int i = 0; i < isNull.length; i++) {
result.set(i, values[position]);
if (!isNull[i]) {
position++;
}
}
return result;
}
public static long[] unpackInt128Nulls(long[] values, boolean[] isNull)
{
long[] result = new long[isNull.length * 2];

View File

@ -297,4 +297,4 @@ public class SliceDirectColumnReader
{
return INSTANCE_SIZE;
}
}
}

View File

@ -16,6 +16,7 @@ package io.prestosql.orc.stream;
import io.airlift.slice.Slice;
import io.airlift.slice.Slices;
import io.prestosql.orc.checkpoint.DoubleStreamCheckpoint;
import nova.hetu.omnicache.vector.DoubleVec;
import java.io.IOException;
@ -62,9 +63,19 @@ public class DoubleInputStream
return slice.getDouble(0);
}
public void next(long[] values, int items)
public void next(double[] values, int items)
throws IOException
{
input.readFully(Slices.wrappedLongArray(values), 0, items * SIZE_OF_DOUBLE);
input.readFully(Slices.wrappedDoubleArray(values), 0, items * SIZE_OF_DOUBLE);
}
public void next(DoubleVec values, int items)
throws IOException
{
double[] buffer = new double[values.size()];
input.readFully(Slices.wrappedDoubleArray(buffer), 0, items * SIZE_OF_DOUBLE);
for (int i = 0; i < values.size(); i++) {
values.set(i, buffer[i]);
}
}
}

View File

@ -16,6 +16,7 @@ package io.prestosql.orc.stream;
import io.airlift.slice.Slice;
import io.airlift.slice.Slices;
import io.prestosql.orc.checkpoint.FloatStreamCheckpoint;
import nova.hetu.omnicache.vector.IntVec;
import java.io.IOException;
@ -67,4 +68,14 @@ public class FloatInputStream
{
input.readFully(Slices.wrappedIntArray(values), 0, items * SIZE_OF_FLOAT);
}
public void next(IntVec values, int items)
throws IOException
{
int[] buffer = new int[values.size()];
input.readFully(Slices.wrappedIntArray(buffer), 0, items * SIZE_OF_FLOAT);
for (int i = 0; i < values.size(); i++) {
values.set(i, buffer[i]);
}
}
}

View File

@ -14,6 +14,8 @@
package io.prestosql.orc.stream;
import io.prestosql.orc.checkpoint.LongStreamCheckpoint;
import nova.hetu.omnicache.vector.IntVec;
import nova.hetu.omnicache.vector.LongVec;
import java.io.IOException;
@ -26,6 +28,12 @@ public interface LongInputStream
long next()
throws IOException;
void next(LongVec longVec, int items)
throws IOException;
void next(IntVec longVec, int items)
throws IOException;
void next(long[] values, int items)
throws IOException;

View File

@ -16,6 +16,8 @@ package io.prestosql.orc.stream;
import io.prestosql.orc.OrcCorruptionException;
import io.prestosql.orc.checkpoint.LongStreamCheckpoint;
import io.prestosql.orc.checkpoint.LongStreamV1Checkpoint;
import nova.hetu.omnicache.vector.IntVec;
import nova.hetu.omnicache.vector.LongVec;
import java.io.IOException;
@ -122,6 +124,35 @@ public class LongInputStreamV1
}
}
@Override
public void next(LongVec values, int items)
throws IOException
{
int offset = 0;
while (items > 0) {
if (used == numLiterals) {
numLiterals = 0;
used = 0;
readValues();
}
int chunkSize = min(numLiterals - used, items);
if (repeat) {
for (int i = 0; i < chunkSize; i++) {
values.set(offset + i, literals[0] + ((used + i) * delta));
}
}
else {
for (int i = 0; i < chunkSize; i++) {
values.set(offset + i, literals[used + i]);
}
}
used += chunkSize;
offset += chunkSize;
items -= chunkSize;
}
}
@Override
public void next(int[] values, int items)
throws IOException
@ -161,6 +192,45 @@ public class LongInputStreamV1
}
}
@Override
public void next(IntVec values, int items)
throws IOException
{
int offset = 0;
while (items > 0) {
if (used == numLiterals) {
numLiterals = 0;
used = 0;
readValues();
}
int chunkSize = min(numLiterals - used, items);
if (repeat) {
for (int i = 0; i < chunkSize; i++) {
long literal = literals[0] + ((used + i) * delta);
int value = (int) literal;
if (literal != value) {
throw new OrcCorruptionException(input.getOrcDataSourceId(), "Decoded value out of range for a 32bit number");
}
values.set(offset + i, value);
}
}
else {
for (int i = 0; i < chunkSize; i++) {
long literal = literals[used + i];
int value = (int) literal;
if (literal != value) {
throw new OrcCorruptionException(input.getOrcDataSourceId(), "Decoded value out of range for a 32bit number");
}
values.set(offset + i, value);
}
}
used += chunkSize;
offset += chunkSize;
items -= chunkSize;
}
}
@Override
public void next(short[] values, int items)
throws IOException

View File

@ -16,6 +16,8 @@ package io.prestosql.orc.stream;
import io.prestosql.orc.OrcCorruptionException;
import io.prestosql.orc.checkpoint.LongStreamCheckpoint;
import io.prestosql.orc.checkpoint.LongStreamV2Checkpoint;
import nova.hetu.omnicache.vector.IntVec;
import nova.hetu.omnicache.vector.LongVec;
import java.io.IOException;
import java.io.InputStream;
@ -334,6 +336,29 @@ public class LongInputStreamV2
return literals[used++];
}
@Override
public void next(LongVec longVec, int items)
throws IOException
{
int offset = 0;
while (items > 0) {
if (used == numLiterals) {
numLiterals = 0;
used = 0;
readValues();
}
int chunkSize = min(numLiterals - used, items);
for (int i = 0; i < chunkSize; i++) {
longVec.set(offset + i, literals[used + i]);
}
// System.arraycopy(literals, used, values, offset, chunkSize);
used += chunkSize;
offset += chunkSize;
items -= chunkSize;
}
}
@Override
public void next(long[] values, int items)
throws IOException
@ -354,6 +379,33 @@ public class LongInputStreamV2
}
}
@Override
public void next(IntVec values, int items)
throws IOException
{
int offset = 0;
while (items > 0) {
if (used == numLiterals) {
numLiterals = 0;
used = 0;
readValues();
}
int chunkSize = min(numLiterals - used, items);
for (int i = 0; i < chunkSize; i++) {
long literal = literals[used + i];
int value = (int) literal;
if (literal != value) {
throw new OrcCorruptionException(input.getOrcDataSourceId(), "Decoded value out of range for a 32bit number");
}
values.set(offset + i, value);
}
used += chunkSize;
offset += chunkSize;
items -= chunkSize;
}
}
@Override
public void next(int[] values, int items)
throws IOException

View File

@ -1094,7 +1094,7 @@ public class BenchmarkColumnReaders
{
Options options = new OptionsBuilder()
.verbosity(VerboseMode.NORMAL)
.include(".*" + BenchmarkColumnReaders.class.getSimpleName() + ".*")
.include(".*" + BenchmarkColumnReaders.class.getSimpleName() + ".readSliceDirectNoNull")
.build();
new Runner(options).run();

View File

@ -120,5 +120,16 @@
<artifactId>log</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.hetu.core</groupId>
<artifactId>omni-cache</artifactId>
<version>1.2.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -63,6 +63,13 @@ public abstract class AbstractSingleRowBlock<T>
return getRawFieldBlock(position).getInt(rowIndex, offset);
}
@Override
public double getDouble(int position, int offset)
{
checkFieldIndex(position);
return getRawFieldBlock(position).getDouble(rowIndex, offset);
}
@Override
public long getLong(int position, int offset)
{

View File

@ -15,6 +15,7 @@ package io.prestosql.spi.block;
import io.airlift.slice.Slice;
import io.prestosql.spi.util.BloomFilter;
import nova.hetu.omnicache.vector.Vec;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.util.function.BiConsumer;
@ -25,6 +26,16 @@ import static io.prestosql.spi.block.DictionaryId.randomDictionaryId;
public interface Block<T>
{
default Vec getValues()
{
throw new UnsupportedOperationException();
}
default Object setValues()
{
throw new UnsupportedOperationException();
}
/**
* Gets the length of the value at the {@code position}.
* This method must be implemented if @{code getSlice} is implemented.
@ -58,6 +69,14 @@ public interface Block<T>
throw new UnsupportedOperationException(getClass().getName());
}
/**
* Gets a little endian double at {@code offset} in the value at {@code position}.
*/
default double getDouble(int position, int offset)
{
throw new UnsupportedOperationException(getClass().getName());
}
/**
* Gets a little endian long at {@code offset} in the value at {@code position}.
* <p>

View File

@ -42,6 +42,14 @@ public interface BlockBuilder<T>
throw new UnsupportedOperationException(getClass().getName());
}
/**
* Write a double to the current entry;
*/
default BlockBuilder writeDouble(double value)
{
throw new UnsupportedOperationException(getClass().getName());
}
/**
* Write a long to the current entry;
*/

View File

@ -0,0 +1,284 @@
/*
* Copyright (C) 2018-2020. Huawei Technologies Co., Ltd. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.spi.block;
import nova.hetu.omnicache.vector.DoubleVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.function.BiConsumer;
import static io.airlift.slice.SizeOf.sizeOf;
import static io.prestosql.spi.block.BlockUtil.checkArrayRange;
import static io.prestosql.spi.block.BlockUtil.checkValidRegion;
import static io.prestosql.spi.block.BlockUtil.compactArray;
import static io.prestosql.spi.block.BlockUtil.countUsedPositions;
public class DoubleArrayBlock
implements Block<Double>
{
private static final int INSTANCE_SIZE = ClassLayout.parseClass(DoubleArrayBlock.class).instanceSize();
private final int arrayOffset;
private final int positionCount;
@Nullable
private final boolean[] valueIsNull;
private final DoubleVec values;
private final long sizeInBytes;
private final long retainedSizeInBytes;
public DoubleArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, double[] values)
{
this(0, positionCount, valueIsNull.orElse(null), values);
}
public DoubleArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, DoubleVec values)
{
this(0, positionCount, valueIsNull.orElse(null), values);
}
DoubleArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, double[] values)
{
if (arrayOffset < 0) {
throw new IllegalArgumentException("arrayOffset is negative");
}
this.arrayOffset = arrayOffset;
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
if (values.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = new DoubleVec(values.length);
for (int i = 0; i < values.length; i++) {
this.values.set(i, values[i]);
}
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = (Double.BYTES + Byte.BYTES) * (long) positionCount;
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
}
DoubleArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, DoubleVec values)
{
if (arrayOffset < 0) {
throw new IllegalArgumentException("arrayOffset is negative");
}
this.arrayOffset = arrayOffset;
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
if (values.size() - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = values;
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = (Double.BYTES + Byte.BYTES) * (long) positionCount;
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + values.capacity();
}
@Override
public DoubleVec getValues(){
return values;
}
@Override
public long getSizeInBytes()
{
return sizeInBytes;
}
@Override
public long getRegionSizeInBytes(int position, int length)
{
return (Double.BYTES + Byte.BYTES) * (long) length;
}
@Override
public long getPositionsSizeInBytes(boolean[] positions)
{
return (Double.BYTES + Byte.BYTES) * (long) countUsedPositions(positions);
}
@Override
public long getRetainedSizeInBytes()
{
return retainedSizeInBytes;
}
@Override
public long getEstimatedDataSizeForStats(int position)
{
return isNull(position) ? 0 : Double.BYTES;
}
@Override
public void retainedBytesForEachPart(BiConsumer<Object, Long> consumer)
{
// TODO: try to avoid copy here
double[] valuesArray = new double[values.size()];
for (int i = 0; i < values.size(); i++) {
valuesArray[i] = values.get(i);
}
consumer.accept(valuesArray, sizeOf(valuesArray));
if (valueIsNull != null) {
consumer.accept(valueIsNull, sizeOf(valueIsNull));
}
consumer.accept(this, (long) INSTANCE_SIZE);
}
@Override
public int getPositionCount()
{
return positionCount;
}
@Override
public double getDouble(int position, int offset)
{
checkReadablePosition(position);
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
return values.get(position + arrayOffset);
}
@Override
public boolean mayHaveNull()
{
return valueIsNull != null;
}
@Override
public boolean isNull(int position)
{
checkReadablePosition(position);
return valueIsNull != null && valueIsNull[position + arrayOffset];
}
@Override
public void writePositionTo(int position, BlockBuilder blockBuilder)
{
checkReadablePosition(position);
blockBuilder.writeDouble(values.get(position + arrayOffset));
blockBuilder.closeEntry();
}
@Override
public Block getSingleValueBlock(int position)
{
checkReadablePosition(position);
return new DoubleArrayBlock(
0,
1,
isNull(position) ? new boolean[] {true} : null,
new double[] {values.get(position + arrayOffset)});
}
@Override
public Block copyPositions(int[] positions, int offset, int length)
{
checkArrayRange(positions, offset, length);
boolean[] newValueIsNull = null;
if (valueIsNull != null) {
newValueIsNull = new boolean[length];
}
double[] newValues = new double[length];
for (int i = 0; i < length; i++) {
int position = positions[offset + i];
checkReadablePosition(position);
if (valueIsNull != null) {
newValueIsNull[i] = valueIsNull[position + arrayOffset];
}
newValues[i] = values.get(position + arrayOffset);
}
return new DoubleArrayBlock(0, length, newValueIsNull, newValues);
}
@Override
public Block<Double> getRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
return new DoubleArrayBlock(positionOffset + arrayOffset, length, valueIsNull, values);
}
@Override
public Block<Double> copyRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
positionOffset += arrayOffset;
DoubleVec newValues = new DoubleVec(length);
for (int i = 0; i < length; i++) {
newValues.set(i, this.values.get(positionOffset + i));
}
boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, positionOffset, length);
if (newValueIsNull == valueIsNull && newValues == values) {
return this;
}
return new DoubleArrayBlock(0, length, newValueIsNull, newValues);
}
@Override
public String getEncodingName()
{
return DoubleArrayBlockEncoding.NAME;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder("DoubleArrayBlock{");
sb.append("positionCount=").append(getPositionCount());
sb.append('}');
return sb.toString();
}
private void checkReadablePosition(int position)
{
if (position < 0 || position >= getPositionCount()) {
throw new IllegalArgumentException("position is not valid");
}
}
@Override
public Double get(int position)
{
if (valueIsNull != null && valueIsNull[position + arrayOffset]) {
return null;
}
return values.get(position + arrayOffset);
}
}

View File

@ -0,0 +1,297 @@
/*
* Copyright (C) 2018-2020. Huawei Technologies Co., Ltd. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.spi.block;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.function.BiConsumer;
import static io.airlift.slice.SizeOf.sizeOf;
import static io.prestosql.spi.block.BlockUtil.calculateBlockResetSize;
import static io.prestosql.spi.block.BlockUtil.checkArrayRange;
import static io.prestosql.spi.block.BlockUtil.checkValidRegion;
import static io.prestosql.spi.block.BlockUtil.countUsedPositions;
import static java.lang.Math.max;
public class DoubleArrayBlockBuilder
implements BlockBuilder<Double>
{
private static final int INSTANCE_SIZE = ClassLayout.parseClass(DoubleArrayBlockBuilder.class).instanceSize();
private static final Block NULL_VALUE_BLOCK = new DoubleArrayBlock(0, 1, new boolean[] {true}, new double[1]);
@Nullable
private BlockBuilderStatus blockBuilderStatus;
private boolean initialized;
private int initialEntryCount;
private int positionCount;
private boolean hasNullValue;
private boolean hasNonNullValue;
// it is assumed that these arrays are the same length
private boolean[] valueIsNull = new boolean[0];
private double[] values = new double[0];
private long retainedSizeInBytes;
public DoubleArrayBlockBuilder(@Nullable BlockBuilderStatus blockBuilderStatus, int expectedEntries)
{
this.blockBuilderStatus = blockBuilderStatus;
this.initialEntryCount = max(expectedEntries, 1);
updateDataSize();
}
@Override
public BlockBuilder writeDouble(double value)
{
if (values.length <= positionCount) {
growCapacity();
}
values[positionCount] = value;
hasNonNullValue = true;
positionCount++;
if (blockBuilderStatus != null) {
blockBuilderStatus.addBytes(Byte.BYTES + Double.BYTES);
}
return this;
}
@Override
public BlockBuilder closeEntry()
{
return this;
}
@Override
public BlockBuilder appendNull()
{
if (values.length <= positionCount) {
growCapacity();
}
valueIsNull[positionCount] = true;
hasNullValue = true;
positionCount++;
if (blockBuilderStatus != null) {
blockBuilderStatus.addBytes(Byte.BYTES + Double.BYTES);
}
return this;
}
@Override
public Block build()
{
if (!hasNonNullValue) {
return new RunLengthEncodedBlock(NULL_VALUE_BLOCK, positionCount);
}
return new DoubleArrayBlock(0, positionCount, hasNullValue ? valueIsNull : null, values);
}
@Override
public BlockBuilder newBlockBuilderLike(BlockBuilderStatus blockBuilderStatus)
{
return new DoubleArrayBlockBuilder(blockBuilderStatus, calculateBlockResetSize(positionCount));
}
private void growCapacity()
{
int newSize;
if (initialized) {
newSize = BlockUtil.calculateNewArraySize(values.length);
}
else {
newSize = initialEntryCount;
initialized = true;
}
valueIsNull = Arrays.copyOf(valueIsNull, newSize);
values = Arrays.copyOf(values, newSize);
updateDataSize();
}
private void updateDataSize()
{
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
if (blockBuilderStatus != null) {
retainedSizeInBytes += BlockBuilderStatus.INSTANCE_SIZE;
}
}
@Override
public long getSizeInBytes()
{
return (Double.BYTES + Byte.BYTES) * (long) positionCount;
}
@Override
public long getRegionSizeInBytes(int position, int length)
{
return (Double.BYTES + Byte.BYTES) * (long) length;
}
@Override
public long getPositionsSizeInBytes(boolean[] positions)
{
return (Double.BYTES + Byte.BYTES) * (long) countUsedPositions(positions);
}
@Override
public long getRetainedSizeInBytes()
{
return retainedSizeInBytes;
}
@Override
public long getEstimatedDataSizeForStats(int position)
{
return isNull(position) ? 0 : Double.BYTES;
}
@Override
public void retainedBytesForEachPart(BiConsumer<Object, Long> consumer)
{
consumer.accept(values, sizeOf(values));
consumer.accept(valueIsNull, sizeOf(valueIsNull));
consumer.accept(this, (long) INSTANCE_SIZE);
}
@Override
public int getPositionCount()
{
return positionCount;
}
@Override
public double getDouble(int position, int offset)
{
checkReadablePosition(position);
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
return values[position];
}
@Override
public boolean mayHaveNull()
{
return hasNullValue;
}
@Override
public boolean isNull(int position)
{
checkReadablePosition(position);
return valueIsNull[position];
}
@Override
public void writePositionTo(int position, BlockBuilder blockBuilder)
{
checkReadablePosition(position);
blockBuilder.writeDouble(values[position]);
blockBuilder.closeEntry();
}
@Override
public Block getSingleValueBlock(int position)
{
checkReadablePosition(position);
return new DoubleArrayBlock(
0,
1,
valueIsNull[position] ? new boolean[] {true} : null,
new double[] {values[position]});
}
@Override
public Block copyPositions(int[] positions, int offset, int length)
{
checkArrayRange(positions, offset, length);
if (!hasNonNullValue) {
return new RunLengthEncodedBlock(NULL_VALUE_BLOCK, length);
}
boolean[] newValueIsNull = null;
if (hasNullValue) {
newValueIsNull = new boolean[length];
}
double[] newValues = new double[length];
for (int i = 0; i < length; i++) {
int position = positions[offset + i];
checkReadablePosition(position);
if (hasNullValue) {
newValueIsNull[i] = valueIsNull[position];
}
newValues[i] = values[position];
}
return new DoubleArrayBlock(0, length, newValueIsNull, newValues);
}
@Override
public Block getRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
if (!hasNonNullValue) {
return new RunLengthEncodedBlock(NULL_VALUE_BLOCK, length);
}
return new DoubleArrayBlock(positionOffset, length, hasNullValue ? valueIsNull : null, values);
}
@Override
public Block copyRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
if (!hasNonNullValue) {
return new RunLengthEncodedBlock(NULL_VALUE_BLOCK, length);
}
boolean[] newValueIsNull = null;
if (hasNullValue) {
newValueIsNull = Arrays.copyOfRange(valueIsNull, positionOffset, positionOffset + length);
}
double[] newValues = Arrays.copyOfRange(values, positionOffset, positionOffset + length);
return new DoubleArrayBlock(0, length, newValueIsNull, newValues);
}
@Override
public String getEncodingName()
{
return DoubleArrayBlockEncoding.NAME;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder("DoubleArrayBlockBuilder{");
sb.append("positionCount=").append(getPositionCount());
sb.append('}');
return sb.toString();
}
private void checkReadablePosition(int position)
{
if (position < 0 || position >= getPositionCount()) {
throw new IllegalArgumentException("position is not valid");
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2018-2020. Huawei Technologies Co., Ltd. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.prestosql.spi.block;
import io.airlift.slice.SliceInput;
import io.airlift.slice.SliceOutput;
import static io.prestosql.spi.block.EncoderUtil.decodeNullBits;
import static io.prestosql.spi.block.EncoderUtil.encodeNullsAsBits;
public class DoubleArrayBlockEncoding
implements BlockEncoding
{
public static final String NAME = "DOUBLE_ARRAY";
@Override
public String getName()
{
return NAME;
}
@Override
public void writeBlock(BlockEncodingSerde blockEncodingSerde, SliceOutput sliceOutput, Block block)
{
int positionCount = block.getPositionCount();
sliceOutput.appendInt(positionCount);
encodeNullsAsBits(sliceOutput, block);
for (int position = 0; position < positionCount; position++) {
if (!block.isNull(position)) {
sliceOutput.writeDouble(block.getDouble(position, 0));
}
}
}
@Override
public Block readBlock(BlockEncodingSerde blockEncodingSerde, SliceInput sliceInput)
{
int positionCount = sliceInput.readInt();
boolean[] valueIsNull = decodeNullBits(sliceInput, positionCount).orElse(null);
double[] values = new double[positionCount];
for (int position = 0; position < positionCount; position++) {
if (valueIsNull == null || !valueIsNull[position]) {
values[position] = sliceInput.readDouble();
}
}
return new DoubleArrayBlock(0, positionCount, valueIsNull, values);
}
}

View File

@ -16,6 +16,7 @@ package io.prestosql.spi.block;
import io.airlift.slice.Slice;
import io.airlift.slice.Slices;
import io.prestosql.spi.util.BloomFilter;
import nova.hetu.omnicache.vector.LongVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
@ -40,7 +41,7 @@ public class Int128ArrayBlock
private final int positionCount;
@Nullable
private final boolean[] valueIsNull;
private final long[] values;
private final LongVec values;
private final long sizeInBytes;
private final long retainedSizeInBytes;
@ -50,6 +51,11 @@ public class Int128ArrayBlock
this(0, positionCount, valueIsNull.orElse(null), values);
}
public Int128ArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, LongVec values)
{
this(0, positionCount, valueIsNull.orElse(null), values);
}
Int128ArrayBlock(int positionOffset, int positionCount, boolean[] valueIsNull, long[] values)
{
if (positionOffset < 0) {
@ -64,6 +70,34 @@ public class Int128ArrayBlock
if (values.length - (positionOffset * 2) < positionCount * 2) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = new LongVec(values.length);
for (int i = 0; i < values.length; i++) {
this.values.set(i, values[i]);
}
if (valueIsNull != null && valueIsNull.length - positionOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = (INT128_BYTES + Byte.BYTES) * (long) positionCount;
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + this.values.capacity();
}
Int128ArrayBlock(int positionOffset, int positionCount, boolean[] valueIsNull, LongVec values)
{
if (positionOffset < 0) {
throw new IllegalArgumentException("positionOffset is negative");
}
this.positionOffset = positionOffset;
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
if (values.size() - (positionOffset * 2) < positionCount * 2) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = values;
if (valueIsNull != null && valueIsNull.length - positionOffset < positionCount) {
@ -72,7 +106,7 @@ public class Int128ArrayBlock
this.valueIsNull = valueIsNull;
sizeInBytes = (INT128_BYTES + Byte.BYTES) * (long) positionCount;
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + this.values.capacity();
}
@Override
@ -108,7 +142,12 @@ public class Int128ArrayBlock
@Override
public void retainedBytesForEachPart(BiConsumer<Object, Long> consumer)
{
consumer.accept(values, sizeOf(values));
// TODO: try to avoid copy here
long[] valuesArray = new long[values.size()];
for (int i = 0; i < values.size(); i++) {
valuesArray[i] = values.get(i);
}
consumer.accept(valuesArray, sizeOf(valuesArray));
if (valueIsNull != null) {
consumer.accept(valueIsNull, sizeOf(valueIsNull));
}
@ -126,10 +165,10 @@ public class Int128ArrayBlock
{
checkReadablePosition(position);
if (offset == 0) {
return values[(position + positionOffset) * 2];
return values.get((position + positionOffset) * 2);
}
if (offset == 8) {
return values[((position + positionOffset) * 2) + 1];
return values.get(((position + positionOffset) * 2) + 1);
}
throw new IllegalArgumentException("offset must be 0 or 8");
}
@ -151,8 +190,8 @@ public class Int128ArrayBlock
public void writePositionTo(int position, BlockBuilder blockBuilder)
{
checkReadablePosition(position);
blockBuilder.writeLong(values[(position + positionOffset) * 2]);
blockBuilder.writeLong(values[((position + positionOffset) * 2) + 1]);
blockBuilder.writeLong(values.get((position + positionOffset) * 2));
blockBuilder.writeLong(values.get(((position + positionOffset) * 2) + 1));
blockBuilder.closeEntry();
}
@ -165,8 +204,8 @@ public class Int128ArrayBlock
1,
isNull(position) ? new boolean[] {true} : null,
new long[] {
values[(position + positionOffset) * 2],
values[((position + positionOffset) * 2) + 1]});
values.get((position + positionOffset) * 2),
values.get(((position + positionOffset) * 2) + 1)});
}
@Override
@ -185,8 +224,8 @@ public class Int128ArrayBlock
if (valueIsNull != null) {
newValueIsNull[i] = valueIsNull[position + positionOffset];
}
newValues[i * 2] = values[(position + positionOffset) * 2];
newValues[(i * 2) + 1] = values[((position + positionOffset) * 2) + 1];
newValues[i * 2] = values.get((position + positionOffset) * 2);
newValues[(i * 2) + 1] = values.get(((position + positionOffset) * 2) + 1);
}
return new Int128ArrayBlock(0, length, newValueIsNull, newValues);
}
@ -203,10 +242,13 @@ public class Int128ArrayBlock
public Block copyRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
positionOffset += this.positionOffset;
LongVec newValues = new LongVec(length * 2);
for (int i = 0; i < length * 2; i++) {
newValues.set(i, this.values.get(positionOffset * 2 + i));
}
boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, positionOffset, length);
long[] newValues = compactArray(values, positionOffset * 2, length * 2);
if (newValueIsNull == valueIsNull && newValues == values) {
return this;
@ -239,8 +281,8 @@ public class Int128ArrayBlock
@Override
public boolean[] filter(BloomFilter filter, boolean[] validPositions)
{
for (int i = 0; i < values.length / 2; i++) {
Slice value = Slices.wrappedLongArray(values[i * 2], values[i * 2 + 1]);
for (int i = 0; i < values.size() / 2; i++) {
Slice value = Slices.wrappedLongArray(values.get(i * 2), values.get(i * 2 + 1));
validPositions[i] = validPositions[i] && filter.test(value);
}
return validPositions;
@ -258,8 +300,8 @@ public class Int128ArrayBlock
}
}
else {
val[0] = values[(positions[i] + positionOffset) * 2];
val[1] = values[((positions[i] + positionOffset) * 2) + 1];
val[0] = values.get((positions[i] + positionOffset) * 2);
val[1] = values.get(((positions[i] + positionOffset) * 2) + 1);
if (test.apply(val)) {
matchedPositions[matchCount++] = positions[i];
}
@ -276,8 +318,8 @@ public class Int128ArrayBlock
if (valueIsNull != null && valueIsNull[position + positionOffset]) {
return null;
}
val[0] = values[(position + positionOffset) * 2];
val[1] = values[((position + positionOffset) * 2) + 1];
val[0] = values.get((position + positionOffset) * 2);
val[1] = values.get(((position + positionOffset) * 2) + 1);
return val;
}

View File

@ -14,6 +14,7 @@
package io.prestosql.spi.block;
import io.prestosql.spi.util.BloomFilter;
import nova.hetu.omnicache.vector.IntVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
@ -37,7 +38,7 @@ public class IntArrayBlock
private final int positionCount;
@Nullable
private final boolean[] valueIsNull;
private final int[] values;
private final IntVec values;
private final long sizeInBytes;
private final long retainedSizeInBytes;
@ -47,6 +48,11 @@ public class IntArrayBlock
this(0, positionCount, valueIsNull.orElse(null), values);
}
public IntArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, IntVec values)
{
this(0, positionCount, valueIsNull.orElse(null), values);
}
IntArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, int[] values)
{
if (arrayOffset < 0) {
@ -61,7 +67,10 @@ public class IntArrayBlock
if (values.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = values;
this.values = new IntVec(values.length);
for (int i = 0; i < values.length; i++) {
this.values.set(i, values[i]);
}
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
@ -72,6 +81,36 @@ public class IntArrayBlock
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
}
IntArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, IntVec values)
{
if (arrayOffset < 0) {
throw new IllegalArgumentException("arrayOffset is negative");
}
this.arrayOffset = arrayOffset;
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
if (values.size() - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = values;
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = (Integer.BYTES + Byte.BYTES) * (long) positionCount;
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + values.capacity();
}
@Override
public IntVec getValues(){
return values;
}
@Override
public long getSizeInBytes()
{
@ -105,7 +144,12 @@ public class IntArrayBlock
@Override
public void retainedBytesForEachPart(BiConsumer<Object, Long> consumer)
{
consumer.accept(values, sizeOf(values));
// TODO: try to avoid copy here
int[] valuesArray = new int[values.size()];
for (int i = 0; i < values.size(); i++) {
valuesArray[i] = values.get(i);
}
consumer.accept(valuesArray, sizeOf(valuesArray));
if (valueIsNull != null) {
consumer.accept(valueIsNull, sizeOf(valueIsNull));
}
@ -125,7 +169,7 @@ public class IntArrayBlock
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
return values[position + arrayOffset];
return values.get(position + arrayOffset);
}
@Override
@ -151,7 +195,7 @@ public class IntArrayBlock
public void writePositionTo(int position, BlockBuilder blockBuilder)
{
checkReadablePosition(position);
blockBuilder.writeInt(values[position + arrayOffset]);
blockBuilder.writeInt(values.get(position + arrayOffset));
blockBuilder.closeEntry();
}
@ -163,7 +207,7 @@ public class IntArrayBlock
0,
1,
isNull(position) ? new boolean[] {true} : null,
new int[] {values[position + arrayOffset]});
new int[] {values.get(position + arrayOffset)});
}
@Override
@ -182,7 +226,7 @@ public class IntArrayBlock
if (valueIsNull != null) {
newValueIsNull[i] = valueIsNull[position + arrayOffset];
}
newValues[i] = values[position + arrayOffset];
newValues[i] = values.get(position + arrayOffset);
}
return new IntArrayBlock(0, length, newValueIsNull, newValues);
}
@ -199,10 +243,13 @@ public class IntArrayBlock
public Block copyRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
positionOffset += arrayOffset;
IntVec newValues = new IntVec(length);
for (int i = 0; i < length; i++) {
newValues.set(i, this.values.get(positionOffset + i));
}
boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, positionOffset, length);
int[] newValues = compactArray(values, positionOffset, length);
if (newValueIsNull == valueIsNull && newValues == values) {
return this;
@ -235,8 +282,8 @@ public class IntArrayBlock
@Override
public boolean[] filter(BloomFilter filter, boolean[] validPositions)
{
for (int i = 0; i < values.length; i++) {
validPositions[i] = validPositions[i] && filter.test(values[i]);
for (int i = 0; i < values.size(); i++) {
validPositions[i] = validPositions[i] && filter.test(values.get(i));
}
return validPositions;
}
@ -251,7 +298,7 @@ public class IntArrayBlock
matchedPositions[matchCount++] = positions[i];
}
}
else if (test.apply(values[positions[i] + arrayOffset])) {
else if (test.apply(values.get(positions[i] + arrayOffset))) {
matchedPositions[matchCount++] = positions[i];
}
}
@ -266,6 +313,6 @@ public class IntArrayBlock
return null;
}
return values[position + arrayOffset];
return values.get(position + arrayOffset);
}
}

View File

@ -14,6 +14,7 @@
package io.prestosql.spi.block;
import io.prestosql.spi.util.BloomFilter;
import nova.hetu.omnicache.vector.LongVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
@ -41,7 +42,7 @@ public class LongArrayBlock
private final int positionCount;
@Nullable
private final boolean[] valueIsNull;
private final long[] values; //change to use offheap --> accessible by RDMA
private final LongVec values;
private final long sizeInBytes;
private final long retainedSizeInBytes;
@ -51,6 +52,11 @@ public class LongArrayBlock
this(0, positionCount, valueIsNull.orElse(null), values);
}
public LongArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, LongVec longVec)
{
this(0, positionCount, valueIsNull.orElse(null), longVec);
}
LongArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, long[] values)
{
if (arrayOffset < 0) {
@ -65,7 +71,10 @@ public class LongArrayBlock
if (values.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = values;
this.values = new LongVec(values.length);
for (int idx = 0; idx < values.length; idx++) {
this.values.set(idx, values[idx]);
}
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
@ -76,6 +85,37 @@ public class LongArrayBlock
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
}
public LongArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, LongVec longVec)
{
if (arrayOffset < 0) {
throw new IllegalArgumentException("arrayOffset is negative");
}
this.arrayOffset = arrayOffset;
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
if (longVec.size() - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = longVec;
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("isNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = (Long.BYTES + Byte.BYTES) * (long) positionCount;
retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + values.capacity();
}
@Override
public LongVec getValues()
{
return values;
}
@Override
public long getSizeInBytes()
{
@ -109,7 +149,12 @@ public class LongArrayBlock
@Override
public void retainedBytesForEachPart(BiConsumer<Object, Long> consumer)
{
consumer.accept(values, sizeOf(values));
// TODO: try to avoid copy here
long[] valuesArray = new long[values.size()];
for (int i = 0; i < values.size(); i++) {
valuesArray[i] = values.get(i);
}
consumer.accept(valuesArray, sizeOf(valuesArray));
if (valueIsNull != null) {
consumer.accept(valueIsNull, sizeOf(valueIsNull));
}
@ -129,7 +174,7 @@ public class LongArrayBlock
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
return values[position + arrayOffset];
return values.get(position + arrayOffset);
}
public Long get(int position)
@ -137,7 +182,7 @@ public class LongArrayBlock
if (valueIsNull != null && valueIsNull[position + arrayOffset]) {
return null;
}
return values[position + arrayOffset];
return values.get(position + arrayOffset);
}
@Override
@ -149,41 +194,7 @@ public class LongArrayBlock
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
return toIntExact(values[position + arrayOffset]);
}
@Override
@Deprecated
// TODO: Remove when we fix intermediate types on aggregations.
public short getShort(int position, int offset)
{
checkReadablePosition(position);
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
short value = (short) (values[position + arrayOffset]);
if (value != values[position + arrayOffset]) {
throw new ArithmeticException("short overflow");
}
return value;
}
@Override
@Deprecated
// TODO: Remove when we fix intermediate types on aggregations.
public byte getByte(int position, int offset)
{
checkReadablePosition(position);
if (offset != 0) {
throw new IllegalArgumentException("offset must be zero");
}
byte value = (byte) (values[position + arrayOffset]);
if (value != values[position + arrayOffset]) {
throw new ArithmeticException("byte overflow");
}
return value;
return toIntExact(values.get(position + arrayOffset));
}
@Override
@ -203,7 +214,7 @@ public class LongArrayBlock
public void writePositionTo(int position, BlockBuilder blockBuilder)
{
checkReadablePosition(position);
blockBuilder.writeLong(values[position + arrayOffset]);
blockBuilder.writeLong(values.get(position + arrayOffset));
blockBuilder.closeEntry();
}
@ -215,7 +226,7 @@ public class LongArrayBlock
0,
1,
isNull(position) ? new boolean[] {true} : null,
new long[] {values[position + arrayOffset]});
new long[] {values.get(position + arrayOffset)});
}
@Override
@ -234,7 +245,7 @@ public class LongArrayBlock
if (valueIsNull != null) {
newValueIsNull[i] = valueIsNull[position + arrayOffset];
}
newValues[i] = values[position + arrayOffset];
newValues[i] = values.get(position + arrayOffset);
}
return new LongArrayBlock(0, length, newValueIsNull, newValues);
}
@ -243,7 +254,6 @@ public class LongArrayBlock
public Block getRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
return new LongArrayBlock(positionOffset + arrayOffset, length, valueIsNull, values);
}
@ -251,10 +261,13 @@ public class LongArrayBlock
public Block copyRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
positionOffset += arrayOffset;
LongVec newValues = new LongVec(length);
for (int i = 0; i < length; i++) {
newValues.set(i, this.values.get(positionOffset + i));
}
boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, positionOffset, length);
long[] newValues = compactArray(values, positionOffset, length);
if (newValueIsNull == valueIsNull && newValues == values) {
return this;
@ -287,9 +300,10 @@ public class LongArrayBlock
@Override
public boolean[] filter(BloomFilter filter, boolean[] validPositions)
{
for (int i = arrayOffset; i < positionCount; i++) {
validPositions[i] = validPositions[i] && filter.test(values[i]);
for (int i = 0; i < values.size(); i++) {
validPositions[i] = validPositions[i] && filter.test(values.get(i));
}
return validPositions;
}
@ -303,7 +317,7 @@ public class LongArrayBlock
matchedPositions[matchCount++] = positions[i];
}
}
else if (test.apply(values[positions[i] + arrayOffset])) {
else if (test.apply(values.get(positions[i] + arrayOffset))) {
matchedPositions[matchCount++] = positions[i];
}
}

View File

@ -121,6 +121,14 @@ public class SingleRowBlockWriter<T>
return this;
}
@Override
public BlockBuilder writeDouble(double value)
{
checkFieldIndexToWrite();
fieldBlockBuilders[currentFieldIndexToWrite].writeDouble(value);
return this;
}
@Override
public BlockBuilder writeLong(long value)
{

View File

@ -17,6 +17,7 @@ import io.airlift.slice.Slice;
import io.airlift.slice.SliceOutput;
import io.airlift.slice.Slices;
import io.prestosql.spi.util.BloomFilter;
import nova.hetu.omnicache.vector.VarcharVec;
import org.openjdk.jol.info.ClassLayout;
import javax.annotation.Nullable;
@ -41,11 +42,13 @@ public class VariableWidthBlock
private final int positionCount;
private final Slice slice;
private final int[] offsets;
protected final VarcharVec varcharVec;
protected final boolean isVecMode = true;
@Nullable
private final boolean[] valueIsNull;
protected final boolean[] valueIsNull;
private final long retainedSizeInBytes;
private final long sizeInBytes;
protected final long retainedSizeInBytes;
protected final long sizeInBytes;
public VariableWidthBlock(int positionCount, Slice slice, int[] offsets, Optional<boolean[]> valueIsNull)
{
@ -67,6 +70,18 @@ public class VariableWidthBlock
throw new IllegalArgumentException("slice is null");
}
this.slice = slice;
if (isVecMode) {
byte[] data = slice.getBytes();
this.varcharVec = new VarcharVec(data.length, offsets.length);
this.varcharVec.setData(data);
int[] lengths = new int [offsets.length];
for (int i=0; i< (positionCount +1); i++) {
if (i < offsets.length -1) {
lengths[i] = offsets[i + 1] - offsets[i];
}
}
this.varcharVec.set(offsets, lengths);
}
if (offsets.length - arrayOffset < (positionCount + 1)) {
throw new IllegalArgumentException("offsets length is less than positionCount");
@ -80,6 +95,36 @@ public class VariableWidthBlock
sizeInBytes = offsets[arrayOffset + positionCount] - offsets[arrayOffset] + ((Integer.BYTES + Byte.BYTES) * (long) positionCount);
retainedSizeInBytes = INSTANCE_SIZE + slice.getRetainedSize() + sizeOf(valueIsNull) + sizeOf(offsets);
}
public VariableWidthBlock(VarcharVec varcharVec, int[] offsets, int[] lengths, boolean[] valueIsNull)
{
this.arrayOffset = 0;
this.positionCount = 0;
if (varcharVec == null) {
throw new IllegalArgumentException("varcharVec is null");
}
this.varcharVec = varcharVec;
for (int i=0; i < offsets.length; i++) {
this.varcharVec.set(i, offsets[i], lengths[i]);
}
this.slice = null;
if (offsets.length - arrayOffset < (positionCount + 1)) {
throw new IllegalArgumentException("offsets length is less than positionCount");
}
this.offsets = offsets;
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("valueIsNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = varcharVec.capacity();
retainedSizeInBytes = varcharVec.capacity();
}
@Override
@ -91,6 +136,7 @@ public class VariableWidthBlock
@Override
public int getSliceLength(int position)
{
// System.out.println("GetSlice Length::" + position);
checkReadablePosition(position);
return getPositionOffset(position + 1) - getPositionOffset(position);
}
@ -128,6 +174,7 @@ public class VariableWidthBlock
@Override
public long getPositionsSizeInBytes(boolean[] positions)
{
System.out.println("Get position size in bytes:::");
long sizeInBytes = 0;
int usedPositionCount = 0;
for (int i = 0; i < positions.length; ++i) {
@ -160,7 +207,9 @@ public class VariableWidthBlock
public Block copyPositions(int[] positions, int offset, int length)
{
checkArrayRange(positions, offset, length);
if(isVecMode) {
return vecCopyPositions(positions, offset, length);
}
int finalLength = 0;
for (int i = offset; i < offset + length; i++) {
finalLength += getSliceLength(positions[i]);
@ -185,9 +234,45 @@ public class VariableWidthBlock
return new VariableWidthBlock(0, length, newSlice.slice(), newOffsets, newValueIsNull);
}
private Block vecCopyPositions(int[] positions, int offset, int length) {
int finalLength = 0;
for (int i = 0; i < positions.length; i++) {
finalLength += this.varcharVec.getLength(positions[i]);
}
VarcharVec newVec = new VarcharVec(finalLength, length);
int[] offsets = new int[positions.length];
int[] lengths = new int[positions.length];
int newOffset = 0;
boolean[] newValueIsNull = null;
if (valueIsNull != null) {
newValueIsNull = new boolean[length];
}
for (int i = 0; i < length; i++) {
int position = positions[i];
if (!isEntryNull(position)) {
byte[] data = this.varcharVec.getDataAtOffset(position);
offsets[i] = newOffset;
lengths[i] = data.length;
newVec.setData(newOffset, data);
newOffset = newOffset + data.length;
}
else if (newValueIsNull != null) {
newValueIsNull[i] = true;
}
}
newVec.set(offsets, lengths);
return new VariableWidthBlock(newVec, offsets, lengths, newValueIsNull);
}
@Override
protected Slice getRawSlice(int position)
{
if (isVecMode) {
return Slices.wrappedBuffer(varcharVec.getData(0, varcharVec.capacity()));
}
return slice;
}
@ -196,13 +281,27 @@ public class VariableWidthBlock
{
checkValidRegion(getPositionCount(), positionOffset, length);
if (isVecMode) {
return getRegionVec(positionOffset, length);
}
return new VariableWidthBlock(positionOffset + arrayOffset, length, slice, offsets, valueIsNull);
}
private Block getRegionVec(int positionOffset, int length)
{
VarcharVec newVec = (VarcharVec) this.varcharVec.slice(positionOffset, positionOffset + length);
return new VariableWidthBlock(newVec, newVec.getOffsets(), newVec.getLengths(), valueIsNull);
}
@Override
public Block copyRegion(int positionOffset, int length)
{
checkValidRegion(getPositionCount(), positionOffset, length);
if(isVecMode) {
return copyRegionVec(positionOffset, length);
}
positionOffset += arrayOffset;
int[] newOffsets = compactOffsets(offsets, positionOffset, length);
@ -215,6 +314,12 @@ public class VariableWidthBlock
return new VariableWidthBlock(0, length, newSlice, newOffsets, newValueIsNull);
}
public Block copyRegionVec(int positionOffset, int length)
{
VarcharVec newVec = (VarcharVec) this.varcharVec.slice(positionOffset, positionOffset + length);
return new VariableWidthBlock(newVec, newVec.getOffsets(), newVec.getLengths(), valueIsNull);
}
@Override
public String toString()
{
@ -262,6 +367,10 @@ public class VariableWidthBlock
if (valueIsNull != null && valueIsNull[position + arrayOffset]) {
return null;
}
if (isVecMode) {
System.out.println("Reading data from vector::::");
return varcharVec.getData(position);
}
return slice.slice(offsets[position + arrayOffset], offsets[position + arrayOffset + 1] - offsets[position + arrayOffset]).getBytes();
}
}

View File

@ -16,7 +16,7 @@ package io.prestosql.spi.type;
import io.prestosql.spi.block.Block;
import io.prestosql.spi.block.BlockBuilder;
import io.prestosql.spi.block.BlockBuilderStatus;
import io.prestosql.spi.block.LongArrayBlockBuilder;
import io.prestosql.spi.block.DoubleArrayBlockBuilder;
import io.prestosql.spi.block.PageBuilderStatus;
import io.prestosql.spi.connector.ConnectorSession;
@ -24,7 +24,6 @@ import java.util.Optional;
import static io.prestosql.spi.type.TypeSignature.parseTypeSignature;
import static java.lang.Double.doubleToLongBits;
import static java.lang.Double.longBitsToDouble;
public final class DoubleType
extends AbstractType
@ -61,14 +60,14 @@ public final class DoubleType
if (block.isNull(position)) {
return null;
}
return longBitsToDouble(block.getLong(position, 0));
return block.getDouble(position, 0);
}
@Override
public boolean equalTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition)
{
double leftValue = longBitsToDouble(leftBlock.getLong(leftPosition, 0));
double rightValue = longBitsToDouble(rightBlock.getLong(rightPosition, 0));
double leftValue = leftBlock.getDouble(leftPosition, 0);
double rightValue = rightBlock.getDouble(rightPosition, 0);
// direct equality is correct here
// noinspection FloatingPointEquality
@ -79,14 +78,14 @@ public final class DoubleType
public long hash(Block block, int position)
{
// convert to canonical NaN if necessary
return AbstractLongType.hash(doubleToLongBits(longBitsToDouble(block.getLong(position, 0))));
return AbstractLongType.hash(doubleToLongBits(block.getDouble(position, 0)));
}
@Override
public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition)
{
double leftValue = longBitsToDouble(leftBlock.getLong(leftPosition, 0));
double rightValue = longBitsToDouble(rightBlock.getLong(rightPosition, 0));
double leftValue = leftBlock.getDouble(leftPosition, 0);
double rightValue = rightBlock.getDouble(rightPosition, 0);
return Double.compare(leftValue, rightValue);
}
@ -97,20 +96,20 @@ public final class DoubleType
blockBuilder.appendNull();
}
else {
blockBuilder.writeLong(block.getLong(position, 0)).closeEntry();
blockBuilder.writeDouble(block.getDouble(position, 0)).closeEntry();
}
}
@Override
public double getDouble(Block block, int position)
{
return longBitsToDouble(block.getLong(position, 0));
return block.getDouble(position, 0);
}
@Override
public void writeDouble(BlockBuilder blockBuilder, double value)
{
blockBuilder.writeLong(doubleToLongBits(value)).closeEntry();
blockBuilder.writeDouble(value).closeEntry();
}
@Override
@ -123,7 +122,7 @@ public final class DoubleType
else {
maxBlockSizeInBytes = blockBuilderStatus.getMaxPageSizeInBytes();
}
return new LongArrayBlockBuilder(
return new DoubleArrayBlockBuilder(
blockBuilderStatus,
Math.min(expectedEntries, maxBlockSizeInBytes / Double.BYTES));
}
@ -137,7 +136,7 @@ public final class DoubleType
@Override
public final BlockBuilder createFixedSizeBlockBuilder(int positionCount)
{
return new LongArrayBlockBuilder(null, positionCount);
return new DoubleArrayBlockBuilder(null, positionCount);
}
@Override

View File

@ -35,6 +35,7 @@ public final class TestingBlockEncodingSerde
addBlockEncoding(new ByteArrayBlockEncoding());
addBlockEncoding(new ShortArrayBlockEncoding());
addBlockEncoding(new IntArrayBlockEncoding());
addBlockEncoding(new DoubleArrayBlockEncoding());
addBlockEncoding(new LongArrayBlockEncoding());
addBlockEncoding(new Int128ArrayBlockEncoding());
addBlockEncoding(new DictionaryBlockEncoding());