[JBoss JIRA] (ISPN-8521) Off-heap addresses could be stored as int instead of long
by Dan Berindei (JIRA)
Dan Berindei created ISPN-8521:
----------------------------------
Summary: Off-heap addresses could be stored as int instead of long
Key: ISPN-8521
URL: https://issues.jboss.org/browse/ISPN-8521
Project: Infinispan
Issue Type: Task
Components: Core
Affects Versions: 9.2.0.Alpha2
Reporter: Dan Berindei
Assignee: William Burns
The JVM can store object pointers as 4-byte ints even on machines with > 32GB of RAM, as long as the heap itself is < 32GB, by using the fact that Java objects are always aligned to 8 bytes:
{{address = stored_pointer << 3 + base}}
Off-heap relies on the platform malloc (via {{Unsafe.allocateMemory}}), so it cannot guarantee that all off-heap allocations are in a 32GB range (except in a 32-bit JVM, of course). But that should work on a machine with less than 32GB of RAM, and it may also work if the JVM runs in a Docker container limited to < 32GB.
If we allocated one big block at startup and did our own memory management, we could both guarantee that all allocations are in a 32GB range, and increase the alignment of our entries in order to use a bigger shift (e.g. align to 32 bytes and shift by 5, for a maximum of 128GB).
Doing the alignment on top of {{Unsafe.allocateMemory()}} would probably waste more memory than the small pointers would save, but it's more feasible with a native library: [posix_memalign|http://man7.org/linux/man-pages/man3/posix_memalign.3.html].
Another option would be to use open addressing instead of separate chaining with linked lists for our hash table. The table in {{MemoryAddressHash}} would have to keep the full addresses of the entries, but the LRU next/previous pointers could be replaced by table indexes.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months
[JBoss JIRA] (ISPN-8520) Use single memory block for address list values
by William Burns (JIRA)
William Burns created ISPN-8520:
-----------------------------------
Summary: Use single memory block for address list values
Key: ISPN-8520
URL: https://issues.jboss.org/browse/ISPN-8520
Project: Infinispan
Issue Type: Sub-task
Components: Off Heap
Affects Versions: 9.2.0.Alpha2
Reporter: William Burns
Currently off heap stores the values as a forward only list of separate pointers. We could instead store these in a single block of memory for each bucket. This would reduce overhead for each bucket as it would only require 1 block of memory. However every time a new entry is added or removed we would have to free the entire block of memory. This however would have the benefit of the lookup would be much more efficient when we have more entries as they are contiguous in memory.
This issue would probably benefit reads at the cost of writes possibly, but it would have to be tested with different sizes of address lookups to be sure.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months
[JBoss JIRA] (ISPN-8517) Lazily ressurect ice fromMemory
by William Burns (JIRA)
[ https://issues.jboss.org/browse/ISPN-8517?page=com.atlassian.jira.plugin.... ]
William Burns updated ISPN-8517:
--------------------------------
Status: Pull Request Sent (was: Open)
Git Pull Request: https://github.com/infinispan/infinispan/pull/5583
> Lazily ressurect ice fromMemory
> -------------------------------
>
> Key: ISPN-8517
> URL: https://issues.jboss.org/browse/ISPN-8517
> Project: Infinispan
> Issue Type: Sub-task
> Components: Off Heap
> Affects Versions: 9.2.0.Alpha2
> Reporter: William Burns
> Assignee: William Burns
> Fix For: 9.2.0.Beta1, 9.1.3.Final
>
>
> Currently many places do
> {code}
> ice = ice = offHeapEntryFactory.fromMemory(address)
> if (wrappedKey.equalsWrappedBytes(ice.getKey()))
> {code}
> In cases where this ends up being a miss, we read the entire value which is wasteful. And the CPU may not have the key in the cache size we read the object into memory. Where as if we do
> {code}
> if (offHeapEntryFactory.equalsKey(address, key))
> ice = ice = offHeapEntryFactory.fromMemory(address)
> {code}
> we know that CPU is reading from the address location twice in a row, which has a very high chance of still being in CPU caches which should hopefully provide better performance. We also then don't have to read the entire ice object in memory unless there was a hit.
> We also should change _performGet_ to return the address instead of the ice. This way callers can use this address for other optimizations such as when doing a _evict_ or _compute_ which have to read the entry first before a remove.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months
[JBoss JIRA] (ISPN-8517) Lazily ressurect ice fromMemory
by William Burns (JIRA)
[ https://issues.jboss.org/browse/ISPN-8517?page=com.atlassian.jira.plugin.... ]
William Burns commented on ISPN-8517:
-------------------------------------
So when using eviction it helped about 6% and without eviction it was only a couple percent at most. This change would have more affect as the key or values are larger though as mine were only 10 and 1000 bytes each.
> Lazily ressurect ice fromMemory
> -------------------------------
>
> Key: ISPN-8517
> URL: https://issues.jboss.org/browse/ISPN-8517
> Project: Infinispan
> Issue Type: Sub-task
> Components: Off Heap
> Affects Versions: 9.2.0.Alpha2
> Reporter: William Burns
> Assignee: William Burns
> Fix For: 9.2.0.Beta1, 9.1.3.Final
>
>
> Currently many places do
> {code}
> ice = ice = offHeapEntryFactory.fromMemory(address)
> if (wrappedKey.equalsWrappedBytes(ice.getKey()))
> {code}
> In cases where this ends up being a miss, we read the entire value which is wasteful. And the CPU may not have the key in the cache size we read the object into memory. Where as if we do
> {code}
> if (offHeapEntryFactory.equalsKey(address, key))
> ice = ice = offHeapEntryFactory.fromMemory(address)
> {code}
> we know that CPU is reading from the address location twice in a row, which has a very high chance of still being in CPU caches which should hopefully provide better performance. We also then don't have to read the entire ice object in memory unless there was a hit.
> We also should change _performGet_ to return the address instead of the ice. This way callers can use this address for other optimizations such as when doing a _evict_ or _compute_ which have to read the entry first before a remove.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months
[JBoss JIRA] (ISPN-8517) Lazily ressurect ice fromMemory
by William Burns (JIRA)
[ https://issues.jboss.org/browse/ISPN-8517?page=com.atlassian.jira.plugin.... ]
William Burns updated ISPN-8517:
--------------------------------
Status: Open (was: New)
> Lazily ressurect ice fromMemory
> -------------------------------
>
> Key: ISPN-8517
> URL: https://issues.jboss.org/browse/ISPN-8517
> Project: Infinispan
> Issue Type: Sub-task
> Components: Off Heap
> Affects Versions: 9.2.0.Alpha2
> Reporter: William Burns
> Assignee: William Burns
> Fix For: 9.2.0.Beta1, 9.1.3.Final
>
>
> Currently many places do
> {code}
> ice = ice = offHeapEntryFactory.fromMemory(address)
> if (wrappedKey.equalsWrappedBytes(ice.getKey()))
> {code}
> In cases where this ends up being a miss, we read the entire value which is wasteful. And the CPU may not have the key in the cache size we read the object into memory. Where as if we do
> {code}
> if (offHeapEntryFactory.equalsKey(address, key))
> ice = ice = offHeapEntryFactory.fromMemory(address)
> {code}
> we know that CPU is reading from the address location twice in a row, which has a very high chance of still being in CPU caches which should hopefully provide better performance. We also then don't have to read the entire ice object in memory unless there was a hit.
> We also should change _performGet_ to return the address instead of the ice. This way callers can use this address for other optimizations such as when doing a _evict_ or _compute_ which have to read the entry first before a remove.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months
[JBoss JIRA] (ISPN-8517) Lazily ressurect ice fromMemory
by William Burns (JIRA)
[ https://issues.jboss.org/browse/ISPN-8517?page=com.atlassian.jira.plugin.... ]
William Burns updated ISPN-8517:
--------------------------------
Fix Version/s: 9.2.0.Beta1
9.1.3.Final
> Lazily ressurect ice fromMemory
> -------------------------------
>
> Key: ISPN-8517
> URL: https://issues.jboss.org/browse/ISPN-8517
> Project: Infinispan
> Issue Type: Sub-task
> Components: Off Heap
> Affects Versions: 9.2.0.Alpha2
> Reporter: William Burns
> Assignee: William Burns
> Fix For: 9.2.0.Beta1, 9.1.3.Final
>
>
> Currently many places do
> {code}
> ice = ice = offHeapEntryFactory.fromMemory(address)
> if (wrappedKey.equalsWrappedBytes(ice.getKey()))
> {code}
> In cases where this ends up being a miss, we read the entire value which is wasteful. And the CPU may not have the key in the cache size we read the object into memory. Where as if we do
> {code}
> if (offHeapEntryFactory.equalsKey(address, key))
> ice = ice = offHeapEntryFactory.fromMemory(address)
> {code}
> we know that CPU is reading from the address location twice in a row, which has a very high chance of still being in CPU caches which should hopefully provide better performance. We also then don't have to read the entire ice object in memory unless there was a hit.
> We also should change _performGet_ to return the address instead of the ice. This way callers can use this address for other optimizations such as when doing a _evict_ or _compute_ which have to read the entry first before a remove.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months
[JBoss JIRA] (ISPN-8517) Lazily ressurect ice fromMemory
by William Burns (JIRA)
[ https://issues.jboss.org/browse/ISPN-8517?page=com.atlassian.jira.plugin.... ]
William Burns commented on ISPN-8517:
-------------------------------------
I ran some tests comparing get performance between the new and old and it is a bit faster (I also added a preinsert as gets were always misses with no entries before so we could see that perf better)
https://gist.github.com/wburns/f74db9ac854552c0babea6fb53282291
> Lazily ressurect ice fromMemory
> -------------------------------
>
> Key: ISPN-8517
> URL: https://issues.jboss.org/browse/ISPN-8517
> Project: Infinispan
> Issue Type: Sub-task
> Components: Off Heap
> Affects Versions: 9.2.0.Alpha2
> Reporter: William Burns
> Assignee: William Burns
>
> Currently many places do
> {code}
> ice = ice = offHeapEntryFactory.fromMemory(address)
> if (wrappedKey.equalsWrappedBytes(ice.getKey()))
> {code}
> In cases where this ends up being a miss, we read the entire value which is wasteful. And the CPU may not have the key in the cache size we read the object into memory. Where as if we do
> {code}
> if (offHeapEntryFactory.equalsKey(address, key))
> ice = ice = offHeapEntryFactory.fromMemory(address)
> {code}
> we know that CPU is reading from the address location twice in a row, which has a very high chance of still being in CPU caches which should hopefully provide better performance. We also then don't have to read the entire ice object in memory unless there was a hit.
> We also should change _performGet_ to return the address instead of the ice. This way callers can use this address for other optimizations such as when doing a _evict_ or _compute_ which have to read the entry first before a remove.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
7 years, 2 months