This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git


The following commit(s) were added to refs/heads/main by this push:
     new a41921691 🔄 synced local 'docs/specification/' with remote 
'docs/specification/'
a41921691 is described below

commit a419216913ece65143925da065a6d5b77018fbf9
Author: chaokunyang <[email protected]>
AuthorDate: Thu Dec 11 03:17:05 2025 +0000

    🔄 synced local 'docs/specification/' with remote 'docs/specification/'
---
 docs/specification/row_format_spec.md | 520 +++++++++++++++++++++++++++++++++-
 1 file changed, 518 insertions(+), 2 deletions(-)

diff --git a/docs/specification/row_format_spec.md 
b/docs/specification/row_format_spec.md
index c83dadde6..441f5f599 100644
--- a/docs/specification/row_format_spec.md
+++ b/docs/specification/row_format_spec.md
@@ -19,6 +19,522 @@ license: |
   limitations under the License.
 ---
 
-## Row Format
+## Overview
 
-Coming soon
+Apache Fory Row Format is a cache-friendly, random-access binary format 
designed for high-performance data processing. Unlike traditional serialization 
formats that require full deserialization, the row format enables:
+
+- **Random Field Access**: Read individual fields without deserializing the 
entire row
+- **Zero-Copy Operations**: Direct memory access without data transformation
+- **Cache-Friendly Layout**: Optimized memory layout for CPU cache efficiency
+- **Cross-Language Support**: Consistent binary format across Java, C++, and 
Python
+
+Fory provides two row format variants:
+
+| Format          | Languages         | Use Case                       |
+| --------------- | ----------------- | ------------------------------ |
+| Standard Format | Java, C++, Python | Cross-language compatibility   |
+| Compact Format  | Java only         | Space efficiency, smaller rows |
+
+## Format Comparison
+
+| Feature              | Standard Format               | Compact Format        
              |
+| -------------------- | ----------------------------- | 
----------------------------------- |
+| Field Slot Size      | Fixed 8 bytes                 | Natural width (1, 2, 
4, or 8 bytes) |
+| Null Bitmap Size     | 8-byte aligned                | Byte-aligned, can 
borrow padding    |
+| Null Bitmap Position | Before field slots            | After field slots (at 
end)          |
+| Fixed-Size Structs   | Variable region (offset+size) | Inline in fixed 
region              |
+| Field Ordering       | Schema-defined order          | Sorted by alignment   
              |
+| All Non-Nullable     | Bitmap still present          | Bitmap skipped 
entirely             |
+| Alignment            | Strict 8-byte                 | Relaxed (2, 4, or 
8-byte)           |
+
+---
+
+## Standard Row Format
+
+The standard format prioritizes cross-language compatibility and simplicity 
with uniform 8-byte field slots.
+
+### Design Principles
+
+1. **8-Byte Alignment**: All major structures are aligned to 8-byte boundaries 
for optimal memory access
+2. **Fixed-Width Field Slots**: Every field uses an 8-byte slot for uniform 
offset calculation
+3. **Null Bitmap**: Compact null tracking using bit vectors
+4. **Relative Offsets**: Variable-length data uses relative offsets for 
sub-buffer navigation
+
+### Row Binary Layout
+
+A row stores structured data with the following layout:
+
+```
++----------------+------------------+------------------+-----+------------------+------------------+
+|  Null Bitmap   |  Field 0 Slot    |  Field 1 Slot    | ... |  Field N-1 Slot 
 |  Variable Data   |
++----------------+------------------+------------------+-----+------------------+------------------+
+|  B bytes       |     8 bytes      |     8 bytes      |     |     8 bytes     
 |  Variable size   |
+```
+
+#### Null Bitmap
+
+The null bitmap tracks which fields contain null values:
+
+- **Size**: `((num_fields + 63) / 64) * 8` bytes (rounded up to nearest 8-byte 
word)
+- **Encoding**: Each bit corresponds to a field index
+  - Bit value `1` = field is null
+  - Bit value `0` = field is not null
+- **Bit Order**: Bit 0 of the first byte corresponds to field 0
+
+**Example**: For 10 fields, bitmap size = `((10 + 63) / 64) * 8 = 8` bytes
+
+#### Field Slots
+
+Each field occupies a fixed 8-byte slot regardless of its actual data type:
+
+- **Slot Offset**: `bitmap_size + field_index * 8`
+- **Total Fixed Region**: `bitmap_size + num_fields * 8` bytes
+
+**Field Slot Contents by Type**:
+
+| Type Category  | Slot Contents                       |
+| -------------- | ----------------------------------- |
+| Fixed-width    | Value stored directly (zero-padded) |
+| Variable-width | Offset + Size encoding (see below)  |
+
+#### Variable-Width Data Encoding
+
+Variable-length fields (strings, arrays, maps, nested structs) store an 
offset-size pair in their slot:
+
+```
++---------------------------+---------------------------+
+|    Relative Offset        |         Size              |
+|       (32 bits)           |       (32 bits)           |
++---------------------------+---------------------------+
+|<-------------- 64-bit field slot value -------------->|
+```
+
+- **Relative Offset** (upper 32 bits): Offset from the row's base address
+- **Size** (lower 32 bits): Size of the variable-width data in bytes
+
+**Encoding**:
+
+```
+offset_and_size = (relative_offset << 32) | size
+```
+
+**Decoding**:
+
+```
+relative_offset = (offset_and_size >> 32) & 0xFFFFFFFF
+size = offset_and_size & 0xFFFFFFFF
+```
+
+#### Variable Data Region
+
+Variable-length data is stored after the fixed region:
+
+- Data is written sequentially as fields are set
+- Each variable-length value is padded to 8-byte alignment
+- Padding bytes are zeroed for deterministic output
+
+### Array Binary Layout
+
+Arrays store homogeneous sequences of elements:
+
+```
++------------------+------------------+------------------+
+|  Element Count   |   Null Bitmap    |   Element Data   |
++------------------+------------------+------------------+
+|     8 bytes      |     B bytes      |   Variable size  |
+```
+
+#### Array Header
+
+| Field         | Size                            | Description                
 |
+| ------------- | ------------------------------- | 
--------------------------- |
+| Element Count | 8 bytes                         | Number of elements 
(uint64) |
+| Null Bitmap   | `((count + 63) / 64) * 8` bytes | Per-element null flags     
 |
+
+**Header Size**: `8 + ((num_elements + 63) / 64) * 8` bytes
+
+#### Array Element Data
+
+Elements are stored contiguously after the header:
+
+- **Fixed-width elements**: Stored with their natural width (1, 2, 4, or 8 
bytes)
+- **Variable-width elements**: Stored as 8-byte offset+size pairs
+
+**Element Offset**: `header_size + element_index * element_size`
+
+**Data Region Size**: Rounded up to nearest 8-byte boundary
+
+#### Array Element Sizes
+
+| Element Type     | Element Size          |
+| ---------------- | --------------------- |
+| bool             | 1 byte                |
+| int8             | 1 byte                |
+| int16            | 2 bytes               |
+| int32            | 4 bytes               |
+| int64            | 8 bytes               |
+| float32          | 4 bytes               |
+| float64          | 8 bytes               |
+| string/binary    | 8 bytes (offset+size) |
+| array/map/struct | 8 bytes (offset+size) |
+
+### Map Binary Layout
+
+Maps store key-value pairs as two separate arrays:
+
+```
++------------------+------------------+------------------+
+|  Keys Array Size |   Keys Array     |   Values Array   |
++------------------+------------------+------------------+
+|     8 bytes      |   Variable size  |   Variable size  |
+```
+
+#### Map Structure
+
+| Field           | Size     | Description                       |
+| --------------- | -------- | --------------------------------- |
+| Keys Array Size | 8 bytes  | Total size of keys array in bytes |
+| Keys Array      | Variable | Full array structure for keys     |
+| Values Array    | Variable | Full array structure for values   |
+
+**Keys Array Offset**: `base_offset + 8`
+**Values Array Offset**: `base_offset + 8 + keys_array_size`
+
+Both keys and values arrays follow the standard array binary layout.
+
+### Nested Struct Layout
+
+Nested structs are stored as complete row structures within the variable data 
region:
+
+1. Parent field slot contains offset+size pointing to nested row
+2. Nested row has its own null bitmap and field slots
+3. Supports arbitrary nesting depth
+
+```
+Parent Row:
++----------------+------------------+------------------+
+|  Null Bitmap   |  ... Slots ...   |  Nested Row Data |
++----------------+------------------+------------------+
+                        |                    ^
+                        |  offset+size       |
+                        +------------------->+
+
+Nested Row:
++----------------+------------------+------------------+
+|  Null Bitmap   |  Field Slots     |  Variable Data   |
++----------------+------------------+------------------+
+```
+
+---
+
+## Compact Row Format (Java Only)
+
+The compact format provides space-efficient encoding with additional 
optimizations. It is currently implemented in Java only.
+
+> **Note**: The compact format is still under development and may not be 
stable yet.
+
+### Design Principles
+
+1. **Natural Width Storage**: Fixed-size fields use their natural byte width 
instead of 8 bytes
+2. **Alignment-Based Field Sorting**: Fields are sorted by alignment 
requirements to minimize padding
+3. **Conditional Null Bitmap**: Null bitmap is omitted when all fields are 
non-nullable
+4. **Inline Fixed-Size Structs**: Nested structs with all fixed-size fields 
are stored inline
+
+### Compact Row Binary Layout
+
+```
++------------------+------------------+-----+------------------+----------------+------------------+
+|  Field 0 Value   |  Field 1 Value   | ... |  Field N-1 Value | Null Bitmap   
 |  Variable Data   |
++------------------+------------------+-----+------------------+----------------+------------------+
+|  W0 bytes        |  W1 bytes        |     |  WN-1 bytes      | B bytes (opt) 
 |  Variable size   |
+```
+
+#### Key Differences from Standard Format
+
+1. **Field Slot Sizes**: Each field uses its natural width (Wi = type width or 
8 for variable)
+2. **Null Bitmap Position**: Placed after field slots, can borrow alignment 
padding
+3. **Field Order**: Fields are sorted by alignment (8-byte → 4-byte → 2-byte → 
1-byte → variable)
+4. **Conditional Bitmap**: Skipped entirely if all fields are non-nullable
+
+#### Null Bitmap (Compact)
+
+- **Size**: `(num_nullable_fields + 7) / 8` bytes (byte-aligned, not 8-byte 
aligned)
+- **Skipped**: When all fields are primitive/non-nullable
+- **Position**: After all fixed-size field slots, can use alignment padding 
space
+
+#### Field Sorting Algorithm
+
+Fields are sorted to minimize padding and optimize alignment:
+
+```
+Priority order (highest to lowest):
+1. Fields with 8-byte alignment (int64, float64, variable-width)
+2. Fields with 4-byte alignment (int32, float32)
+3. Fields with 2-byte alignment (int16)
+4. Fields with 1-byte alignment (int8, bool)
+```
+
+Within each alignment group, larger fields come first.
+
+#### Fixed-Size Struct Inlining
+
+Nested structs with all fixed-size fields are stored inline in the parent row:
+
+**Standard Format** (nested struct with 2 int32 fields):
+
+```
+Parent slot: [offset (4 bytes) | size (4 bytes)]  → Points to nested row (8+ 
bytes elsewhere)
+```
+
+**Compact Format** (same nested struct):
+
+```
+Parent slot: [int32 field 0 | int32 field 1]  → 8 bytes total, inline
+```
+
+This eliminates the offset+size indirection for fixed-size nested structures.
+
+#### Fixed-Width Calculation
+
+A field's fixed width is determined recursively:
+
+- **Primitive types**: Natural byte width (1, 2, 4, or 8)
+- **Struct types**: Sum of all child fixed widths (if all children are 
fixed-width)
+- **Variable types** (string, array, map): Returns -1 (uses 8-byte offset+size 
slot)
+
+```
+fixed_width(field) =
+  if primitive: type_width
+  if struct and all_children_fixed: header_bytes + sum(fixed_width(child) for 
each child)
+  else: -1 (variable, uses 8-byte slot)
+```
+
+### Compact Array Binary Layout
+
+```
++------------------+------------------+------------------+
+|  Element Count   |   Null Bitmap    |   Element Data   |
++------------------+------------------+------------------+
+|     4 bytes      | B bytes (opt)    |   Variable size  |
+```
+
+#### Compact Array Header
+
+| Field         | Size                          | Description                |
+| ------------- | ----------------------------- | -------------------------- |
+| Element Count | 4 bytes                       | Number of elements (int32) |
+| Null Bitmap   | `(count + 7) / 8` bytes (opt) | Per-element null flags     |
+
+**Header Size Calculation**:
+
+```
+header_size = 4 + (element_nullable ? (num_elements + 7) / 8 : 0)
+
+// Round to 8-byte boundary only if element width is 8-byte aligned
+if (fixed_width % 8 == 0):
+    header_size = round_to_8_bytes(header_size)
+```
+
+#### Key Differences from Standard Array
+
+1. **Element Count**: 4 bytes instead of 8 bytes
+2. **Null Bitmap**: Byte-aligned, skipped if elements are non-nullable
+3. **Fixed-Size Structs**: Inline storage for fixed-width struct elements
+
+---
+
+## Common Specifications
+
+The following specifications apply to both standard and compact formats.
+
+### Type Encoding
+
+#### Primitive Types
+
+| Type    | Width   | Encoding                        |
+| ------- | ------- | ------------------------------- |
+| bool    | 1 byte  | `0x00` (false) or `0x01` (true) |
+| int8    | 1 byte  | Two's complement                |
+| int16   | 2 bytes | Two's complement, little-endian |
+| int32   | 4 bytes | Two's complement, little-endian |
+| int64   | 8 bytes | Two's complement, little-endian |
+| float32 | 4 bytes | IEEE 754 single precision       |
+| float64 | 8 bytes | IEEE 754 double precision       |
+
+#### Temporal Types
+
+| Type      | Width   | Encoding                              |
+| --------- | ------- | ------------------------------------- |
+| timestamp | 8 bytes | Microseconds since Unix epoch (int64) |
+| date32    | 4 bytes | Days since Unix epoch (int32)         |
+| duration  | 8 bytes | Duration in microseconds (int64)      |
+
+#### String and Binary
+
+- **Encoding**: UTF-8 for strings, raw bytes for binary
+- **Storage**: Offset+size pair in field slot, data in variable region
+- **Padding**: Data padded to 8-byte alignment (standard) or natural alignment 
(compact)
+
+### Null Handling
+
+#### Row Null Handling
+
+- Null fields have their corresponding bit set to 1 in the null bitmap
+- Field slot contents are undefined for null fields (standard) or zeroed 
(compact)
+- Reading a null field returns a null/empty value indicator
+
+#### Array Null Handling
+
+- Null elements have their corresponding bit set to 1 in the array's null 
bitmap
+- Element data is undefined for null elements
+- Compact format: Bitmap skipped if elements are non-nullable
+
+#### Variable-Width Null Semantics
+
+When reading variable-width data from a null field:
+
+- Returns size of -1 or equivalent null indicator
+- No data access is performed
+
+### Alignment and Padding
+
+#### Standard Format Alignment
+
+1. **Null Bitmap**: Size rounded to 8-byte boundary
+2. **Field Slots**: Always 8 bytes each
+3. **Variable Data**: Each value padded to 8-byte boundary
+4. **Array Data**: Total data region padded to 8-byte boundary
+
+#### Compact Format Alignment
+
+1. **Field Slots**: Natural width (1, 2, 4, or 8 bytes)
+2. **Null Bitmap**: Byte-aligned, placed after fields
+3. **Variable Data**: Padded to 8-byte boundary only when needed
+4. **Header**: May use relaxed alignment for smaller overhead
+
+#### Padding Bytes
+
+- All padding bytes must be set to zero
+- Ensures deterministic serialization output
+- Prevents information leakage from uninitialized memory
+
+## Size Calculations
+
+### Standard Row Size
+
+```
+row_size = bitmap_size + num_fields * 8 + variable_data_size
+
+where:
+  bitmap_size = ((num_fields + 63) / 64) * 8
+  variable_data_size = sum of (padded_size for each variable field)
+  padded_size = ((size + 7) / 8) * 8
+```
+
+### Compact Row Size
+
+```
+row_size = fixed_region_size + bitmap_size + variable_data_size
+
+where:
+  fixed_region_size = sum of (fixed_width(field) or 8 for each field)
+  bitmap_size = all_non_nullable ? 0 : (num_nullable_fields + 7) / 8
+  // May be rounded to 8-byte boundary if has variable fields
+```
+
+### Standard Array Size
+
+```
+array_size = header_size + data_size
+
+where:
+  header_size = 8 + ((num_elements + 63) / 64) * 8
+  data_size = ((num_elements * element_size + 7) / 8) * 8
+```
+
+### Compact Array Size
+
+```
+array_size = header_size + data_size
+
+where:
+  header_size = 4 + (element_nullable ? (num_elements + 7) / 8 : 0)
+  // header_size rounded to 8 if element_width % 8 == 0
+  data_size = num_elements * element_width
+```
+
+### Map Size
+
+```
+map_size = 8 + keys_array_size + values_array_size
+```
+
+## Summary Tables
+
+### Layout Summary
+
+| Component        | Standard Format                 | Compact Format          
              |
+| ---------------- | ------------------------------- | 
------------------------------------- |
+| Row Header       | `((N + 63) / 64) * 8` bytes     | 0 or `(N + 7) / 8` 
bytes (at end)     |
+| Row Field Slots  | `N * 8` bytes                   | `sum(field_widths)` 
bytes             |
+| Array Header     | `8 + ((E + 63) / 64) * 8` bytes | `4 + (E + 7) / 8` bytes 
(if nullable) |
+| Array Elements   | `E * element_size` (8-aligned)  | `E * element_width`     
              |
+| Map Header       | 8 bytes                         | 8 bytes                 
              |
+| Offset+Size Pair | 8 bytes (32-bit offset + size)  | 8 bytes (same)          
              |
+
+Where N = number of fields, E = number of elements
+
+### Type Width Summary
+
+| Category      | Storage Width | Standard Slot | Compact Slot |
+| ------------- | ------------- | ------------- | ------------ |
+| bool          | 1 byte        | 8 bytes       | 1 byte       |
+| int8          | 1 byte        | 8 bytes       | 1 byte       |
+| int16         | 2 bytes       | 8 bytes       | 2 bytes      |
+| int32         | 4 bytes       | 8 bytes       | 4 bytes      |
+| int64         | 8 bytes       | 8 bytes       | 8 bytes      |
+| float32       | 4 bytes       | 8 bytes       | 4 bytes      |
+| float64       | 8 bytes       | 8 bytes       | 8 bytes      |
+| string/binary | Variable      | 8 bytes       | 8 bytes      |
+| array         | Variable      | 8 bytes       | 8 bytes      |
+| map           | Variable      | 8 bytes       | 8 bytes      |
+| struct        | Variable      | 8 bytes       | inline or 8  |
+
+## Implementation Notes
+
+### Endianness
+
+- All multi-byte integers are stored in **little-endian** format
+- Floating-point values use native IEEE 754 representation
+
+### Memory Safety
+
+- Writers must zero padding bytes to prevent information leakage
+- Readers must validate offsets and sizes before accessing data
+- Buffer bounds checking is required for untrusted input
+
+### Performance Considerations
+
+**Standard Format**:
+
+- Fixed 8-byte slots enable O(1) field access with simple arithmetic
+- 8-byte alignment optimizes CPU cache line usage
+- Best for cross-language interoperability
+
+**Compact Format**:
+
+- Smaller row sizes reduce memory bandwidth
+- Field sorting minimizes padding waste
+- Inline structs eliminate pointer chasing
+- Relaxed alignment may have slight CPU overhead on some architectures
+
+### When to Use Each Format
+
+| Scenario                         | Recommended Format |
+| -------------------------------- | ------------------ |
+| Cross-language data exchange     | Standard           |
+| Java-only, memory-constrained    | Compact            |
+| Many small primitive fields      | Compact            |
+| Many nested fixed-size structs   | Compact            |
+| Maximum read performance         | Standard           |
+| Interoperability with C++/Python | Standard           |


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to