-
Notifications
You must be signed in to change notification settings - Fork 15
Optimize some cell and value extraction read paths #6073
Changes from 12 commits
bcd8fce
6192110
68260ef
e02d713
cbb123e
08e372b
c335fc1
fc5046d
eff7daa
60cfb11
76e8651
80f9d98
a324cae
0f3ad73
28e9966
1aa92eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* (c) Copyright 2022 Palantir Technologies Inc. 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 com.palantir.atlasdb.keyvalue.api; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
import com.palantir.logsafe.exceptions.SafeIllegalArgumentException; | ||
import com.palantir.logsafe.exceptions.SafeNullPointerException; | ||
import java.nio.charset.StandardCharsets; | ||
import org.junit.Test; | ||
|
||
public final class CellTest { | ||
|
||
@Test | ||
public void create() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can we prefix |
||
Cell cell = Cell.create(bytes("row"), bytes("col")); | ||
assertThat(cell.getRowName()).isEqualTo(bytes("row")); | ||
assertThat(cell.getColumnName()).isEqualTo(bytes("col")); | ||
assertThatThrownBy(() -> Cell.create(null, bytes("col"))).isInstanceOf(SafeNullPointerException.class); | ||
assertThatThrownBy(() -> Cell.create(bytes("row"), null)).isInstanceOf(SafeNullPointerException.class); | ||
assertThatThrownBy(() -> Cell.create(bytes(""), bytes(""))).isInstanceOf(SafeIllegalArgumentException.class); | ||
assertThatThrownBy(() -> Cell.create(bytes("row"), bytes(""))).isInstanceOf(SafeIllegalArgumentException.class); | ||
assertThatThrownBy(() -> Cell.create(bytes(""), bytes("col"))).isInstanceOf(SafeIllegalArgumentException.class); | ||
assertThatThrownBy(() -> Cell.create(bytes("row"), bytes("x".repeat(Cell.MAX_NAME_LENGTH + 1)))) | ||
.isInstanceOf(SafeIllegalArgumentException.class); | ||
assertThatThrownBy(() -> Cell.create(bytes("x".repeat(Cell.MAX_NAME_LENGTH + 1)), bytes("col"))) | ||
.isInstanceOf(SafeIllegalArgumentException.class); | ||
} | ||
|
||
@Test | ||
@SuppressWarnings("ConstantConditions") // explicitly testing conditions | ||
public void isNameValid() { | ||
assertThat(Cell.isNameValid(bytes("row"))).isTrue(); | ||
assertThat(Cell.isNameValid(null)).isFalse(); | ||
assertThat(Cell.isNameValid(new byte[0])).isFalse(); | ||
assertThat(Cell.isNameValid(bytes("x"))).isTrue(); | ||
assertThat(Cell.isNameValid(bytes("x".repeat(Cell.MAX_NAME_LENGTH + 1)))) | ||
.isFalse(); | ||
} | ||
|
||
@Test | ||
public void compareTo() { | ||
assertThat(Cell.create(bytes("row"), bytes("col"))) | ||
.isEqualByComparingTo(Cell.create(bytes("row"), bytes("col"))); | ||
assertThat(Cell.create(bytes("row"), bytes("col"))) | ||
.isNotEqualByComparingTo(Cell.create(bytes("row2"), bytes("col"))); | ||
assertThat(Cell.create(bytes("row"), bytes("col"))) | ||
.isNotEqualByComparingTo(Cell.create(bytes("row2"), bytes("col2"))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're missing the case where row is the same and column is different |
||
assertThat(Cell.create(bytes("row1"), bytes("col"))).isLessThan(Cell.create(bytes("row2"), bytes("col"))); | ||
assertThat(Cell.create(bytes("row1"), bytes("col"))).isGreaterThan(Cell.create(bytes("row0"), bytes("col"))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the |
||
} | ||
|
||
@Test | ||
public void testEquals() { | ||
assertThat(Cell.create(bytes("row"), bytes("col"))).isEqualTo(Cell.create(bytes("row"), bytes("col"))); | ||
assertThat(Cell.create(bytes("row"), bytes("col"))).isNotEqualTo(Cell.create(bytes("col"), bytes("row"))); | ||
} | ||
|
||
@Test | ||
public void testHashCode() { | ||
assertThat(Cell.create(bytes("row"), bytes("col")).hashCode()).isNotZero(); | ||
assertThat(Cell.create(bytes("row"), bytes("col"))) | ||
.describedAs("Cell unfortunately has a non-ideal hashCode where swapped " | ||
+ "row and column values lead to the same hashCode and cannot be changed due " | ||
+ "to backward compatibility. See goodHash") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
.hasSameHashCodeAs(Cell.create(bytes("col"), bytes("row"))); | ||
} | ||
|
||
private static byte[] bytes(String value) { | ||
return value.getBytes(StandardCharsets.UTF_8); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: newline There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. spotless is failing on this |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,7 +110,8 @@ void loadWithTs( | |
} | ||
int totalPartitions = hostsAndCells.keySet().size(); | ||
|
||
if (log.isTraceEnabled()) { | ||
final boolean isTraceEnabled = log.isTraceEnabled(); | ||
if (isTraceEnabled) { | ||
log.trace( | ||
"Loading {} cells from {} {}starting at timestamp {}, partitioned across {} nodes.", | ||
SafeArg.of("cells", cells.size()), | ||
|
@@ -120,12 +121,12 @@ void loadWithTs( | |
SafeArg.of("totalPartitions", totalPartitions)); | ||
} | ||
|
||
List<Callable<Void>> tasks = new ArrayList<>(); | ||
List<Callable<Void>> tasks = new ArrayList<>(hostsAndCells.size()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while this is probably a better estimate, we're still possibly going to exceed this probably (as each There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this isn't fully optimal but should be more reasonable estimate |
||
for (Map.Entry<CassandraServer, List<Cell>> hostAndCells : hostsAndCells.entrySet()) { | ||
if (log.isTraceEnabled()) { | ||
if (isTraceEnabled) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in general case I wouldn't normally pull There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, that makes sense |
||
log.trace( | ||
"Requesting {} cells from {} {}starting at timestamp {} on {}", | ||
SafeArg.of("cells", hostsAndCells.values().size()), | ||
SafeArg.of("cells", hostAndCells.getValue().size()), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this was a drive by fix as this seemed to log incorrect value There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep - thanks! |
||
LoggingArgs.tableRef(tableRef), | ||
SafeArg.of("timestampClause", loadAllTs ? "for all timestamps " : ""), | ||
SafeArg.of("startTs", startTs), | ||
|
@@ -159,8 +160,9 @@ private List<Callable<Void>> getLoadWithTsTasksForSingleHost( | |
final CassandraKeyValueServices.ThreadSafeResultVisitor visitor, | ||
final ConsistencyLevel consistency) { | ||
final ColumnParent colFam = new ColumnParent(CassandraKeyValueServiceImpl.internalTableName(tableRef)); | ||
List<Callable<Void>> tasks = new ArrayList<>(); | ||
for (final List<Cell> partition : batcher.partitionIntoBatches(cells, cassandraServer, tableRef)) { | ||
List<List<Cell>> batches = batcher.partitionIntoBatches(cells, cassandraServer, tableRef); | ||
List<Callable<Void>> tasks = new ArrayList<>(batches.size()); | ||
for (final List<Cell> partition : batches) { | ||
Comment on lines
+163
to
+165
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
Callable<Void> multiGetCallable = () -> clientPool.runWithRetryOnServer( | ||
cassandraServer, new FunctionCheckedException<CassandraClient, Void, Exception>() { | ||
@Override | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
type: improvement | ||
improvement: | ||
description: Optimize some cell and value extraction read paths | ||
links: | ||
- https://github.com/palantir/atlasdb/pull/6073 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we want to keep this method small so that it gets JITed & inlined for the
Cell.create
happy path