Skip to content

DataSize bytes is acutally bibytes for method toKilobytes and aboveΒ #35184

@elienFR

Description

@elienFR

Hi spring dev community,

I found something quite confusing when using org.springframework.util.unit.DataSize, or org.springframework.util.unit.DataUnit.

Spring framework version is 6.2.8

Enhancements requests
When using DataSize class, if we run this spring test :

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.util.unit.DataSize;

@ExtendWith(MockitoExtension.class)
class DumbTest {

   @Test
   void test() {
       System.out.println(DataSize.ofMegabytes(10).toBytes());
   }

}

we have this console print :

10485760

This result is quite confusing since 10 megabytes (MB) should represent 10 million bytes , which would be 10 000 000 bytes.

Actually it seems `DataSize.ofMegabytes(10) is actually representing 10 mebibytes (10MiB) that represent 10 485 760 bytes.

So what is confusing is when we use the toBytes() method because converting megabytes (MB) to bytes (B) seems not to be accurate.

Could we improve the class so we could have methods concernnin bytes and bibytes ?
Same for DataUnit that would be based on DataSize, we would have something like DataUnit.MEGABYTES and DataUnit.MEBIBYTES.

Same things apply to other power of ten (kilo, mega, giga, tera...).

The way we could solve this is just by modifing DataSize code like so :

// --------------------- Existing code example for toKilobytes ------------------------

public final class DataSize implements Comparable<DataSize>, Serializable {

    private static final long BYTES_PER_KB = 1024L;
    private static final long BYTES_PER_MB = 1048576L;
    private static final long BYTES_PER_GB = 1073741824L;
    private static final long BYTES_PER_TB = 1099511627776L;

// Other method in other powers of ten 

    public static DataSize ofKilobytes(long kilobytes) {
        return new DataSize(Math.multiplyExact(kilobytes, BYTES_PER_KB));
    }

// Other method in other powers of ten 
}

// ----------------------- Changed code --------------------------
public final class DataSize implements Comparable<DataSize>, Serializable {
    private static final long BYTES_PER_KB = 1000L;
    private static final long BYTES_PER_MB = 1000000L;
    private static final long BYTES_PER_GB = 1000000000L;
    private static final long BYTES_PER_TB = 1000000000000L;
    private static final long BYTES_PER_KIB = 1024L;
    private static final long BYTES_PER_MIB = 1048576L;
    private static final long BYTES_PER_GIB = 1073741824L;
    private static final long BYTES_PER_TIB = 1099511627776L;

// Other method in other powers of ten 
    
    public static DataSize ofKilobytes(long kilobytes) {
        return new DataSize(Math.multiplyExact(kilobytes, BYTES_PER_KB));
    }

    public static DataSize ofKibibytes(long kibibytes) {
        return new DataSize(Math.multiplyExact(kilobytes, BYTES_PER_KIB));
    }

// Other method in other powers of ten 
// parsers to modify
}

Tank you :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: declinedA suggestion or change that we don't feel we should currently apply

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions