# mPy - profiling multiple implementations of persistent function parameters in a buffer
# Copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2026-09-03  initial release

from	time	import	ticks_us, ticks_diff
import	struct
from	array	import	array
import	json

# results:
# test1: bytes slicing buffer	432 uSec 
# test2: bytes memory view 		413 uSec
# test3: bytes struct 			385 uSec
# test4: array 					120 uSec
# test5: list 					 75 uSec
# test6: dict 					 58 uSec	<--
# test7: class					145 uSec

# ============================ utility ===============================

# a decorator for profiling a no parameter function including printing dt
def printDuration(f_test):

    def fut():
        t1 = ticks_us()
        result = f_test()
        t2 = ticks_us()
        print(ticks_diff(t2, t1), 'uSec ', end='')
        return result
    
    return fut

# ================================ tests =============================

# Serialising a integer by json and bytes 730 and 235 uSec
def test0():
    
    @printDuration
    def a():
        s = json.dumps(10).encode()
        a = json.loads(s.decode())
        
        
    @printDuration
    def b():
        a = 10 .to_bytes(4, 'little')
        b = int.from_bytes(a, 'little')
        
    a()
    b()

#test0()

# =====================================================

# bytes slicing buffer, 432 uSec 
def test1():

    @printDuration
    def incrI():
        i = int.from_bytes(buffer[4:8], 'little')
        i += 1
        buffer[4:8] = i.to_bytes(4, 'little') 
        return i
    
    
    buffer = bytearray(40)
    buffer[4:8] = 10 .to_bytes(4, 'little')

    for _ in range(5):
        i = incrI()
        print(i)

#test1()

# ===================================================
# bytes memoryview 413 uSec
def test2():
    ...

    @printDuration
    def incrI():
        i = int.from_bytes(data[4:8], 'little')
        i += 1
        data[4:8] = i.to_bytes(4, 'little') 
        return i
    
    
    buffer = bytearray(40)
    data   = memoryview(buffer)
    data[4:8] = 10 .to_bytes(4, 'little')

    for _ in range(5):
        i = incrI()
        print(i)

#test2()

# ========================================================

# bytes struct 385 uSec
def test3():
    
    @printDuration
    def incrI():
        i = struct.unpack_from('@i', buffer, N)[0]
        i += 1
        struct.pack_into('@i', buffer, N, i)
        return i
    
        
    buffer = bytearray(40)
    N = 4
    struct.pack_into('@i', buffer, N, 10)
    
    for _ in range(5):
        i = incrI()
        print(i)
    
#test3()

# ======================================================

# array 120 uSec
def test4():
    
    @printDuration
    def incrI():
        buffer[1] += 1
        return buffer[1]
    
        
    buffer = array('i', [0]*10)
    buffer[1] = 10
    
    for _ in range(5):
        i = incrI()
        print(i)

# test4()

# ===========================================

# list 75 uSec
def test5():
    
    @printDuration
    def incrI():
        buffer[1] += 1
        return buffer[1]
    
        
    buffer    = [0]*10
    buffer[1] = 10
    
    for _ in range(5):
        i = incrI()
        print(i)

# test5()

# =====================================

# dict 58 uSec
def test6():
    
    @printDuration
    def incrI():
         buffer['n1'] += 1
         return buffer['n1']
        
        
    buffer = dict(n0=0, n1=0, n2=0, n3=0, n4=0, n5=0, n6=0, n7=0, n8=0, n9=0)
    buffer['n1'] = 10
    
    for _ in range(5):
        i = incrI()
        print(i)

#test6()

# ===============================================

# class 146 uSec

class G:
    var1 = 10
    var2 = 20
    
    
def test7():
    
    @printDuration
    def incrI():
        G.var1 += 1
        return G.var1
    
           
    for _ in range(5):
        i = incrI()
        print(i)

#test7()

# ============================ end =============================
