🐛 Bug
64-bit int metrics report incorrectly in the Runs Explorer table if the 31st bit in the value is set. This causes the UI to report an incorrect metric while the metrics graphs and the Aim repo itself will report the correct value. Because the export function in the Runs Explorer view uses the same data from that table, the exported CSVs also contain incorrect values.
To reproduce
Click for reprex code
import os
from aim import Repo, Run
# byte 3 = 0x3B, high bit clear -> displays correctly as 1,000,000,000
GOOD_VALUE = 1_000_000_000
# byte 3 = 0xB2, high bit SET -> UI displays -1,294,967,296 (off by 2^32 -> negative)
BAD_VALUE = 3_000_000_000
repo_path = os.path.dirname(os.path.abspath(__file__))
Repo(repo_path, init=True)
run = Run(repo=repo_path, experiment='int64-decoder-bug-demo')
run.name = 'int64-decoder-bug-demo'
run.track(GOOD_VALUE, name='good_int64', step=0)
run.track(BAD_VALUE, name='bad_int64', step=0)
run.close()
byte3_good = (GOOD_VALUE >> 24) & 0xFF
byte3_bad = (BAD_VALUE >> 24) & 0xFF
print(f'Run hash: {run.hash}')
print(f'good_int64: tracked {GOOD_VALUE:,}'
f' (byte3=0x{byte3_good:02X}, high bit {"set" if byte3_good & 0x80 else "clear"})'
f' -> UI shows {GOOD_VALUE:,}')
print(f'bad_int64: tracked {BAD_VALUE:,}'
f' (byte3=0x{byte3_bad:02X}, high bit {"set" if byte3_bad & 0x80 else "clear"})'
f' -> UI shows {BAD_VALUE - 2**32:,}')
This code will create a new Aim repo in the current directory, register a new run, and add 2 values which should showcase the issue.
In this demo case, I intentionally picked a value to show negative in the UI which is rather extreme and would instantly tip a user off to problems. But I actually encountered this in the wild with a much larger value where the bugged value was also reasonable. It wasn't until pouring over charts I noticed the discrepancy, so this can sneak up on you.
Expected behavior
bad_int64 value in the Runs Explorer table should show 3,000,000,000, not a negative number. Additionally, the exported CSV from the Runs Explorer should export the correct 3,000,000,000 value and not the negative.
Environment
- Aim Version - 3.29.1
- Python version - 3.12.13
- pip version - 26.0.1
- OS
- Aim server: Ubuntu 24.04
- UI client: Windows 11 Build 26200
- Browsers tested:
- Microsoft Edge 148.0.3967.54
- Google Chrome 147.0.7778.98
Additional context
I believe the issue is in this section of code here:
|
return ( |
|
x[offset + 7] * _2__56 + |
|
x[offset + 6] * _2__48 + |
|
x[offset + 5] * _2__40 + |
|
x[offset + 4] * _2__32 + |
|
(x[offset + 3] << 24) + |
|
(x[offset + 2] << 16) + |
|
(x[offset + 1] << 8) + |
|
(x[offset + 0] << 0) |
|
); |
|
} |
The << in JavaScript is treating the output as a signed 32-bit int and therefore the 3rd byte becomes negative with the most significant bit of the 3rd byte (31st bit of the entire 64-bit value) is set.
Following the conventions around that code, a new const _2__24 = Math.pow(2, 24); followed by x[offset + 3] * _2__24 + for that 3rd byte should fix it?
🐛 Bug
64-bit int metrics report incorrectly in the Runs Explorer table if the 31st bit in the value is set. This causes the UI to report an incorrect metric while the metrics graphs and the Aim repo itself will report the correct value. Because the export function in the Runs Explorer view uses the same data from that table, the exported CSVs also contain incorrect values.
To reproduce
Click for reprex code
This code will create a new Aim repo in the current directory, register a new run, and add 2 values which should showcase the issue.
In this demo case, I intentionally picked a value to show negative in the UI which is rather extreme and would instantly tip a user off to problems. But I actually encountered this in the wild with a much larger value where the bugged value was also reasonable. It wasn't until pouring over charts I noticed the discrepancy, so this can sneak up on you.
Expected behavior
bad_int64value in the Runs Explorer table should show 3,000,000,000, not a negative number. Additionally, the exported CSV from the Runs Explorer should export the correct 3,000,000,000 value and not the negative.Environment
Additional context
I believe the issue is in this section of code here:
aim/aim/web/ui/src/utils/encoder/streamEncoding.ts
Lines 143 to 153 in 6e098e3
The
<<in JavaScript is treating the output as a signed 32-bit int and therefore the 3rd byte becomes negative with the most significant bit of the 3rd byte (31st bit of the entire 64-bit value) is set.Following the conventions around that code, a new
const _2__24 = Math.pow(2, 24);followed byx[offset + 3] * _2__24 +for that 3rd byte should fix it?