strs_tools 0.45.0

Tools to manipulate strings.
Documentation
# Task 002: Zero-Copy String Operations Optimization

## Priority: High
## Impact: 2-5x memory reduction, 20-40% speed improvement
## Estimated Effort: 3-4 days

## Problem Statement

Current `strs_tools` implementation returns owned `String` objects from split operations, causing unnecessary memory allocations and copies:

```rust
// Current approach - allocates new String for each segment
let result: Vec<String> = string::split()
    .src(input)
    .delimeter(" ")
    .perform()
    .map(String::from)  // ← Unnecessary allocation
    .collect();
```

This affects performance in several ways:
- **Memory overhead**: Each split segment requires heap allocation
- **Copy costs**: String content copied from original to new allocations
- **GC pressure**: Frequent allocations increase memory management overhead
- **Cache misses**: Scattered allocations reduce memory locality

## Solution Approach

Implement zero-copy string operations using lifetime-managed string slices and copy-on-write semantics.

### Implementation Plan

#### 1. Zero-Copy Split Iterator

```rust
// New zero-copy split iterator
pub struct ZeroCopySplitIterator<'a> 
{
    input: &'a str,
    delimiters: &'a [&'a str],
    position: usize,
    preserve_delimiters: bool,
    preserve_empty: bool,
}

impl<'a> Iterator for ZeroCopySplitIterator<'a> {
    type Item = ZeroCopySegment<'a>;
    
    fn next(&mut self) -> Option<Self::Item> 
{
        // Return string slices directly from original input
        // No allocations unless modification needed
    }
}
```

#### 2. Copy-on-Write String Segments

```rust
use std::borrow::Cow;

/// Zero-copy string segment with optional mutation
pub struct ZeroCopySegment<'a> 
{
    content: Cow<'a, str>,
    segment_type: SegmentType,
    start_pos: usize,
    end_pos: usize,
    was_quoted: bool,
}

impl<'a> ZeroCopySegment<'a> {
    /// Get string slice without allocation
    pub fn as_str(&self) -> &str 
{
        &self.content
    }
    
    /// Convert to owned String only when needed
    pub fn into_owned(self) -> String 
{
        self.content.into_owned()
    }
    
    /// Modify content (triggers copy-on-write)
    pub fn make_mut(&mut self) -> &mut String 
{
        self.content.to_mut()
    }
}
```

#### 3. Lifetime-Safe Builder Pattern

```rust
pub struct ZeroCopySplit<'a> 
{
    src: Option<&'a str>,
    delimiters: Vec<&'a str>,
    options: SplitOptions,
}

impl<'a> ZeroCopySplit<'a> {
    pub fn src(mut self, src: &'a str) -> Self 
{
        self.src = Some(src);
        self
    }
    
    pub fn delimeter(mut self, delim: &'a str) -> Self 
{
        self.delimiters.push(delim);
        self
    }
    
    pub fn perform(self) -> ZeroCopySplitIterator<'a> 
{
        ZeroCopySplitIterator::new(
            self.src.expect("Source string required"),
            &self.delimiters,
            self.options
        )
    }
}
```

#### 4. SIMD Integration with Zero-Copy

```rust
#[cfg(feature = "simd")]
pub struct SIMDZeroCopySplitIterator<'a> 
{
    input: &'a str,
    patterns: Arc<AhoCorasick>,
    position: usize,
    delimiter_patterns: &'a [&'a str],
}

impl<'a> Iterator for SIMDZeroCopySplitIterator<'a> {
    type Item = ZeroCopySegment<'a>;
    
    fn next(&mut self) -> Option<Self::Item> 
{
        // SIMD pattern matching returning zero-copy segments
        if let Some(mat) = self.patterns.find(&self.input[self.position..]) {
            let segment_slice = &self.input[self.position..self.position + mat.start()];
            Some(ZeroCopySegment {
                content: Cow::Borrowed(segment_slice),
                segment_type: SegmentType::Content,
                start_pos: self.position,
                end_pos: self.position + mat.start(),
                was_quoted: false,
            })
        } else {
            None
        }
    }
}
```

### Technical Requirements

#### Memory Management
- **Zero allocation** for string slices from original input
- **Copy-on-write** semantics for modifications
- **Lifetime tracking** to ensure memory safety
- **Arena allocation** option for bulk operations

#### API Compatibility
- **Backwards compatibility** with existing `split().perform()` API
- **Gradual migration** path for existing code
- **Performance opt-in** via new `zero_copy()` method
- **Feature flag** for zero-copy optimizations

#### Safety Guarantees
- **Lifetime correctness** verified at compile time
- **Memory safety** without runtime overhead
- **Borrow checker** compliance for all operations
- **No dangling references** in any usage pattern

### Performance Targets

| Operation | Current | Zero-Copy Target | Improvement |
|-----------|---------|------------------|-------------|
| **Split 1KB text** | 15.2μs | 6.1μs | **2.5x faster** |
| **Split 10KB text** | 142.5μs | 48.3μs | **2.9x faster** |
| **Memory usage** | 100% | 20-40% | **60-80% reduction** |
| **Cache misses** | High | Low | **3-5x fewer misses** |

#### Memory Impact
- **Heap allocations**: Reduce from O(n) segments to O(1) 
- **Peak memory**: 60-80% reduction for typical workloads
- **GC pressure**: Eliminate frequent small allocations
- **Memory locality**: Improve cache performance significantly

### Implementation Steps

1. **Design lifetime-safe API** ensuring borrowing rules compliance
2. **Implement ZeroCopySegment** with Cow<'a, str> backing
3. **Create zero-copy split iterator** returning string slices
4. **Integrate with SIMD optimizations** maintaining zero-copy benefits
5. **Add performance benchmarks** comparing allocation patterns
6. **Comprehensive testing** for lifetime and memory safety
7. **Migration guide** for existing code adoption

### Challenges & Solutions

#### Challenge: Complex Lifetime Management
**Solution**: Use lifetime parameters consistently and provide helper methods
```rust
// Lifetime-safe helper for common patterns
pub fn zero_copy_split<'a>(input: &'a str, delimiters: &[&str]) -> impl Iterator<Item = &'a str> + 'a 

{
    // Simplified interface for basic cases
}
```

#### Challenge: Backwards Compatibility
**Solution**: Maintain existing API while adding zero-copy alternatives
```rust
impl Split 
{
    // Existing API unchanged
    pub fn perform(self) -> impl Iterator<Item = String> { /* ... */ }
    
    // New zero-copy API
    pub fn perform_zero_copy(self) -> impl Iterator<Item = ZeroCopySegment> { /* ... */ }
}
```

#### Challenge: Modification Operations
**Solution**: Copy-on-write with clear mutation semantics
```rust
let mut segment = split.perform_zero_copy().next().unwrap();
// No allocation until modification
println!("{}", segment.as_str());  // Zero-copy access

// Triggers copy-on-write
segment.make_mut().push('!');     // Now owned
```

### Success Criteria

- [ ] **60% memory reduction** in typical splitting operations
- [ ] **25% speed improvement** for read-only access patterns  
- [ ] **Zero breaking changes** to existing strs_tools API
- [ ] **Comprehensive lifetime safety** verified by borrow checker
- [ ] **SIMD compatibility** maintained with zero-copy benefits
- [ ] **Performance benchmarks** showing memory and speed improvements

### Benchmarking Strategy

#### Memory Usage Benchmarks
```rust
#[bench]
fn bench_memory_allocation_patterns(b: &mut Bencher) 
{
    let input = "large text with many segments...".repeat(1000);
    
    // Current approach
    b.iter(|| {
        let owned_strings: Vec<String> = split()
            .src(&input)
            .delimeter(" ")
            .perform()
            .collect();
        black_box(owned_strings)
    });
}

#[bench] 
fn bench_zero_copy_patterns(b: &mut Bencher) 
{
    let input = "large text with many segments...".repeat(1000);
    
    // Zero-copy approach
    b.iter(|| {
        let segments: Vec<&str> = split()
            .src(&input)
            .delimeter(" ")
            .perform_zero_copy()
            .map(|seg| seg.as_str())
            .collect();
        black_box(segments)
    });
}
```

#### Performance Validation
- **Allocation tracking** using custom allocators
- **Memory profiling** with valgrind/heaptrack
- **Cache performance** measurement with perf
- **Throughput comparison** across input sizes

### Integration with Existing Optimizations

#### SIMD Compatibility
- Zero-copy segments work seamlessly with SIMD pattern matching
- Memory locality improvements complement SIMD vectorization
- Pattern caching remains effective with zero-copy iterators

#### Future Optimization Synergy
- **Streaming operations**: Zero-copy enables efficient large file processing
- **Parser integration**: Direct slice passing reduces parsing overhead
- **Parallel processing**: Safer memory sharing across threads

### Migration Path

#### Phase 1: Opt-in Zero-Copy API
```rust
// Existing code unchanged
let strings: Vec<String> = split().src(input).delimeter(" ").perform().collect();

// New zero-copy opt-in
let segments: Vec<&str> = split().src(input).delimeter(" ").perform_zero_copy()
    .map(|seg| seg.as_str()).collect();
```

#### Phase 2: Performance-Aware Defaults
```rust
// Automatic zero-copy for read-only patterns
let count = split().src(input).delimeter(" ").perform().count();  // Uses zero-copy

// Explicit allocation when mutation needed
let mut strings: Vec<String> = split().src(input).delimeter(" ").perform().to_owned().collect();
```

### Success Metrics Documentation

Update `benchmarks/readme.md` with:
- Memory allocation pattern comparisons (before/after)
- Cache performance improvements with hardware counters
- Throughput analysis for different access patterns (read-only vs mutation)
- Integration performance with SIMD optimizations

### Related Tasks

- Task 001: SIMD optimization (synergy with zero-copy memory patterns)
- Task 003: Memory pool allocation (complementary allocation strategies) 
- Task 005: Streaming evaluation (zero-copy enables efficient streaming)
- Task 007: Parser integration (direct slice passing optimization)