Skip to content

Replace int-based access for edges with bytes-based access#2986

Closed
karussell wants to merge 22 commits into
masterfrom
bytes_edge_flags
Closed

Replace int-based access for edges with bytes-based access#2986
karussell wants to merge 22 commits into
masterfrom
bytes_edge_flags

Conversation

@karussell

@karussell karussell commented Apr 24, 2024

Copy link
Copy Markdown
Member

Currently we are only able to read integers from edges, which is a bit limiting as everything has to fit in one integer and if not, it will require two integers (instead of expanding to just 5 bytes).

So, with this change we can use only 5 bytes for the georef (see #2978) and we do not have to use int-based edge flags too, i.e. potential less space for this either. I.e. this change can reduce the storage requirement by 6 bytes (e.g. if flags use 5 or 9 bytes).

There is only a minor slowdown for routingCH_full, probably because of the change of the georef to bytes. The other minor slowdown for routingCH was compensated via removing the new instance of EdgeIntAccess for every EdgeIteratorState (independent of this PR).

Later this change will help if other edge properties like the edge IDs or link ID grow beyond 4 bytes.

TODO:

  • getByte/Short additionally to getInt to speed up retrieval for values with only a few bits -> tricky. Do later as it requires rewrite of InitializerConfig and IntEncodedValueImpl to a byte-based approach.
  • avoid padding via implementing padding in DataAccess.set/getInt/Short
  • later: use bytes for nodes too, then we could reduce 4 to probably just 1 byte for the turn restriction information
  • later: distance could be 5 bytes now, see Make EdgeAccess#INT_DIST_FACTOR configurable #1688 and Store distances as integers #1663.

@karussell karussell added this to the 10.0 milestone Apr 24, 2024

@easbar easbar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good!

Comment on lines +26 to +30
/**
* Gets the int value at the given index for the given edgeId
*/
int getInt(int edgeId, int edgeRowBytesOffset);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just int getInt(int edgeId, int offset)? And in the javadocs it should be 'at the given offset' then.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

offset would be a bit confusing in the context with getBytes? And also IMO it is unclear if the offset is int-based or byte-based?


import com.graphhopper.util.BitUtil;

public class EdgeBytesAccessArray implements EdgeBytesAccess {

@easbar easbar Apr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call it ArrayEdgeBytesAccess ? It's an EdgeByteAccess that uses an array rather than an array of EdgeBytesAccess? Just like there is java.util.ArrayList not java.util.ListArray(?).

public static final int VERSION_EDGE = 22;
public static final int VERSION_EDGE = 23;
// this should be increased whenever the format of the serialized EncodingManager is changed
public static final int VERSION_EM = 3;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be 4 now

Comment on lines +235 to +239
// measureRouting(hopper, new QuerySettings("routingCH_alt", count / 100, isCH, isLM).
// withInstructions().sod().alternative());
// measureRouting(hopper, new QuerySettings("routingCH_with_hints", count, isCH, isLM).
// withInstructions().sod().withPointHints());
// measureRouting(hopper, new QuerySettings("routingCH_no_sod", count, isCH, isLM).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't forget to uncomment this before merge?

Comment thread CHANGELOG.md Outdated
@@ -1,5 +1,7 @@
### 10.0 [not yet released]

- replaced IntsRef with BytesRef. Note that setInt(edgeId, index) uses a byte index now, i.e. instead of edgeAccess.setInt(edgeId, index, value) you now have to use edgeAccess.setInt(edgeId, index * 4, value)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention that previous TagParsers will no longer compile, but since they only pass on the edge access this is easy to fix. The direct usages of setInt are rare in comparison and probably hardly affect any users(?).

@Override
public double getCost(DecimalEncodedValue encodedValue) {
intsRef.ints[0] = turnCosts.getInt(turnCostPtr() + TC_FLAGS);
return encodedValue.getDecimal(false, -1, edgeIntAccess);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought using -1 made it a bit more clear that we are passing an unused value? In the code above we still use -1

*/
@Override
public int compareTo(IntsRef other) {
public int compareTo(BytesRef other) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Why) do we need to implement Comparable here?

This reverts commit ab278cd.
@karussell karussell closed this Apr 29, 2024
@karussell karussell removed this from the 10.0 milestone Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants