looptick


Namelooptick JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryA simple loop execution time measurement tool.
upload_time2025-08-12 03:58:00
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords benchmark loop performance profiling timer
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # LoopTick

一个简单的 Python 循环耗时测量工具。

## 安装
```bash
pip install looptick
```
本地安装
```bash
git clone https://github.com/DBinK/LoopTick
pip install -e .
```

## 使用示例

### 测量每个循环用时

常规方式

```python
from looptick import LoopTick
import time

looptick = LoopTick()

# 常规调用方式
for i in range(5):
    diff = looptick.tick()
    print(f"第 {i} 次循环耗时: {diff * looptick.NS2MS:.6f} ms")
    time.sleep(0.01)
    
print(f"总耗时: {looptick.total_sec:.6f} 秒")
print(f"平均耗时: {looptick.average_ms:.6f} ms")

# 或者用更精简的语法
for i in range(5):
    diff = looptick()  # 直接调用 __call__() 方法, 免去书写 tick()
    print(f"第 {i} 次循环耗时: {diff * looptick.NS2MS:.6f} ms")
    time.sleep(0.01)
```

使用上下文方式

```python
from looptick import LoopTick
import time

with LoopTick() as looptick:
with LoopTick() as looptick:
    for i in range(5):
        diff = looptick.tick()
        print(f"第 {i} 次循环耗时: {diff * looptick.NS2MS:.6f} ms")
        diff = looptick.tick()
        print(f"第 {i} 次循环耗时: {diff * looptick.NS2MS:.6f} ms")
        time.sleep(0.01)
```

输出结果示例:
```bash
(LoopTick) PS C:\IT\LoopTick> & C:\IT\LoopTick\.venv\Scripts\python.exe c:/IT/LoopTick/examples/with_usage.py  
第 0 次循环耗时: 0.000000 ms
第 1 次循环耗时: 10.829900 ms
第 2 次循环耗时: 16.055800 ms
第 3 次循环耗时: 14.013400 ms
第 4 次循环耗时: 15.587100 ms
总耗时: 0.056486 秒
平均耗时: 14.121550 ms
```


### 测量行间代码用时
```python
from looptick import LoopTick
import time

def stage1():
    time.sleep(0.02)  # 模拟 I/O 操作

def stage2():
    time.sleep(0.05)  # 模拟复杂计算

def stage3():
    time.sleep(0.01)  # 模拟轻量处理

# 使用多阶段测量
linetick = LoopTick()

for i in range(3):  # 模拟 1000 次循环

    start = linetick.tick()  # 第一次调用, 返回一个极小值 (0.000_001) 
                             # 完成一次循环后, 返回上一次循环的 mid2 -> start 的用时
                             # 一般我们不关心 start 变量的值, 仅表示测量开始
    stage1()  
    stage2() 

    mid1 = linetick.tick()   # 返回 start —> mid1 的用时

    stage3()  

    mid2 = linetick.tick()   # 返回 mid1 —> mid2 的用时

    print(f"\n第 {i} 次循环")
    print(f"stage1() + stage2() 耗时: {mid1 * linetick.NS2MS:.2f} ms")
    print(f"stage3() 耗时: {mid2 * linetick.NS2MS:.2f} ms")
    print(f"本循环总耗时: {(mid1 + mid2) * linetick.NS2MS:.2f} ms")
    
print(f"\n循环任务总耗时: {linetick.total_sec:.6f} 秒")
```
输出结果示例:
```bash
(LoopTick) PS C:\IT\LoopTick> & C:\IT\LoopTick\.venv\Scripts\python.exe c:/IT/LoopTick/examples/lines_usage.py     

第 0 次循环
stage1() + stage2() 耗时: 93.78 ms
stage3() 耗时: 15.10 ms
本循环总耗时: 108.88 ms

第 1 次循环
stage1() + stage2() 耗时: 89.86 ms
stage3() 耗时: 15.11 ms
本循环总耗时: 104.97 ms

第 2 次循环
stage1() + stage2() 耗时: 89.71 ms
stage3() 耗时: 15.01 ms
本循环总耗时: 104.72 ms

循环任务总耗时: 0.319596 秒
```

### 进阶用法: 多 Tick 测量
```python
from looptick import LoopTick
import time

def stage1():
    time.sleep(0.02)  # 模拟 I/O 操作

def stage2():
    time.sleep(0.05)  # 模拟复杂计算

def stage3():
    time.sleep(0.03)  # 模拟轻量处理

# 使用多阶段测量 + 单独循环测量
linetick = LoopTick()
looptick = LoopTick()

for i in range(3):  # 模拟 1000 次循环

    loop_ns = looptick.tick()  # 单独使用一个对象测量循环时间

    start = linetick.tick()  # 第一次调用, 返回一个极小值 (0.000_001) 
                             # 完成一次循环后, 返回上一次循环的 mid2 -> start 的用时
                             # 一般我们不关心 start 变量的值, 仅表示测量开始
                            
    stage1()  
    stage2() 

    mid1 = linetick.tick()     # 返回 start —> mid1 的用时

    stage3()  

    mid2 = linetick.tick()     # 返回 mid1 —> mid2 的用时

    print(f"\n第 {i} 次循环")
    print(f"stage1() + stage2() 耗时: {mid1 * linetick.NS2MS:.2f} ms")
    print(f"stage3() 耗时: {mid2 * linetick.NS2MS:.2f} ms")

    print(f"linetick 对象测量的循环耗时: {(mid1 + mid2) * linetick.NS2MS:.2f} ms")
    print(f"looptick 对象测量的循环耗时: {loop_ns * linetick.NS2MS:.2f} ms")

    
print(f"\nlinetick 对象测量的循环任务总耗时: {linetick.total_sec:.6f} 秒")

print(f"looptick 对象测量的循环任务总耗时: {looptick.total_sec:.6f} 秒")  
print(f"looptick 测量的每次循环平均耗时: {looptick.average_ms:.6f} ms")

# 注意: looptick 对象会少一次循环的计时, 因为在第一次调用时只能返回一个极小值 (0.000_001) 
```

输出结果示例:
```bash
(LoopTick) PS C:\IT\LoopTick> & C:\IT\LoopTick\.venv\Scripts\python.exe c:/IT/LoopTick/examples/multi_tick_usage.py

第 0 次循环
stage1() + stage2() 耗时: 94.48 ms
stage3() 耗时: 45.04 ms
linetick 对象测量的循环耗时: 139.52 ms
looptick 对象测量的循环耗时: 0.00 ms

第 1 次循环
stage1() + stage2() 耗时: 89.68 ms
stage3() 耗时: 44.96 ms
linetick 对象测量的循环耗时: 134.65 ms
looptick 对象测量的循环耗时: 140.12 ms

第 2 次循环
stage1() + stage2() 耗时: 89.43 ms
stage3() 耗时: 44.88 ms
linetick 对象测量的循环耗时: 134.31 ms
looptick 对象测量的循环耗时: 135.23 ms

linetick 对象测量的循环任务总耗时: 0.409659 秒
looptick 对象测量的循环任务总耗时: 0.275349 秒
looptick 测量的每次循环平均耗时: 137.674650 ms
```

## 已知问题
- [] 在第一次调用时只能返回一个极小值 (0.000_001)
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "looptick",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "benchmark, loop, performance, profiling, timer",
    "author": null,
    "author_email": "DBinK <DBinKv1d@Gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/8d/71/682cd0c190d7020ba50cb97a10b67d101728702e4eda16f8dff132eb430c/looptick-0.1.1.tar.gz",
    "platform": null,
    "description": "# LoopTick\n\n\u4e00\u4e2a\u7b80\u5355\u7684 Python \u5faa\u73af\u8017\u65f6\u6d4b\u91cf\u5de5\u5177\u3002\n\n## \u5b89\u88c5\n```bash\npip install looptick\n```\n\u672c\u5730\u5b89\u88c5\n```bash\ngit clone https://github.com/DBinK/LoopTick\npip install -e .\n```\n\n## \u4f7f\u7528\u793a\u4f8b\n\n### \u6d4b\u91cf\u6bcf\u4e2a\u5faa\u73af\u7528\u65f6\n\n\u5e38\u89c4\u65b9\u5f0f\n\n```python\nfrom looptick import LoopTick\nimport time\n\nlooptick = LoopTick()\n\n# \u5e38\u89c4\u8c03\u7528\u65b9\u5f0f\nfor i in range(5):\n    diff = looptick.tick()\n    print(f\"\u7b2c {i} \u6b21\u5faa\u73af\u8017\u65f6: {diff * looptick.NS2MS:.6f} ms\")\n    time.sleep(0.01)\n    \nprint(f\"\u603b\u8017\u65f6: {looptick.total_sec:.6f} \u79d2\")\nprint(f\"\u5e73\u5747\u8017\u65f6: {looptick.average_ms:.6f} ms\")\n\n# \u6216\u8005\u7528\u66f4\u7cbe\u7b80\u7684\u8bed\u6cd5\nfor i in range(5):\n    diff = looptick()  # \u76f4\u63a5\u8c03\u7528 __call__() \u65b9\u6cd5, \u514d\u53bb\u4e66\u5199 tick()\n    print(f\"\u7b2c {i} \u6b21\u5faa\u73af\u8017\u65f6: {diff * looptick.NS2MS:.6f} ms\")\n    time.sleep(0.01)\n```\n\n\u4f7f\u7528\u4e0a\u4e0b\u6587\u65b9\u5f0f\n\n```python\nfrom looptick import LoopTick\nimport time\n\nwith LoopTick() as looptick:\nwith LoopTick() as looptick:\n    for i in range(5):\n        diff = looptick.tick()\n        print(f\"\u7b2c {i} \u6b21\u5faa\u73af\u8017\u65f6: {diff * looptick.NS2MS:.6f} ms\")\n        diff = looptick.tick()\n        print(f\"\u7b2c {i} \u6b21\u5faa\u73af\u8017\u65f6: {diff * looptick.NS2MS:.6f} ms\")\n        time.sleep(0.01)\n```\n\n\u8f93\u51fa\u7ed3\u679c\u793a\u4f8b\uff1a\n```bash\n(LoopTick) PS C:\\IT\\LoopTick> & C:\\IT\\LoopTick\\.venv\\Scripts\\python.exe c:/IT/LoopTick/examples/with_usage.py  \n\u7b2c 0 \u6b21\u5faa\u73af\u8017\u65f6: 0.000000 ms\n\u7b2c 1 \u6b21\u5faa\u73af\u8017\u65f6: 10.829900 ms\n\u7b2c 2 \u6b21\u5faa\u73af\u8017\u65f6: 16.055800 ms\n\u7b2c 3 \u6b21\u5faa\u73af\u8017\u65f6: 14.013400 ms\n\u7b2c 4 \u6b21\u5faa\u73af\u8017\u65f6: 15.587100 ms\n\u603b\u8017\u65f6: 0.056486 \u79d2\n\u5e73\u5747\u8017\u65f6: 14.121550 ms\n```\n\n\n### \u6d4b\u91cf\u884c\u95f4\u4ee3\u7801\u7528\u65f6\n```python\nfrom looptick import LoopTick\nimport time\n\ndef stage1():\n    time.sleep(0.02)  # \u6a21\u62df I/O \u64cd\u4f5c\n\ndef stage2():\n    time.sleep(0.05)  # \u6a21\u62df\u590d\u6742\u8ba1\u7b97\n\ndef stage3():\n    time.sleep(0.01)  # \u6a21\u62df\u8f7b\u91cf\u5904\u7406\n\n# \u4f7f\u7528\u591a\u9636\u6bb5\u6d4b\u91cf\nlinetick = LoopTick()\n\nfor i in range(3):  # \u6a21\u62df 1000 \u6b21\u5faa\u73af\n\n    start = linetick.tick()  # \u7b2c\u4e00\u6b21\u8c03\u7528, \u8fd4\u56de\u4e00\u4e2a\u6781\u5c0f\u503c (0.000_001) \n                             # \u5b8c\u6210\u4e00\u6b21\u5faa\u73af\u540e, \u8fd4\u56de\u4e0a\u4e00\u6b21\u5faa\u73af\u7684 mid2 -> start \u7684\u7528\u65f6\n                             # \u4e00\u822c\u6211\u4eec\u4e0d\u5173\u5fc3 start \u53d8\u91cf\u7684\u503c, \u4ec5\u8868\u793a\u6d4b\u91cf\u5f00\u59cb\n    stage1()  \n    stage2() \n\n    mid1 = linetick.tick()   # \u8fd4\u56de start \u2014> mid1 \u7684\u7528\u65f6\n\n    stage3()  \n\n    mid2 = linetick.tick()   # \u8fd4\u56de mid1 \u2014> mid2 \u7684\u7528\u65f6\n\n    print(f\"\\n\u7b2c {i} \u6b21\u5faa\u73af\")\n    print(f\"stage1() + stage2() \u8017\u65f6: {mid1 * linetick.NS2MS:.2f} ms\")\n    print(f\"stage3() \u8017\u65f6: {mid2 * linetick.NS2MS:.2f} ms\")\n    print(f\"\u672c\u5faa\u73af\u603b\u8017\u65f6: {(mid1 + mid2) * linetick.NS2MS:.2f} ms\")\n    \nprint(f\"\\n\u5faa\u73af\u4efb\u52a1\u603b\u8017\u65f6: {linetick.total_sec:.6f} \u79d2\")\n```\n\u8f93\u51fa\u7ed3\u679c\u793a\u4f8b\uff1a\n```bash\n(LoopTick) PS C:\\IT\\LoopTick> & C:\\IT\\LoopTick\\.venv\\Scripts\\python.exe c:/IT/LoopTick/examples/lines_usage.py     \n\n\u7b2c 0 \u6b21\u5faa\u73af\nstage1() + stage2() \u8017\u65f6: 93.78 ms\nstage3() \u8017\u65f6: 15.10 ms\n\u672c\u5faa\u73af\u603b\u8017\u65f6: 108.88 ms\n\n\u7b2c 1 \u6b21\u5faa\u73af\nstage1() + stage2() \u8017\u65f6: 89.86 ms\nstage3() \u8017\u65f6: 15.11 ms\n\u672c\u5faa\u73af\u603b\u8017\u65f6: 104.97 ms\n\n\u7b2c 2 \u6b21\u5faa\u73af\nstage1() + stage2() \u8017\u65f6: 89.71 ms\nstage3() \u8017\u65f6: 15.01 ms\n\u672c\u5faa\u73af\u603b\u8017\u65f6: 104.72 ms\n\n\u5faa\u73af\u4efb\u52a1\u603b\u8017\u65f6: 0.319596 \u79d2\n```\n\n### \u8fdb\u9636\u7528\u6cd5: \u591a Tick \u6d4b\u91cf\n```python\nfrom looptick import LoopTick\nimport time\n\ndef stage1():\n    time.sleep(0.02)  # \u6a21\u62df I/O \u64cd\u4f5c\n\ndef stage2():\n    time.sleep(0.05)  # \u6a21\u62df\u590d\u6742\u8ba1\u7b97\n\ndef stage3():\n    time.sleep(0.03)  # \u6a21\u62df\u8f7b\u91cf\u5904\u7406\n\n# \u4f7f\u7528\u591a\u9636\u6bb5\u6d4b\u91cf + \u5355\u72ec\u5faa\u73af\u6d4b\u91cf\nlinetick = LoopTick()\nlooptick = LoopTick()\n\nfor i in range(3):  # \u6a21\u62df 1000 \u6b21\u5faa\u73af\n\n    loop_ns = looptick.tick()  # \u5355\u72ec\u4f7f\u7528\u4e00\u4e2a\u5bf9\u8c61\u6d4b\u91cf\u5faa\u73af\u65f6\u95f4\n\n    start = linetick.tick()  # \u7b2c\u4e00\u6b21\u8c03\u7528, \u8fd4\u56de\u4e00\u4e2a\u6781\u5c0f\u503c (0.000_001) \n                             # \u5b8c\u6210\u4e00\u6b21\u5faa\u73af\u540e, \u8fd4\u56de\u4e0a\u4e00\u6b21\u5faa\u73af\u7684 mid2 -> start \u7684\u7528\u65f6\n                             # \u4e00\u822c\u6211\u4eec\u4e0d\u5173\u5fc3 start \u53d8\u91cf\u7684\u503c, \u4ec5\u8868\u793a\u6d4b\u91cf\u5f00\u59cb\n                            \n    stage1()  \n    stage2() \n\n    mid1 = linetick.tick()     # \u8fd4\u56de start \u2014> mid1 \u7684\u7528\u65f6\n\n    stage3()  \n\n    mid2 = linetick.tick()     # \u8fd4\u56de mid1 \u2014> mid2 \u7684\u7528\u65f6\n\n    print(f\"\\n\u7b2c {i} \u6b21\u5faa\u73af\")\n    print(f\"stage1() + stage2() \u8017\u65f6: {mid1 * linetick.NS2MS:.2f} ms\")\n    print(f\"stage3() \u8017\u65f6: {mid2 * linetick.NS2MS:.2f} ms\")\n\n    print(f\"linetick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: {(mid1 + mid2) * linetick.NS2MS:.2f} ms\")\n    print(f\"looptick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: {loop_ns * linetick.NS2MS:.2f} ms\")\n\n    \nprint(f\"\\nlinetick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u4efb\u52a1\u603b\u8017\u65f6: {linetick.total_sec:.6f} \u79d2\")\n\nprint(f\"looptick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u4efb\u52a1\u603b\u8017\u65f6: {looptick.total_sec:.6f} \u79d2\")  \nprint(f\"looptick \u6d4b\u91cf\u7684\u6bcf\u6b21\u5faa\u73af\u5e73\u5747\u8017\u65f6: {looptick.average_ms:.6f} ms\")\n\n# \u6ce8\u610f: looptick \u5bf9\u8c61\u4f1a\u5c11\u4e00\u6b21\u5faa\u73af\u7684\u8ba1\u65f6, \u56e0\u4e3a\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\u53ea\u80fd\u8fd4\u56de\u4e00\u4e2a\u6781\u5c0f\u503c (0.000_001) \n```\n\n\u8f93\u51fa\u7ed3\u679c\u793a\u4f8b\uff1a\n```bash\n(LoopTick) PS C:\\IT\\LoopTick> & C:\\IT\\LoopTick\\.venv\\Scripts\\python.exe c:/IT/LoopTick/examples/multi_tick_usage.py\n\n\u7b2c 0 \u6b21\u5faa\u73af\nstage1() + stage2() \u8017\u65f6: 94.48 ms\nstage3() \u8017\u65f6: 45.04 ms\nlinetick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: 139.52 ms\nlooptick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: 0.00 ms\n\n\u7b2c 1 \u6b21\u5faa\u73af\nstage1() + stage2() \u8017\u65f6: 89.68 ms\nstage3() \u8017\u65f6: 44.96 ms\nlinetick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: 134.65 ms\nlooptick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: 140.12 ms\n\n\u7b2c 2 \u6b21\u5faa\u73af\nstage1() + stage2() \u8017\u65f6: 89.43 ms\nstage3() \u8017\u65f6: 44.88 ms\nlinetick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: 134.31 ms\nlooptick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u8017\u65f6: 135.23 ms\n\nlinetick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u4efb\u52a1\u603b\u8017\u65f6: 0.409659 \u79d2\nlooptick \u5bf9\u8c61\u6d4b\u91cf\u7684\u5faa\u73af\u4efb\u52a1\u603b\u8017\u65f6: 0.275349 \u79d2\nlooptick \u6d4b\u91cf\u7684\u6bcf\u6b21\u5faa\u73af\u5e73\u5747\u8017\u65f6: 137.674650 ms\n```\n\n## \u5df2\u77e5\u95ee\u9898\n- [] \u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\u53ea\u80fd\u8fd4\u56de\u4e00\u4e2a\u6781\u5c0f\u503c (0.000_001)",
    "bugtrack_url": null,
    "license": null,
    "summary": "A simple loop execution time measurement tool.",
    "version": "0.1.1",
    "project_urls": {
        "Source": "https://github.com/DBinK/LoopTick"
    },
    "split_keywords": [
        "benchmark",
        " loop",
        " performance",
        " profiling",
        " timer"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "54ddff02f0729c549bf0c51d8df3a4d0a881b68c634559848bcf94b5b50f58d7",
                "md5": "4ac8260a63f97721fe9ad3939040aaa3",
                "sha256": "d7f15701bacdaafa27363a8c346bd7bc5ee0b30556ee67853f3a098365b9ff1f"
            },
            "downloads": -1,
            "filename": "looptick-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4ac8260a63f97721fe9ad3939040aaa3",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 4594,
            "upload_time": "2025-08-12T03:57:59",
            "upload_time_iso_8601": "2025-08-12T03:57:59.501732Z",
            "url": "https://files.pythonhosted.org/packages/54/dd/ff02f0729c549bf0c51d8df3a4d0a881b68c634559848bcf94b5b50f58d7/looptick-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8d71682cd0c190d7020ba50cb97a10b67d101728702e4eda16f8dff132eb430c",
                "md5": "78e1a153325efe4bc67819c2e8cebafd",
                "sha256": "b765259186af7b507b612b6b15b1ec675470e3a7b9593064335e3393cc4a32fc"
            },
            "downloads": -1,
            "filename": "looptick-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "78e1a153325efe4bc67819c2e8cebafd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 6900,
            "upload_time": "2025-08-12T03:58:00",
            "upload_time_iso_8601": "2025-08-12T03:58:00.594575Z",
            "url": "https://files.pythonhosted.org/packages/8d/71/682cd0c190d7020ba50cb97a10b67d101728702e4eda16f8dff132eb430c/looptick-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-12 03:58:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "DBinK",
    "github_project": "LoopTick",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "looptick"
}
        
Elapsed time: 1.50524s