Repository: plasma-umass/scalene
Branch: master
Commit: 58c1b708ace1
Files: 396
Total size: 5.5 MB
Directory structure:
gitextract_amujz6e_/
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── blacken.yml
│ ├── build-and-upload.yml
│ ├── codeql.yml
│ ├── run-linters.yml
│ ├── test-smoketests.yml
│ └── tests.yml
├── .gitignore
├── .readthedocs.yaml
├── .vscode/
│ └── c_cpp_properties.json
├── CITATION.cff
├── CLAUDE.md
├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── GNUmakefile
├── LICENSE
├── MANIFEST.in
├── Makefile
├── Pipfile
├── README.md
├── Scalene-Agents.md
├── Scalene-Debugging.md
├── Scalene-GUI.md
├── agents/
│ └── windows-memory-profiling-port.md
├── benchmarks/
│ ├── bench_torch_memory.py
│ ├── benchmark.py
│ ├── julia1_nopil.py
│ ├── measure_profiler_memory.py
│ ├── new_benchmark.py
│ └── pystone.py
├── demo_torch_jit.py
├── docs/
│ └── scalene-demo.ipynb
├── index.rst
├── mypy.ini
├── pyproject.toml
├── pyrightconfig.json
├── pytest.ini
├── refactoring_todo.md
├── requirements.txt
├── ruff.toml
├── scalene/
│ ├── README.md
│ ├── __init__.py
│ ├── __main__.py
│ ├── adaptive.py
│ ├── find_browser.py
│ ├── get_module_details.py
│ ├── launchbrowser.py
│ ├── merge_scalene_neuron_profiles.py
│ ├── profile.py
│ ├── redirect_python.py
│ ├── replacement_asyncio.py
│ ├── replacement_exec.py
│ ├── replacement_exit.py
│ ├── replacement_fork.py
│ ├── replacement_get_context.py
│ ├── replacement_lock.py
│ ├── replacement_mp_lock.py
│ ├── replacement_pjoin.py
│ ├── replacement_poll_selector.py
│ ├── replacement_sem_lock.py
│ ├── replacement_signal_fns.py
│ ├── replacement_thread_join.py
│ ├── runningstats.py
│ ├── scalene-gui/
│ │ ├── README.md
│ │ ├── TODO-TypeScript.md
│ │ ├── amazon.ts
│ │ ├── anthropic.ts
│ │ ├── azure.ts
│ │ ├── example-profile.js
│ │ ├── gemini.ts
│ │ ├── gui-elements.ts
│ │ ├── index.html
│ │ ├── index.html.template
│ │ ├── list-amazon-models.py
│ │ ├── ollama.ts
│ │ ├── openai.ts
│ │ ├── optimizations.ts
│ │ ├── package.json
│ │ ├── persistence.ts
│ │ ├── prism.css
│ │ ├── prism.d.ts
│ │ ├── prism.js
│ │ ├── profile.json
│ │ ├── profiler.html
│ │ ├── scalene-demo.ts
│ │ ├── scalene-fetch.ts
│ │ ├── scalene-gui-bundle.js
│ │ ├── scalene-gui.ts
│ │ ├── tablesort.d.ts
│ │ ├── tablesort.js
│ │ ├── tsconfig.json
│ │ └── utils.ts
│ ├── scalene-usage.txt
│ ├── scalene_accelerator.py
│ ├── scalene_analysis.py
│ ├── scalene_apple_gpu.py
│ ├── scalene_arguments.py
│ ├── scalene_async.py
│ ├── scalene_client_timer.py
│ ├── scalene_config.py
│ ├── scalene_cpu_profiler.py
│ ├── scalene_funcutils.py
│ ├── scalene_jax.py
│ ├── scalene_json.py
│ ├── scalene_jupyter.py
│ ├── scalene_leak_analysis.py
│ ├── scalene_library_profiler.py
│ ├── scalene_library_registry.py
│ ├── scalene_lifecycle.py
│ ├── scalene_magics.py
│ ├── scalene_mapfile.py
│ ├── scalene_memory_profiler.py
│ ├── scalene_neuron.py
│ ├── scalene_nvidia_gpu.py
│ ├── scalene_output.py
│ ├── scalene_parseargs.py
│ ├── scalene_preload.py
│ ├── scalene_profiler.py
│ ├── scalene_signal_manager.py
│ ├── scalene_signals.py
│ ├── scalene_sigqueue.py
│ ├── scalene_statistics.py
│ ├── scalene_tensorflow.py
│ ├── scalene_torch.py
│ ├── scalene_tracer.py
│ ├── scalene_tracing.py
│ ├── scalene_utility.py
│ ├── scalene_windows.py
│ ├── set_nvidia_gpu_modes.py
│ ├── sorted_reservoir.py
│ ├── sparkline.py
│ ├── syntaxline.py
│ └── time_info.py
├── setup.py
├── src/
│ ├── include/
│ │ ├── common.hpp
│ │ ├── common_win.hpp
│ │ ├── lowdiscrepancy.hpp
│ │ ├── mallocrecursionguard.hpp
│ │ ├── mallocrecursionguard_win.hpp
│ │ ├── memcpysampler.hpp
│ │ ├── poissonsampler.hpp
│ │ ├── pyptr.h
│ │ ├── pywhere.hpp
│ │ ├── samplefile.hpp
│ │ ├── samplefile_win.hpp
│ │ ├── sampleheap.hpp
│ │ ├── sampleheap_win.hpp
│ │ ├── sampler.hpp
│ │ ├── scaleneheader.hpp
│ │ ├── thresholdsampler.hpp
│ │ └── traceconfig.hpp
│ └── source/
│ ├── get_line_atomic.cpp
│ ├── libscalene.cpp
│ ├── libscalene_windows.cpp
│ ├── pywhere.cpp
│ └── traceconfig.cpp
├── test/
│ ├── automatic/
│ │ ├── README.md
│ │ ├── dataframe/
│ │ │ ├── README.md
│ │ │ ├── dataframe-select-optimized.py
│ │ │ └── dataframe-select-original.py
│ │ └── svm/
│ │ ├── README.md
│ │ ├── data/
│ │ │ └── svm_data.pkl
│ │ ├── svm-optimized.py
│ │ └── svm-original.py
│ ├── expensive_benchmarks/
│ │ ├── README.md
│ │ ├── bm_async_tree_io.py
│ │ ├── bm_docutils.py
│ │ ├── bm_fannukh.py
│ │ ├── bm_mdp.py
│ │ ├── bm_pprint.py
│ │ ├── bm_raytrace.py
│ │ ├── bm_sympy.py
│ │ └── docutils_data/
│ │ └── docs/
│ │ ├── api/
│ │ │ ├── publisher.txt
│ │ │ ├── runtime-settings.txt
│ │ │ └── transforms.txt
│ │ ├── dev/
│ │ │ ├── distributing.txt
│ │ │ ├── enthought-plan.txt
│ │ │ ├── enthought-rfp.txt
│ │ │ ├── hacking.txt
│ │ │ ├── policies.txt
│ │ │ ├── pysource.txt
│ │ │ ├── release.txt
│ │ │ ├── repository.txt
│ │ │ ├── rst/
│ │ │ │ ├── alternatives.txt
│ │ │ │ └── problems.txt
│ │ │ ├── runtime-settings-processing.txt
│ │ │ ├── semantics.txt
│ │ │ ├── testing.txt
│ │ │ ├── todo.txt
│ │ │ └── website.txt
│ │ ├── howto/
│ │ │ ├── cmdline-tool.txt
│ │ │ ├── html-stylesheets.txt
│ │ │ ├── i18n.txt
│ │ │ ├── rst-directives.txt
│ │ │ ├── rst-roles.txt
│ │ │ └── security.txt
│ │ ├── index.txt
│ │ ├── peps/
│ │ │ ├── pep-0256.txt
│ │ │ ├── pep-0257.txt
│ │ │ ├── pep-0258.txt
│ │ │ └── pep-0287.txt
│ │ ├── ref/
│ │ │ ├── doctree.txt
│ │ │ └── rst/
│ │ │ ├── definitions.txt
│ │ │ ├── directives.txt
│ │ │ ├── introduction.txt
│ │ │ ├── mathematics.txt
│ │ │ ├── restructuredtext.txt
│ │ │ └── roles.txt
│ │ └── user/
│ │ ├── config.txt
│ │ ├── emacs.txt
│ │ ├── html.txt
│ │ ├── latex.txt
│ │ ├── links.txt
│ │ ├── mailing-lists.txt
│ │ ├── manpage.txt
│ │ ├── odt.txt
│ │ ├── rst/
│ │ │ ├── cheatsheet.txt
│ │ │ ├── demo.txt
│ │ │ ├── images/
│ │ │ │ └── biohazard.swf
│ │ │ └── quickstart.txt
│ │ ├── smartquotes.txt
│ │ └── tools.txt
│ ├── issues/
│ │ ├── test-issue124.py
│ │ ├── test-issue126.py
│ │ ├── test-issue130.py
│ │ ├── test-issue156.py
│ │ ├── test-issue167.py
│ │ ├── test-issue193.py
│ │ ├── test-issue244.py
│ │ ├── test-issue256.py
│ │ ├── test-issue266.py
│ │ ├── test-issue31.py
│ │ ├── test-issue379.py
│ │ ├── test-issue691.py
│ │ ├── test-issue74.py
│ │ └── test-issue914.py
│ ├── line_attribution_tests/
│ │ ├── line_after_final_alloc.py
│ │ ├── loop_below_threshold.py
│ │ ├── loop_with_multiple_lines.py
│ │ ├── loop_with_one_alloc.py
│ │ └── loop_with_two_allocs.py
│ ├── multiprocessing_test.py
│ ├── new_mp_test.py
│ ├── optimized/
│ │ ├── bm_pyflate.py
│ │ ├── bm_raytrace.py
│ │ ├── bm_richards.py
│ │ ├── bm_scimark.py
│ │ └── bm_spectral_norm.py
│ ├── original/
│ │ ├── bm_mdp.py
│ │ ├── bm_pyflate.py
│ │ ├── bm_raytrace.py
│ │ ├── bm_richards.py
│ │ ├── bm_scimark.py
│ │ ├── bm_spectral_norm.py
│ │ └── bm_sympy.py
│ ├── pool-test.py
│ ├── pool_spawn_test.py
│ ├── profile_annotation_test.py
│ ├── signal_test.py
│ ├── small_mp_test.py
│ ├── smoketest.py
│ ├── smoketest_line_invalidation.py
│ ├── smoketest_pool_spawn.py
│ ├── smoketest_profile_decorator.py
│ ├── test-martinheinz.py
│ ├── test-memory.py
│ ├── test-pprofile.py
│ ├── test-size.py
│ ├── test_async_demo.py
│ ├── test_sparkline.py
│ ├── test_timers.py
│ ├── test_tracer.py
│ ├── testflask-driver.py
│ ├── testflask.py
│ ├── testme.py
│ ├── testpyt.py
│ ├── testtf.py
│ ├── threads-test.py
│ └── torchtest.py
└── tests/
├── test_async_profiling.py
├── test_coverup_1.py
├── test_coverup_106.py
├── test_coverup_107.py
├── test_coverup_109.py
├── test_coverup_11.py
├── test_coverup_110.py
├── test_coverup_112.py
├── test_coverup_113.py
├── test_coverup_115.py
├── test_coverup_116.py
├── test_coverup_117.py
├── test_coverup_118.py
├── test_coverup_12.py
├── test_coverup_121.py
├── test_coverup_122.py
├── test_coverup_123.py
├── test_coverup_125.py
├── test_coverup_128.py
├── test_coverup_13.py
├── test_coverup_131.py
├── test_coverup_132.py
├── test_coverup_133.py
├── test_coverup_136.py
├── test_coverup_137.py
├── test_coverup_139.py
├── test_coverup_14.py
├── test_coverup_15.py
├── test_coverup_16.py
├── test_coverup_17.py
├── test_coverup_19.py
├── test_coverup_2.py
├── test_coverup_20.py
├── test_coverup_21.py
├── test_coverup_22.py
├── test_coverup_23.py
├── test_coverup_24.py
├── test_coverup_25.py
├── test_coverup_26.py
├── test_coverup_28.py
├── test_coverup_29.py
├── test_coverup_3.py
├── test_coverup_30.py
├── test_coverup_31.py
├── test_coverup_32.py
├── test_coverup_33.py
├── test_coverup_34.py
├── test_coverup_36.py
├── test_coverup_37.py
├── test_coverup_38.py
├── test_coverup_39.py
├── test_coverup_4.py
├── test_coverup_40.py
├── test_coverup_41.py
├── test_coverup_44.py
├── test_coverup_45.py
├── test_coverup_46.py
├── test_coverup_47.py
├── test_coverup_5.py
├── test_coverup_50.py
├── test_coverup_52.py
├── test_coverup_53.py
├── test_coverup_54.py
├── test_coverup_55.py
├── test_coverup_56.py
├── test_coverup_59.py
├── test_coverup_60.py
├── test_coverup_61.py
├── test_coverup_62.py
├── test_coverup_63.py
├── test_coverup_64.py
├── test_coverup_65.py
├── test_coverup_66.py
├── test_coverup_68.py
├── test_coverup_69.py
├── test_coverup_7.py
├── test_coverup_71.py
├── test_coverup_72.py
├── test_coverup_73.py
├── test_coverup_74.py
├── test_coverup_75.py
├── test_coverup_77.py
├── test_coverup_78.py
├── test_coverup_79.py
├── test_coverup_8.py
├── test_coverup_80.py
├── test_coverup_81.py
├── test_coverup_82.py
├── test_coverup_83.py
├── test_coverup_84.py
├── test_coverup_85.py
├── test_coverup_87.py
├── test_coverup_88.py
├── test_coverup_89.py
├── test_coverup_9.py
├── test_coverup_90.py
├── test_coverup_91.py
├── test_coverup_92.py
├── test_coverup_93.py
├── test_coverup_94.py
├── test_coverup_96.py
├── test_coverup_97.py
├── test_coverup_98.py
├── test_coverup_99.py
├── test_cpu_attribution.py
├── test_jax_profiler.py
├── test_jupyter_display_import.py
├── test_multiprocessing_pool_spawn.py
├── test_multiprocessing_spawn.py
├── test_nested_package_relative_import.py
├── test_on_off_windows.py
├── test_runningstats.py
├── test_scalene_json.py
├── test_tensorflow_profiler.py
└── test_torch_profiler.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [emeryberger, plasma-umass]
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
Please include a minimum working example if at all possible.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
If you have not yet tried with the repository version (`python3 -m pip install git+https://github.com/plasma-umass/scalene`), please try that before reporting.
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/workflows/blacken.yml
================================================
name: Format code
on:
push:
branches: [ master ]
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Format code with black
run: |
pip install black
black scalene
- name: Commit changes
uses: EndBug/add-and-commit@v4
with:
author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com
message: "Format code with black"
add: "."
branch: ${{ github.ref }}
================================================
FILE: .github/workflows/build-and-upload.yml
================================================
# https://docs.github.com/en/actions/guides/building-and-testing-python#publishing-to-package-registries
# When executed manually, this will upload a ".devNNN" build to testpypi;
# when executed upon a release, it will upload a regular build to pypi.
#
# For pypi, you need to have the PYPI_USERNAME and PYPI_PASSWORD secrets configured.
# For testpypi, you'll need TESTPYPI_USERNAME and TESTPYPI_PASSWORD.
name: build & upload
on:
release:
types: [ published ]
workflow_dispatch: # manual execution
jobs:
pick-devN:
name: create .devN build date coordinated across all matrix jobs
runs-on: ubuntu-latest
steps:
- run: TZ='America/New_York' date '+%Y%m%d%H%M' > devN.txt
- uses: actions/upload-artifact@v4
with:
name: devN
path: devN.txt
build-and-upload:
needs: pick-devN
strategy:
matrix:
python_version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
plat: ['manylinux_2_28', 'macos-latest', 'windows-latest']
include:
- plat: manylinux_2_28
os: ubuntu-latest
container: quay.io/pypa/manylinux_2_28_x86_64 # https://github.com/pypa/manylinux
- plat: macos-latest
os: macos-latest
- plat: macos-latest
os: macos-latest
- plat: macos-latest
os: macos-latest
python_version: 3.11
upload_source: true # just need ONE of them to do it
- plat: windows-latest
os: windows-latest
exclude:
- plat: windows-latest
python_version: 3.11
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
steps:
- name: get coordinated .devN
uses: actions/download-artifact@v4
with:
name: devN
- name: make dev build if not a release (non-Windows version)
if: github.event_name != 'release' && matrix.os != 'windows-latest'
run: echo "DEV_BUILD=$(cat devN.txt)" >> $GITHUB_ENV # for setup.py
- name: make dev build if not a release (Windows version)
if: github.event_name != 'release' && matrix.os == 'windows-latest'
run: ("DEV_BUILD=" + (get-content devN.txt)) >> $env:GITHUB_ENV # for setup.py
# downgraded to @v3 if using container: https://github.com/actions/checkout/issues/1487
- uses: actions/checkout@v3
if: matrix.container != ''
- uses: actions/checkout@v4
if: matrix.container == ''
- name: Mark workspace safe for git
# needed for container and self-hosted runners; see https://github.com/actions/checkout/issues/766
if: matrix.container != ''
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
# setuptool's bdist uses 'git archive' to find files, and fails silently if it can't,
# leading to missing files in the archive. Run it separately to force a failure in that case.
(cd scalene; git archive --prefix scalene/ HEAD | tar -t > /dev/null)
- name: select Xcode version
# MacOS > 14.2 requires Xcode >= 15.3; otherwise loading native extension modules fails with e.g.:
# dlopen(/opt/homebrew/lib/python3.11/site-packages/slipcover/probe.abi3.so, 0x0002): bad bind opcode 0x00
if: startsWith(matrix.os, 'macos-')
run: |
if [ -d /Applications/Xcode_15.3.app/Contents/Developer ]; then sudo xcode-select --switch /Applications/Xcode_15.3.app/Contents/Developer; fi
clang++ --version
g++ --version
- name: Set up python (script version)
if: matrix.container == ''
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python_version }}
- name: Set up python (container version)
if: matrix.container != ''
run: |
PYV=`echo "${{ matrix.python_version }}" | tr -d "."`; ls -d -1 /opt/python/cp$PYV*/bin | head -n 1 >> $GITHUB_PATH
cat $GITHUB_PATH
- name: Install dependencies
run: |
pip3 install --upgrade setuptools wheel twine build virtualenv
- name: Work around arm64 support on MacOS
# https://github.com/actions/virtual-environments/issues/2557
if: matrix.os == 'macos-latest'
run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*
- name: Install CMake on Windows
# CMake is required to build libscalene.dll for memory profiling on Windows
if: matrix.os == 'windows-latest'
run: choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y
- name: Build source dist
if: matrix.upload_source
run: make sdist
- name: Build binary dist
# Invoking with "bash -c" works around the "bash.exe: ... could not find /tmp" issue on Windows.
# The issue is somehow related to git providing a sh.exe (the "git shell")
# See eg https://help.appveyor.com/discussions/problems/1531-having-issues-with-configured-git-bash
run: bash -c "make bdist"
- name: Check that all required platforms are included
if: matrix.os == 'macos-latest'
run: |
for P in x86_64 arm64 arm64e; do
for F in build/lib.*/scalene/*.so ; do
file $F | grep -q "\\b$P\\b"
if [ $? != 0 ]; then
echo "$P missing"
exit 1
fi
done
done
- name: Check that libscalene.dll is included in Windows wheel
if: matrix.os == 'windows-latest'
shell: python
run: |
import zipfile
import glob
import sys
wheels = glob.glob('dist/*.whl')
if not wheels:
print("ERROR: No wheel files found")
sys.exit(1)
for whl in wheels:
print(f"Checking {whl}...")
with zipfile.ZipFile(whl, 'r') as z:
files = z.namelist()
dll_files = [f for f in files if 'libscalene.dll' in f]
if dll_files:
print(f" Found: {dll_files}")
else:
print(f" ERROR: libscalene.dll not found in wheel!")
print(f" Files in wheel: {[f for f in files if f.endswith(('.dll', '.pyd', '.so'))]}")
sys.exit(1)
print("All Windows wheels contain libscalene.dll")
- name: Non-release (dev) upload
if: github.event_name != 'release'
env:
TWINE_REPOSITORY: testpypi
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.TESTPYPI_TOKEN }}
run: twine upload --verbose dist/*
- name: Release upload
if: github.event_name == 'release'
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: twine upload --verbose dist/*
================================================
FILE: .github/workflows/codeql.yml
================================================
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: "28 9 * * 3"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ cpp, python ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v2
if: ${{ matrix.language == 'cpp' || matrix.language == 'python' }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{ matrix.language }}"
================================================
FILE: .github/workflows/run-linters.yml
================================================
name: linters
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
linters:
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
matrix:
os: [ ubuntu-latest, macos-latest ]
python: [ '3.9', '3.10', '3.11', '3.12', '3.13', '3.14' ]
steps:
- uses: actions/checkout@v4
- name: select Xcode version
# MacOS > 14.2 requires Xcode >= 15.3; otherwise loading native extension modules fails with e.g.:
# dlopen(/opt/homebrew/lib/python3.11/site-packages/slipcover/probe.abi3.so, 0x0002): bad bind opcode 0x00
if: startsWith(matrix.os, 'macos-')
run: |
if [ -d /Applications/Xcode_15.3.app/Contents/Developer ]; then sudo xcode-select --switch /Applications/Xcode_15.3.app/Contents/Developer; fi
clang++ --version
g++ --version
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Work around arm64 support on MacOS
# https://github.com/actions/virtual-environments/issues/2557
if: matrix.os == 'macos-latest'
run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install numpy
- name: Build scalene
run: pip -v install -e .
- name: install test dependencies
run: |
python3 -m pip install mypy ruff types-PyYAML
python3 -m pip install .
- name: Run linters
run: |
mypy scalene
ruff check scalene
================================================
FILE: .github/workflows/test-smoketests.yml
================================================
name: smoketests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch: # manual execution
jobs:
smoketests:
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
python: [ '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Work around arm64 support on MacOS
# https://github.com/actions/virtual-environments/issues/2557
if: matrix.os == 'macos-latest'
run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install numpy
- name: Build scalene
run: pip -v install -e .
- name: --off flag smoke test
# Verify that --off starts with profiling disabled and the program
# still runs to completion. This is the primary cross-platform test
# for the --on/--off lifecycle feature (issue #1009).
run: python -m scalene run --off --cpu-only test/testme.py
- name: cpu-only smoke test
run: python test/smoketest.py test/testme.py --cpu-only
- name: multiprocessing smoke test
if: matrix.os != 'windows-latest'
run: python test/smoketest.py test/multiprocessing_test.py
# NOTE: This test verifies that spawn-mode Pool.map completes under
# Scalene without hanging (regression test for #998). Uses a wrapper
# script with subprocess timeout because the multiprocessing resource
# tracker can hang during cleanup on some platforms.
- name: multiprocessing spawn pool smoke test
run: python test/smoketest_pool_spawn.py
timeout-minutes: 5
# Note: test/smoketest.py only handles single JSON, rather than multiple in sequence.
- name: profile-interval smoke test
run: python -m scalene run --profile-interval=2 test/testme.py && python -m scalene view --cli
# NOTE: The decorator smoke test relies on CPU signal sampling which
# doesn't work reliably on Windows CI (similar to the signal smoketest).
- name: decorator smoke test
if: matrix.os != 'windows-latest'
run: python test/smoketest_profile_decorator.py
# NOTE: this is a regression test for signals not being
# restarted properly. It checks whether the program
# halts or runs forever, not for correctness of timing.
- name: signal smoketest
if: matrix.os != 'windows-latest'
run: python test/smoketest.py test/signal_test.py
timeout-minutes: 0.5
# FIXME: these tests are broken under the current Github runner
#
# - name: line invalidation test
# run: python test/smoketest_line_invalidation.py
# Note: This test doesn't need to read an output,
# it is meant to determine if there is an ImportError
# or anything related if relative imports are used.
- name: -m invocation smoketest
run: |
python -m pip install git+https://github.com/sternj/import_stress_test
python -m scalene run --- -m import_stress_test && python -m scalene view --cli
================================================
FILE: .github/workflows/tests.yml
================================================
name: tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
run-tests:
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
matrix:
os: [ ubuntu-latest, macos-latest ]
python: [ '3.9', '3.10', '3.11', '3.12', '3.13', '3.14' ]
steps:
- uses: actions/checkout@v4
- name: select Xcode version
# MacOS > 14.2 requires Xcode >= 15.3; otherwise loading native extension modules fails with e.g.:
# dlopen(/opt/homebrew/lib/python3.11/site-packages/slipcover/probe.abi3.so, 0x0002): bad bind opcode 0x00
if: startsWith(matrix.os, 'macos-')
run: |
if [ -d /Applications/Xcode_15.3.app/Contents/Developer ]; then sudo xcode-select --switch /Applications/Xcode_15.3.app/Contents/Developer; fi
clang++ --version
g++ --version
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Work around arm64 support on MacOS
# https://github.com/actions/virtual-environments/issues/2557
if: matrix.os == 'macos-latest'
run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install numpy
- name: Build scalene
run: pip -v install -e .
- name: install test dependencies
run: |
python3 -m pip install pytest pytest-asyncio hypothesis
python3 -m pip install torch --index-url https://download.pytorch.org/whl/cpu
# Install JAX and TensorFlow for library profiler tests (Python < 3.13 only)
python3 -m pip install -e ".[test]" || python3 -m pip install -e .
- name: run tests
run: |
python3 -m pytest
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Created by https://www.gitignore.io/api/visualstudiocode
# Edit at https://www.gitignore.io/?templates=visualstudiocode
### VisualStudioCode ###
.vscode/* # Maybe .vscode/**/* instead - see comments
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
### VisualStudioCode Patch ###
# Ignore all local history of files
**/.history
# End of https://www.gitignore.io/api/visualstudiocode
.idea
scalene/libscalene.dylib
scalene/libscalene.dylib.dSYM/Contents/Info.plist
scalene/libscalene.dylib.dSYM/Contents/Resources/DWARF/libscalene.dylib
# Vendor is regenerated by `make`
vendor/
!vendor/README.md
# Node modules
node_modules/
================================================
FILE: .readthedocs.yaml
================================================
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.12"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
# fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
# python:
# install:
# - requirements: docs/requirements.txt
================================================
FILE: .vscode/c_cpp_properties.json
================================================
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**",
"/opt/homebrew/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/include/python3.9"
],
"defines": [],
"macFrameworkPath": [
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-arm64",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}
================================================
FILE: CITATION.cff
================================================
cff-version: 1.0.0
message: "If you use or refer to Scalene, please cite it as below."
authors:
- family-names: "Berger"
given-names: "Emery D."
orcid: "https://orcid.org/0000-0002-3222-3271"
- family-names: "Altmayer Pizzorno"
given-names: "Juan"
orcid: "https://orcid.org/0000-0002-1891-2919"
- family-names: "Stern"
given-names: "Sam"
title: "Scalene: a high-performance, high-precision CPU, GPU, and memory profiler for Python"
version: 1.5.9
date-released: 2022-07-24
url: "https://github.com/plasma-umass/scalene"
preferred-citation:
type: conference-paper
authors:
- family-names: "Berger"
given-names: "Emery D."
orcid: "https://orcid.org/0000-0002-3222-3271"
- family-names: "Stern"
given-names: "Sam"
- family-names: "Altmayer Pizzorno"
given-names: "Juan"
orcid: "https://orcid.org/0000-0002-1891-2919"
journal: "17th USENIX Symposium on Operating Systems Design and Implementation (OSDI 2023)"
month: 7
start: 51 # First page number
end: 64 # Last page number
title: "Triangulating Python Performance Issues with Scalene"
year: 2023
================================================
FILE: CLAUDE.md
================================================
# Scalene Development Guide
## Project Overview
Scalene is a high-performance CPU, GPU, and memory profiler for Python with AI-powered optimization proposals. It runs significantly faster than other Python profilers while providing detailed performance information. See the paper `docs/osdi23-berger.pdf` for technical details on Scalene's design.
**Key features:**
- CPU, GPU (NVIDIA/Apple), and memory profiling
- AI-powered optimization suggestions (OpenAI, Anthropic, Azure, Amazon Bedrock, Gemini, Ollama)
- Web-based GUI and CLI interfaces
- Jupyter notebook support via magic commands (`%scrun`, `%%scalene`)
- Line-by-line profiling with low overhead
- Separates Python time from native/C time
**Platform support:** Linux, macOS, WSL 2 (full support); Windows (partial support)
## Build & Test Commands
```bash
# Install in development mode
pip install -e .
# Run all tests
python3 -m pytest tests/
# Run tests for a specific Python version
python3.X -m pytest tests/
# Run linters
mypy scalene
ruff check scalene
# Run a single test file
python3 -m pytest tests/test_coverup_83.py -v
```
## Project Structure
### Core Profiler Components (`scalene/`)
- **`scalene_profiler.py`** - Main profiler class (`Scalene`). Entry point for profiling. Uses signal-based sampling for CPU profiling. Coordinates all profiling subsystems.
- **`scalene_statistics.py`** - `ScaleneStatistics` class. Collects and aggregates profiling data. Key types: `ProfilingSample`, `MemcpyProfilingSample`. Uses `RunningStats` for statistical aggregation.
- **`scalene_output.py`** - Profile output formatting for CLI/HTML
- **`scalene_json.py`** - `ScaleneJSON` class for JSON output format
- **`scalene_analysis.py`** - Profile analysis logic
### Entry Points
- **`__main__.py`** - Entry point for `python -m scalene`
- **`profile.py`** - Entry point for `--on`/`--off` control of background profiling
### Configuration & Arguments
- **`scalene_config.py`** - Version info (`scalene_version`, `scalene_date`) and constants:
- `SCALENE_PORT = 11235` - Default port for web UI
- `NEWLINE_TRIGGER_LENGTH` - Must match `src/include/sampleheap.hpp`
- **`scalene_arguments.py`** - `ScaleneArguments` class (extends `argparse.Namespace`) with all profiler options and their defaults defined in `ScaleneArgumentsDict`
- **`scalene_parseargs.py`** - `ScaleneParseArgs.parse_args()` builds the argument parser. `RichArgParser` provides colored help output (uses Rich on Python < 3.14, native argparse colors on 3.14+)
### Signal Handling
- **`scalene_signals.py`** - Signal definitions for CPU sampling
- **`scalene_signal_manager.py`** - Manages signal handlers
- **`scalene_sigqueue.py`** - Signal queue management
- **`scalene_client_timer.py`** - Timer for periodic profiling
### GPU Support
- **`scalene_nvidia_gpu.py`** - NVIDIA GPU profiling via `pynvml`
- **`scalene_apple_gpu.py`** - Apple GPU profiling (Metal)
- **`scalene_accelerator.py`** - Generic accelerator interface
- **`scalene_neuron.py`** - AWS Neuron support
### Memory Profiling
- **`scalene_memory_profiler.py`** - Memory profiling logic
- **`scalene_leak_analysis.py`** - Memory leak detection (experimental, `--memory-leak-detector`)
- **`scalene_mapfile.py`** - `ScaleneMapFile` for memory-mapped communication with native extension
- **`scalene_preload.py`** - Sets up `LD_PRELOAD`/`DYLD_INSERT_LIBRARIES` for native memory tracking
### Jupyter Integration
- **`scalene_magics.py`** - Jupyter magic commands (`%scrun` for line mode, `%%scalene` for cell mode)
- **`scalene_jupyter.py`** - Jupyter notebook support utilities
### Replacement Modules (`replacement_*.py`)
These modules monkey-patch standard library functions to capture profiling data during blocking operations:
- **`replacement_fork.py`** - Tracks `os.fork()`
- **`replacement_exit.py`** - Tracks `sys.exit()`
- **`replacement_lock.py`**, **`replacement_mp_lock.py`**, **`replacement_sem_lock.py`** - Lock acquisition timing
- **`replacement_thread_join.py`**, **`replacement_pjoin.py`** - Thread/process join timing
- **`replacement_signal_fns.py`** - Signal function replacements
- **`replacement_poll_selector.py`** - I/O polling timing
- **`replacement_get_context.py`** - Multiprocessing context
### Utilities
- **`runningstats.py`** - `RunningStats` class for online statistical calculations (mean, variance)
- **`scalene_funcutils.py`** - Function utilities
- **`scalene_utility.py`** - General utilities
- **`sparkline.py`** - Sparkline generation for memory visualization
- **`syntaxline.py`** - Syntax-highlighted source code lines
- **`adaptive.py`** - Adaptive sampling logic
- **`time_info.py`** - Time measurement utilities
- **`sorted_reservoir.py`** - Reservoir sampling for bounded-size sample collection
### GUI (`scalene/scalene-gui/`)
Web-based GUI built with TypeScript, bundled with esbuild.
**Core Files:**
- **`index.html.template`** - Jinja2 template for main GUI page (rendered by `scalene_utility.py`)
- **`scalene-gui.ts`** - Main TypeScript entry point, UI event handlers, initialization
- **`scalene-gui-bundle.js`** - Bundled JavaScript output (generated, do not edit directly)
**AI Provider Modules:**
- **`openai.ts`** - OpenAI API integration (`sendPromptToOpenAI`, `fetchOpenAIModels`)
- **`anthropic.ts`** - Anthropic Claude API integration
- **`gemini.ts`** - Google Gemini API integration (`sendPromptToGemini`, `fetchGeminiModels`)
- **`optimizations.ts`** - Provider dispatch logic, prompt generation
- **`persistence.ts`** - localStorage persistence with environment variable fallbacks
**Support Files:**
- **`launchbrowser.py`** - Opens browser to GUI (default port 11235)
- **`find_browser.py`** - Cross-platform browser detection
**Vendored Assets (for offline support):**
- **`jquery-3.6.0.slim.min.js`** - jQuery (vendored locally, not loaded from CDN)
- **`bootstrap.min.css`** - Bootstrap 5.1.3 CSS
- **`bootstrap.bundle.min.js`** - Bootstrap 5.1.3 JS with Popper
- **`prism.css`** - Syntax highlighting styles
- **`favicon.ico`** - Scalene favicon
- **`scalene-image.png`** - Scalene logo
These assets are copied to a temp directory when serving via HTTP, enabling the GUI to work in air-gapped/offline environments.
**Building the GUI:**
```bash
cd scalene/scalene-gui
npx esbuild scalene-gui.ts --bundle --outfile=scalene-gui-bundle.js --format=iife --global-name=ScaleneGUI
```
### Native Extensions (`src/`)
C++ code for low-overhead memory allocation tracking:
**Headers (`src/include/`):**
- **`sampleheap.hpp`** - Sampling heap allocator. Key constant `NEWLINE` must match Python config.
- **`memcpysampler.hpp`** - Intercepts `memcpy` to track copy volume
- **`pywhere.hpp`** - Tracks Python file/line info for allocations
- **`samplefile.hpp`** - File-based communication with Python
- **`sampler.hpp`**, **`poissonsampler.hpp`**, **`thresholdsampler.hpp`** - Sampling strategies
- **`scaleneheader.hpp`** - Common header definitions
**Sources (`src/source/`):**
- **`libscalene.cpp`** - Main native library (loaded via `LD_PRELOAD`)
- **`pywhere.cpp`** - Python location tracking implementation
- **`get_line_atomic.cpp`** - Atomic line number access
- **`traceconfig.cpp`** - Trace configuration
### Vendor Libraries (`vendor/`)
- **`Heap-Layers/`** - Memory allocator infrastructure (by Emery Berger)
- **`printf/`** - Async-signal-safe printf implementation
## Key Patterns
### Python Version Compatibility
The codebase supports Python 3.8-3.14. Version-specific code uses:
```python
if sys.version_info >= (3, 14):
# Python 3.14+ specific code
else:
# Older Python versions
```
**Type Annotation Compatibility (Python 3.8/3.9):**
- **Do NOT use `X | Y` union syntax** in runtime-evaluated annotations (PEP 604 requires Python 3.10+). Use `Optional[X]` or `Union[X, Y]` from `typing` instead.
- **Do NOT use `list[X]`, `dict[K, V]`, `tuple[X, ...]`** in runtime-evaluated annotations (PEP 585 lowercase generics require Python 3.9+). Use `List`, `Dict`, `Tuple` from `typing` for 3.8 support.
- Adding `from __future__ import annotations` makes all annotations strings (not evaluated at runtime), which allows modern syntax on older Python. However, this can break code that inspects annotations at runtime (e.g., dataclasses, pydantic).
- The safest approach for this codebase: use `typing.Optional`, `typing.Union`, `typing.List`, `typing.Tuple`, `typing.Dict` in all annotation positions that are evaluated at runtime (function signatures, variable annotations outside `if TYPE_CHECKING` blocks).
**Python 3.13 Changes (`dis` module):**
- `dis.Instruction.starts_line` changed from `int | None` (line number) to `bool`
- New `dis.Instruction.line_number` attribute (`int | None`) added for the actual line number
- On Python < 3.13, `starts_line` is only set on the **first** instruction of each source line; use a line-tracking loop to propagate line numbers to subsequent instructions
**Bytecode/Opcode Compatibility (`dis` module):**
- **Never match specific opcode names** (e.g., `JUMP_BACKWARD`, `JUMP_ABSOLUTE`, `POP_JUMP_IF_TRUE`). Opcode names change across Python versions — for example, Python 3.10 while loops use `POP_JUMP_IF_TRUE` for backward jumps, Python 3.11+ uses `JUMP_BACKWARD`, and `JUMP_ABSOLUTE` was removed in 3.12.
- **Always use abstract `dis` module categories** when possible: `dis.hasjabs` (absolute jump opcodes), `dis.hasjrel` (relative jump opcodes), `dis.hasconst`, `dis.hasname`, etc. These are maintained by CPython and work across all versions.
- For call detection, matching `opname.startswith("CALL")` is acceptable since that prefix has been stable, but prefer opcode integer sets over name strings for hot paths.
- When checking jump direction (forward vs backward), use `instr.argval` (which `dis` resolves to an absolute offset) and compare against `instr.offset`, rather than relying on opcode names to imply direction.
**Python 3.14 Changes:**
- `argparse` now has built-in colored help output (`color=True` parameter)
- `RichArgParser` uses Rich for colors on Python < 3.14, native argparse colors on 3.14+
### Argument Parsing (`scalene_parseargs.py`)
```python
class RichArgParser(argparse.ArgumentParser):
"""ArgumentParser that uses Rich for colored output on Python < 3.14."""
def __init__(self, *args, **kwargs):
if sys.version_info < (3, 14):
from rich.console import Console
self._console = Console()
else:
self._console = None
super().__init__(*args, **kwargs)
```
The `_colorize_help_for_rich()` function applies Python 3.14-style colors using Rich markup:
- `usage:` and `options:` → bold blue
- Program name → bold magenta
- Long options (`--foo`) → bold cyan
- Short options (`-h`) → bold green
- Metavars (`FOO`) → bold yellow
### GUI Patterns
**Preventing Browser Password Prompts:**
Use `autocomplete="one-time-code"` on password/API key inputs to prevent browsers from offering to save them:
```html
```
**Show/Hide Password Toggle:**
```typescript
function togglePassword(inputId: string, button: HTMLButtonElement): void {
const input = document.getElementById(inputId) as HTMLInputElement;
if (input.type === "password") {
input.type = "text";
button.textContent = "Hide";
} else {
input.type = "password";
button.textContent = "Show";
}
}
```
**Provider Field Visibility:**
Use CSS classes to show/hide provider-specific fields:
```typescript
function toggleServiceFields(): void {
const service = (document.getElementById("service") as HTMLSelectElement).value;
// Hide all provider sections
document.querySelectorAll(".provider-section").forEach((el) => {
(el as HTMLElement).style.display = "none";
});
// Show selected provider section
const section = document.querySelector(`.${service}-fields`);
if (section) (section as HTMLElement).style.display = "block";
}
```
**Persistent Form Elements:**
Add class `persistent` to inputs that should be saved/restored from localStorage:
```html
```
The `persistence.ts` module handles save/restore automatically.
**Standalone HTML Generation:**
The `generate_html()` function in `scalene_utility.py` supports a `standalone` parameter:
- When `standalone=False` (default): Assets are referenced as local files (e.g., `
{% else %}
{% endif %}
```
### Module Imports
When importing submodules, be explicit:
```python
# Correct - mypy can verify this
import importlib.util
importlib.util.find_spec(mod_name)
# Wrong - mypy error: Module has no attribute "util"
import importlib
importlib.util.find_spec(mod_name)
```
## Testing
### Test Files (`tests/`)
- **`test_coverup_*.py`** - Auto-generated coverage tests
- **`test_runningstats.py`** - Statistics tests (requires `hypothesis`)
- **`test_scalene_json.py`** - JSON output tests (requires `hypothesis`)
- **`test_nested_package_relative_import.py`** - Import handling tests
### Test Dependencies
```bash
pip install pytest pytest-asyncio hypothesis
```
### Running Tests Across Python Versions
```bash
for v in 3.9 3.10 3.11 3.12 3.13 3.14; do
python$v -m pytest tests/test_coverup_83.py -v
done
```
### Flaky Smoketests
The smoketests in `test/` can be flaky due to timing/sampling issues inherent to profiling:
- **"No non-zero lines in X"** - The profiler didn't collect enough samples. This happens when the test runs too quickly or signal delivery timing varies.
- **"Expected function 'X' not returned"** - A function wasn't sampled. Common with short-running functions.
These failures are usually timing-related and pass on re-run. They're more common on CI due to variable machine load.
### Port Binding in Tests
When testing port availability, never use hardcoded ports - they may already be in use on CI runners:
```python
# Bad - port 49200 might be in use
port = 49200
sock.bind(("", port))
# Good - find an available port first
port = find_available_port(49200, 49300)
if port is None:
return # Skip test if no ports available
sock.bind(("", port))
```
## CI/CD (`.github/workflows/`)
- **`run-linters.yml`** - Runs mypy and ruff on Python 3.9-3.14
- **`tests.yml`** - Runs pytest on Python 3.9-3.14
- **`build-and-upload.yml`** - Build and publish to PyPI
## Common Tasks
### Adding a New CLI Option
1. Add default value in `scalene_arguments.py`:
```python
class ScaleneArgumentsDict(TypedDict, total=False):
my_option: bool
```
2. Add argument in `scalene_parseargs.py`:
```python
parser.add_argument(
"--my-option",
dest="my_option",
action="store_true",
default=defaults.my_option,
help="Description of option",
)
```
### Adding a New AI Provider
1. **Create provider module** (`scalene/scalene-gui/newprovider.ts`):
```typescript
export async function sendPromptToNewProvider(
prompt: string,
apiKey: string
): Promise {
// API call implementation
}
export async function fetchNewProviderModels(apiKey: string): Promise {
// Optional: fetch available models from API
}
```
2. **Update `optimizations.ts`**:
- Import the new module
- Add case in `sendPromptToService()` switch statement
3. **Update `index.html.template`**:
- Add option to `#service` select dropdown
- Add provider section with API key input, model selector, etc.
- Add CSS for `.newprovider-fields` visibility
4. **Update `scalene-gui.ts`**:
- Add provider to `toggleServiceFields()` function
- Add refresh handler if dynamic model fetching is supported
- Update `getDefaultProvider()` if env var support is needed
5. **Update `persistence.ts`** (for env var support):
- Add mapping in `envKeyMap` for new fields
6. **Update `scalene_utility.py`**:
- Read environment variable in `api_keys` dict
- Pass to template rendering
7. **Rebuild the bundle**:
```bash
cd scalene/scalene-gui
npx esbuild scalene-gui.ts --bundle --outfile=scalene-gui-bundle.js --format=iife --global-name=ScaleneGUI
```
### Environment Variable API Keys
The GUI supports prepopulating API keys from environment variables:
| Element ID | Environment Variable | Provider |
|------------|---------------------|----------|
| `api-key` | `OPENAI_API_KEY` | OpenAI |
| `anthropic-api-key` | `ANTHROPIC_API_KEY` | Anthropic |
| `gemini-api-key` | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | Gemini |
| `azure-api-key` | `AZURE_OPENAI_API_KEY` | Azure OpenAI |
| `azure-api-url` | `AZURE_OPENAI_ENDPOINT` | Azure OpenAI |
| `aws-access-key` | `AWS_ACCESS_KEY_ID` | Amazon Bedrock |
| `aws-secret-key` | `AWS_SECRET_ACCESS_KEY` | Amazon Bedrock |
| `aws-region` | `AWS_DEFAULT_REGION` or `AWS_REGION` | Amazon Bedrock |
**Flow:**
1. `scalene_utility.py` reads env vars and passes to Jinja2 template
2. Template injects `envApiKeys` JavaScript object into page
3. `persistence.ts` uses env vars as fallbacks when localStorage is empty
### Updating Version
Edit `scalene/scalene_config.py`:
```python
scalene_version = "X.Y.Z"
scalene_date = "YYYY.MM.DD"
```
## Dependencies
Key runtime dependencies:
- `rich` - Terminal formatting and colors
- `cloudpickle` - Serialization
- `pynvml` - NVIDIA GPU support (optional)
See `requirements.txt` for full list.
## CLI Structure
Scalene uses a verb-based CLI with two main subcommands:
```bash
# Profile a program (saves to scalene-profile.json by default)
scalene run [options] yourprogram.py
# View an existing profile
scalene view [options] [profile.json]
```
### Run Subcommand Options
```bash
scalene run prog.py # profile, save to scalene-profile.json
scalene run -o my.json prog.py # save to custom file
scalene run --cpu-only prog.py # profile CPU only (faster)
scalene run -c config.yaml prog.py # load options from config file
scalene run prog.py --- --arg # pass args to program
```
### View Subcommand Options
```bash
scalene view # open in browser
scalene view --cli # view in terminal
scalene view --html # save to scalene-profile.html
scalene view --standalone # save as self-contained HTML (all assets embedded)
scalene view myprofile.json # open specific profile
```
### Profile Completion Message
After profiling completes, Scalene prints instructions for viewing the profile:
```
Scalene: profile saved to scalene-profile.json
To view in browser: scalene view
To view in terminal: scalene view --cli
```
The filename is only included in the command if a non-default output file was used.
### YAML Configuration
Create a `scalene.yaml` file with options:
```yaml
outfile: my-profile.json
cpu-only: true
profile-only: "mypackage,utils"
cpu-percent-threshold: 5
```
Load with: `scalene run -c scalene.yaml prog.py`
### Advanced Options
Use `scalene run --help-advanced` to see all options including:
- `--profile-all` - profile all code, not just the target program
- `--profile-only PATH` - only profile files containing these strings
- `--profile-exclude PATH` - exclude files containing these strings
- `--profile-system-libraries` - profile Python stdlib and installed packages (skipped by default)
- `--gpu` - profile GPU time and memory
- `--memory` - profile memory usage
- `--stacks` - collect stack traces
- `--profile-interval N` - output profiles every N seconds
### Smoke Tests
Smoke tests in `test/` use the new CLI syntax:
```python
# test/smoketest.py
cmd = [sys.executable, "-m", "scalene", "run", "-o", str(outfile), *rest, fname]
```
### GitHub Workflows
Workflows in `.github/workflows/` use the new CLI:
```yaml
# Profile with interval, then view
- run: python -m scalene run --profile-interval=2 test/testme.py && python -m scalene view --cli
# Profile with module invocation
- run: python -m scalene run --- -m import_stress_test && python -m scalene view --cli
```
## Signal Handling
Scalene uses several Unix signals for profiling. The signal assignments are in `scalene_signals.py`:
| Signal | Purpose | Platform |
|--------|---------|----------|
| `SIGVTALRM` | CPU profiling timer (default) | Unix |
| `SIGALRM` | CPU profiling timer (real time mode) | Unix |
| `SIGILL` | Start profiling (`--on`) | Unix |
| `SIGBUS` | Stop profiling (`--off`) | Unix |
| `SIGPROF` | memcpy tracking | Unix |
| `SIGXCPU` | malloc tracking | Unix |
| `SIGXFSZ` | free tracking | Unix |
### Signal Conflicts with Libraries
Libraries like PyTorch Lightning may also use these signals. The `replacement_signal_fns.py` module handles conflicts:
**On Linux:** Uses real-time signals (`SIGRTMIN+1` to `SIGRTMIN+5`) for redirection. When user code sets a handler for a Scalene signal, their handler is redirected to a real-time signal. Calls to `raise_signal()` and `kill()` are also redirected transparently.
**On macOS/other platforms:** Uses handler chaining. Both Scalene's handler and the user's handler are called when the signal fires.
```python
# Platform-specific signal handling
_use_rt_signals = sys.platform == "linux" and hasattr(signal, "SIGRTMIN")
if _use_rt_signals:
# Linux: redirect to real-time signals
rt_base = signal.SIGRTMIN + 1
_signal_redirects[signal.SIGILL] = rt_base
else:
# macOS: chain handlers
def chained_handler(sig, frame):
scalene_handler(sig, frame)
user_handler(sig, frame)
```
### Frame Line Number Can Be None (Python 3.11+)
In Python 3.11+, `frame.f_lineno` can be `None` in edge cases (e.g., during multiprocessing cleanup). Always use a fallback:
```python
lineno = frame.f_lineno if frame.f_lineno is not None else frame.f_code.co_firstlineno
```
## Native Extension Build Issues
### C++ Standard Library Conflicts with vendor/printf
The `vendor/printf/printf.h` header defines macros that conflict with C++ standard library:
```c
#define vsnprintf vsnprintf_
#define snprintf snprintf_
```
This breaks `std::vsnprintf` in `` and other headers. **Fix:** Include C++ standard headers BEFORE vendor headers in `src/source/libscalene.cpp`:
```cpp
// Include C++ standard headers FIRST
#include
#include
// Then vendor headers that define conflicting macros
#include // Eventually includes printf.h
```
## Profiling Guide
See [Scalene-Agents.md](Scalene-Agents.md) for detailed information about interpreting Scalene's profiling output, including Python vs C time, memory metrics, and optimization strategies.
## Debugging Guide
See [Scalene-Debugging.md](Scalene-Debugging.md) for signal handler debugging, async profiling debugging, the profile output pipeline (three separate renderers!), and unbounded growth prevention patterns.
## GUI Development Guide
See [Scalene-GUI.md](Scalene-GUI.md) for adding new columns, Vega-Lite chart types, pie chart best practices (two-wedge rendering, rotating pies), and the chart rendering flow.
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.15)
project(scalene VERSION 1.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# FetchContent for downloading dependencies
include(FetchContent)
# Fetch Heap-Layers (required for all platforms)
set(HEAP_LAYERS_DIR "${CMAKE_SOURCE_DIR}/vendor/Heap-Layers")
if(NOT EXISTS "${HEAP_LAYERS_DIR}/heaplayers.h")
message(STATUS "Fetching Heap-Layers...")
FetchContent_Declare(
heap_layers
GIT_REPOSITORY https://github.com/emeryberger/Heap-Layers.git
GIT_TAG master
GIT_SHALLOW TRUE
SOURCE_DIR ${HEAP_LAYERS_DIR}
)
FetchContent_MakeAvailable(heap_layers)
endif()
# Fetch printf library (required for all platforms)
set(PRINTF_DIR "${CMAKE_SOURCE_DIR}/vendor/printf")
if(NOT EXISTS "${PRINTF_DIR}/printf.cpp")
message(STATUS "Fetching printf library...")
FetchContent_Declare(
printf_lib
GIT_REPOSITORY https://github.com/mpaland/printf.git
GIT_TAG master
GIT_SHALLOW TRUE
SOURCE_DIR ${PRINTF_DIR}
)
FetchContent_MakeAvailable(printf_lib)
# Create printf.cpp symlink/copy from printf.c
if(WIN32)
file(COPY "${PRINTF_DIR}/printf.c" DESTINATION "${PRINTF_DIR}")
file(RENAME "${PRINTF_DIR}/printf.c" "${PRINTF_DIR}/printf.cpp")
# Actually we need to keep both, so copy instead
file(READ "${PRINTF_DIR}/printf.c" PRINTF_CONTENT)
file(WRITE "${PRINTF_DIR}/printf.cpp" "${PRINTF_CONTENT}")
else()
execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink printf.c printf.cpp
WORKING_DIRECTORY ${PRINTF_DIR}
)
endif()
# Patch printf.h to comment out the macro definitions
file(READ "${PRINTF_DIR}/printf.h" PRINTF_H_CONTENT)
string(REPLACE "#define printf printf_" "//#define printf printf_" PRINTF_H_CONTENT "${PRINTF_H_CONTENT}")
string(REPLACE "#define vsnprintf vsnprintf_" "//#define vsnprintf vsnprintf_" PRINTF_H_CONTENT "${PRINTF_H_CONTENT}")
file(WRITE "${PRINTF_DIR}/printf.h" "${PRINTF_H_CONTENT}")
endif()
# Find Python
find_package(Python3 REQUIRED COMPONENTS Development)
# Detect architecture
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64")
set(SCALENE_ARCH "ARM64")
message(STATUS "Building for ARM64 architecture")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|x86_64")
set(SCALENE_ARCH "X64")
message(STATUS "Building for x86-64 architecture")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i[3-6]86|x86")
set(SCALENE_ARCH "X86")
message(STATUS "Building for x86 architecture")
else()
message(WARNING "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
set(SCALENE_ARCH "UNKNOWN")
endif()
# Common include directories
set(SCALENE_INCLUDES
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/src/include
${CMAKE_SOURCE_DIR}/vendor/Heap-Layers
${CMAKE_SOURCE_DIR}/vendor/Heap-Layers/heaps
${CMAKE_SOURCE_DIR}/vendor/Heap-Layers/heaps/threads
${CMAKE_SOURCE_DIR}/vendor/Heap-Layers/heaps/utility
${CMAKE_SOURCE_DIR}/vendor/Heap-Layers/wrappers
${CMAKE_SOURCE_DIR}/vendor/Heap-Layers/utility
${CMAKE_SOURCE_DIR}/vendor/printf
${Python3_INCLUDE_DIRS}
)
# Platform-specific configuration
if(WIN32)
# Windows build
message(STATUS "Configuring Windows build")
# Download Microsoft Detours for native malloc/free hooking
FetchContent_Declare(
detours
GIT_REPOSITORY https://github.com/microsoft/Detours.git
GIT_TAG main
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(detours)
# Microsoft Detours sources
set(DETOURS_SOURCES
${detours_SOURCE_DIR}/src/detours.cpp
${detours_SOURCE_DIR}/src/modules.cpp
${detours_SOURCE_DIR}/src/disasm.cpp
${detours_SOURCE_DIR}/src/image.cpp
${detours_SOURCE_DIR}/src/creatwth.cpp
)
# Add architecture-specific disassembler
if(SCALENE_ARCH STREQUAL "ARM64")
list(APPEND DETOURS_SOURCES ${detours_SOURCE_DIR}/src/disolarm64.cpp)
message(STATUS "Using ARM64 Detours disassembler")
elseif(SCALENE_ARCH STREQUAL "X64")
list(APPEND DETOURS_SOURCES ${detours_SOURCE_DIR}/src/disolx64.cpp)
message(STATUS "Using x64 Detours disassembler")
elseif(SCALENE_ARCH STREQUAL "X86")
list(APPEND DETOURS_SOURCES ${detours_SOURCE_DIR}/src/disolx86.cpp)
message(STATUS "Using x86 Detours disassembler")
endif()
add_library(scalene SHARED
src/source/libscalene_windows.cpp
vendor/printf/printf.cpp
${DETOURS_SOURCES}
)
target_include_directories(scalene PRIVATE
${SCALENE_INCLUDES}
${detours_SOURCE_DIR}/src
)
target_compile_definitions(scalene PRIVATE
WIN32_LEAN_AND_MEAN
_REENTRANT=1
NDEBUG
HL_USE_XXREALLOC=1
SCALENE_LIBSCALENE_BUILD=1
_CRT_SECURE_NO_WARNINGS=1
)
target_compile_options(scalene PRIVATE
/W3
/O2
/EHsc
)
target_link_libraries(scalene PRIVATE
kernel32
user32
psapi
${Python3_LIBRARIES}
)
# Output to scalene directory (without Release/Debug subdirectory)
set_target_properties(scalene PROPERTIES
OUTPUT_NAME "libscalene"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/scalene"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/scalene"
# Prevent MSBuild from adding configuration subdirectories
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/scalene"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}/scalene"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/scalene"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}/scalene"
)
elseif(APPLE)
# macOS build
message(STATUS "Configuring macOS build")
add_library(scalene SHARED
src/source/libscalene.cpp
vendor/Heap-Layers/wrappers/macwrapper.cpp
vendor/printf/printf.cpp
)
target_include_directories(scalene PRIVATE ${SCALENE_INCLUDES})
target_compile_definitions(scalene PRIVATE
_REENTRANT=1
NDEBUG
HL_USE_XXREALLOC=1
)
target_compile_options(scalene PRIVATE
-Wall
-O3
-fno-builtin-malloc
-fvisibility=hidden
-flto
-ftls-model=initial-exec
-ftemplate-depth=1024
)
# Universal binary support (x86_64 and arm64)
if(CMAKE_OSX_ARCHITECTURES)
# Use specified architectures
else()
# Default to native architecture
set(CMAKE_OSX_ARCHITECTURES "${CMAKE_SYSTEM_PROCESSOR}")
endif()
target_link_libraries(scalene PRIVATE
dl
pthread
)
set_target_properties(scalene PROPERTIES
OUTPUT_NAME "scalene"
PREFIX "lib"
SUFFIX ".dylib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/scalene"
)
else()
# Linux build
message(STATUS "Configuring Linux build")
add_library(scalene SHARED
src/source/libscalene.cpp
vendor/Heap-Layers/wrappers/gnuwrapper.cpp
vendor/printf/printf.cpp
)
target_include_directories(scalene PRIVATE
${SCALENE_INCLUDES}
/usr/include/nptl
)
target_compile_definitions(scalene PRIVATE
_REENTRANT=1
NDEBUG
HL_USE_XXREALLOC=1
)
target_compile_options(scalene PRIVATE
-Wall
-O3
-pipe
-fno-builtin-malloc
-fvisibility=hidden
-fPIC
-Bsymbolic
)
target_link_libraries(scalene PRIVATE
dl
pthread
)
set_target_properties(scalene PROPERTIES
OUTPUT_NAME "scalene"
PREFIX "lib"
SUFFIX ".so"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/scalene"
)
endif()
# Installation
install(TARGETS scalene
LIBRARY DESTINATION scalene
RUNTIME DESTINATION scalene
)
# Custom target for vendored dependencies (now handled automatically via FetchContent)
add_custom_target(vendor-deps
COMMAND ${CMAKE_COMMAND} -E echo "Vendor dependencies are managed automatically via FetchContent."
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at Emery.berger@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: GNUmakefile
================================================
LIBNAME = scalene
PYTHON = python3
PYTHON_SOURCES = scalene/[a-z]*.py
JS_SOURCES = scalene/scalene-gui/*.js
C_SOURCES = src/source/*.cpp src/include/*.h*
.PHONY: black clang-format prettier format upload vendor-deps
# CXXFLAGS = -std=c++14 -g -O0 # FIXME
CXXFLAGS = -std=c++14 -Wall -g -O3 -DNDEBUG -D_REENTRANT=1 -DHL_USE_XXREALLOC=1 -pipe -fno-builtin-malloc -fvisibility=hidden -Wno-unused-result
# CXX = g++
INCLUDES = -Isrc -Isrc/include
INCLUDES := $(INCLUDES) -Ivendor/Heap-Layers -Ivendor/Heap-Layers/wrappers -Ivendor/Heap-Layers/utility
INCLUDES := $(INCLUDES) -Ivendor/printf
# python3-config may not be available in venv and such
INCLUDES := $(INCLUDES) -I$(shell python3 -c "import sysconfig; print(sysconfig.get_path('include'))")
ifeq ($(shell uname -s),Darwin)
LIBFILE := lib$(LIBNAME).dylib
WRAPPER := vendor/Heap-Layers/wrappers/macwrapper.cpp
ifneq (,$(filter $(shell uname -p),arm arm64)) # this means "if arm or arm64"
ARCH := -arch arm64 -arch arm64e
else
ARCH := -arch x86_64
endif
CXXFLAGS := -std=c++14 -Wall -g -O3 -DNDEBUG -D_REENTRANT=1 -DHL_USE_XXREALLOC=1 -pipe -fno-builtin-malloc -fvisibility=hidden -flto -ftls-model=initial-exec -ftemplate-depth=1024 $(ARCH) -compatibility_version 1 -current_version 1 -dynamiclib
SED_INPLACE = -i ''
else # non-Darwin
LIBFILE := lib$(LIBNAME).so
WRAPPER := vendor/Heap-Layers/wrappers/gnuwrapper.cpp
INCLUDES := $(INCLUDES) -I/usr/include/nptl
CXXFLAGS := $(CXXFLAGS) -fPIC -shared -Bsymbolic
RPATH_FLAGS :=
SED_INPLACE = -i
endif
SRC := src/source/lib$(LIBNAME).cpp $(WRAPPER) vendor/printf/printf.cpp
OUTDIR=scalene
all: $(OUTDIR)/$(LIBFILE)
$(OUTDIR)/$(LIBFILE): vendor-deps $(SRC) $(C_SOURCES) GNUmakefile
$(CXX) $(CXXFLAGS) $(INCLUDES) $(SRC) -o $(OUTDIR)/$(LIBFILE) -ldl -lpthread
clean:
rm -f $(OUTDIR)/$(LIBFILE) scalene/*.so scalene/*.dylib
rm -rf $(OUTDIR)/$(LIBFILE).dSYM
rm -rf scalene.egg-info
rm -rf build dist *egg-info
$(WRAPPER) : vendor/Heap-Layers
vendor/Heap-Layers:
mkdir -p vendor && cd vendor && git clone https://github.com/emeryberger/Heap-Layers
TMP := $(shell mktemp -d || echo /tmp)
vendor/printf/printf.cpp:
mkdir -p vendor && cd vendor && git clone https://github.com/mpaland/printf
cd vendor/printf && ln -s printf.c printf.cpp
sed -e 's/^#define printf printf_/\/\/&/' vendor/printf/printf.h > $(TMP)/printf.h.$$ && mv $(TMP)/printf.h.$$ vendor/printf/printf.h
sed -e 's/^#define vsnprintf vsnprintf_/\/\/&/' vendor/printf/printf.h > $(TMP)/printf.h.$$ && mv $(TMP)/printf.h.$$ vendor/printf/printf.h
vendor-deps: vendor/Heap-Layers vendor/printf/printf.cpp
mypy:
# Requires: pip install mypy types-PyYAML
-mypy $(PYTHON_SOURCES)
format: black clang-format prettier
clang-format:
-clang-format -i $(C_SOURCES) --style=google
black:
-black -l 79 $(PYTHON_SOURCES)
prettier:
-npx prettier -w $(JS_SOURCES)
bdist: vendor-deps
$(PYTHON) -m build --wheel
ifeq ($(shell uname -s),Linux)
auditwheel repair dist/*.whl
rm -f dist/*.whl
mv wheelhouse/*.whl dist/
endif
sdist: vendor-deps
$(PYTHON) -m build --sdist
upload: sdist bdist # to pypi
$(PYTHON) -m twine upload dist/*
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: MANIFEST.in
================================================
graft vendor/Heap-Layers
prune vendor/Heap-Layers/.git
graft vendor/printf
prune vendor/printf/.git
exclude scalene/old/*
================================================
FILE: Makefile
================================================
LIBNAME = scalene
PYTHON = python3
PYTHON_SOURCES = scalene/[a-z]*.py
C_SOURCES = src/source/get_line_atomic.cpp src/include/*.h* # src/source/libscalene.cpp
CXXFLAGS = /Ox /DNDEBUG /std:c++14 /Zi
CXX = cl
MAIN_INCLUDES = -Isrc -Isrc/include
INCLUDES = $(MAIN_INCLUDES) -Ivendor/Heap-Layers -Ivendor/Heap-Layers/wrappers -Ivendor/Heap-Layers/utility -Ivendor/printf
LIBFILE = lib$(LIBNAME).dll
WRAPPER = # vendor/Heap-Layers/wrappers/gnuwrapper.cpp
SRC = src/source/lib$(LIBNAME).cpp $(WRAPPER) vendor/printf/printf.cpp
all: # vendor-deps $(SRC) $(OTHER_DEPS)
# $(CXX) $(CXXFLAGS) $(INCLUDES) $(SRC) /o $(LIBFILE)
mypy:
# Requires: pip install mypy types-PyYAML
-mypy $(PYTHON_SOURCES)
format: black isort clang-format
clang-format:
-clang-format -i $(C_SOURCES) --style=google
isort:
-isort $(PYTHON_SOURCES)
black:
-black -l 79 $(PYTHON_SOURCES)
vendor/Heap-Layers:
cd vendor && git clone https://github.com/emeryberger/Heap-Layers
vendor/printf/printf.cpp:
cd vendor && git clone https://github.com/mpaland/printf
cd vendor\printf && copy printf.c printf.cpp
vendor-deps: clear-vendor-dirs vendor/Heap-Layers vendor/printf/printf.cpp
clear-vendor-dirs:
if exist vendor\ (rmdir /Q /S vendor)
mkdir vendor
pkg: vendor/Heap-Layers vendor/printf/printf.cpp
-rm -rf dist build *egg-info
$(PYTHON) setup.py sdist bdist_wheel
upload: pkg # to pypi
$(PYTHON) -m twine upload dist/*
================================================
FILE: Pipfile
================================================
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
numpy = "*"
pyperf = "*"
pytest = "*"
wheel = "*"
[packages]
cloudpickle = "*"
nvidia-ml-py = "*"
rich = "*"
wheel = "*"
================================================
FILE: README.md
================================================

# Scalene: a Python CPU+GPU+memory profiler with AI-powered optimization proposals
by [Emery Berger](https://emeryberger.com), [Sam Stern](https://samstern.me/), and [Juan Altmayer Pizzorno](https://github.com/jaltmayerpizzorno).
[](https://join.slack.com/t/scaleneprofil-jge3234/shared_invite/zt-110vzrdck-xJh5d4gHnp5vKXIjYD3Uwg)[Scalene community Slack](https://join.slack.com/t/scaleneprofil-jge3234/shared_invite/zt-110vzrdck-xJh5d4gHnp5vKXIjYD3Uwg)
[](https://pypi.org/project/scalene/)[](https://anaconda.org/conda-forge/scalene) [](https://pepy.tech/project/scalene)[](https://anaconda.org/conda-forge/scalene) [](https://pepy.tech/project/scalene) [](https://marketplace.visualstudio.com/items?itemName=EmeryBerger.scalene)  [](https://github.com/plasma-umass/scalene)

(tweet from Ian Ozsvald, author of [_High Performance Python_](https://smile.amazon.com/High-Performance-Python-Performant-Programming/dp/1492055026/ref=sr_1_1?crid=texbooks))

[_Python Profiler Links to AI to Improve Code Scalene identifies inefficiencies and asks GPT-4 for suggestions_](https://spectrum.ieee.org/python-programming), IEEE Spectrum
[Episode 172: Measuring Multiple Facets of Python Performance With Scalene](https://realpython.com/podcasts/rpp/172/), The Real Python podcast
***Scalene web-based user interface:*** [https://scalene-gui.github.io/scalene-gui/](https://scalene-gui.github.io/scalene-gui/)
## About Scalene
Scalene is a high-performance CPU, GPU *and* memory profiler for
Python that does a number of things that other Python profilers do not
and cannot do. It runs orders of magnitude faster than many other
profilers while delivering far more detailed information. It is also
the first profiler ever to incorporate AI-powered proposed
optimizations.
### AI-powered optimization suggestions
> **Note**
>
> For optimization suggestions, Scalene supports a variety of AI providers, including [Amazon Bedrock](https://aws.amazon.com/bedrock), [Microsoft Azure](https://azure.microsoft.com/en-us/), [OpenAI](https://openai.com), and local models via [Ollama](https://ollama.com/). To enable AI-powered optimization suggestions from AI providers, you need to select a provider and, if needed, enter your credentials, in the box under "AI Optimization Options".
>
>
Once you've entered your key and any other needed data, click on the lightning bolt (⚡) beside any line or the explosion (💥) for an entire region of code to generate a proposed optimization. Click on a proposed optimization to copy it to the clipboard.
You can click as many times as you like on the lightning bolt or explosion, and it will generate different suggested optimizations. Your mileage may vary, but in some cases, the suggestions are quite impressive (e.g., order-of-magnitude improvements).
### Quick Start
#### Installing Scalene:
```console
python3 -m pip install -U scalene
```
or
```console
conda install -c conda-forge scalene
```
#### Using Scalene:
After installing Scalene, you can use Scalene at the command line, or as a Visual Studio Code extension.
Using the Scalene VS Code Extension:
First, install the Scalene extension from the VS Code Marketplace or by searching for it within VS Code by typing Command-Shift-X (Mac) or Ctrl-Shift-X (Windows). Once that's installed, click Command-Shift-P or Ctrl-Shift-P to open the Command Palette. Then select "Scalene: AI-powered profiling..." (you can start typing Scalene and it will pop up if it's installed). Run that and, assuming your code runs for at least a second, a Scalene profile will appear in a webview.
Commonly used command-line options:
Scalene uses a verb-based command structure with two main commands: `run` (to profile) and `view` (to display results).
```console
# Profile a program (saves to scalene-profile.json)
scalene run your_prog.py
python3 -m scalene run your_prog.py # equivalent alternative
# View a profile
scalene view # open profile in browser
scalene view --cli # view in terminal
scalene view --html # save to scalene-profile.html
scalene view --standalone # save as self-contained HTML
# Common profiling options
scalene run --cpu-only your_prog.py # only profile CPU (faster)
scalene run -o results.json your_prog.py # custom output filename
scalene run -c config.yaml your_prog.py # load options from config file
# Pass arguments to your program (use --- separator)
scalene run your_prog.py --- --arg1 --arg2
# Get help
scalene --help # main help
scalene run --help # profiling options
scalene run --help-advanced # advanced profiling options
scalene view --help # viewing options
```
Using a YAML configuration file:
You can store Scalene options in a YAML configuration file and load them with `-c` or `--config`:
```console
scalene run -c scalene.yaml your_prog.py
```
Example `scalene.yaml`:
```yaml
# Output options
outfile: my-profile.json
# Profiling mode (use only one)
cpu-only: true # CPU profiling only (faster)
# gpu: true # Include GPU profiling
# memory: true # Include memory profiling
# Filter what gets profiled
profile-only: "mypackage,mymodule" # Only profile these paths
profile-exclude: "tests,venv" # Exclude these paths
profile-all: false # Profile all code, not just target
# Performance tuning
cpu-percent-threshold: 1 # Min CPU% to report (default: 1)
cpu-sampling-rate: 0.01 # Sampling interval in seconds
malloc-threshold: 100 # Min allocations to report
# Other options
use-virtual-time: false # Measure CPU time only (not I/O)
stacks: false # Collect stack traces
memory-leak-detector: true # Detect likely memory leaks
```
Command-line arguments override config file settings.
Using Scalene programmatically in your code:
Invoke using `scalene` as above and then:
```Python
from scalene import scalene_profiler
# Turn profiling on
scalene_profiler.start()
# your code
# Turn profiling off
scalene_profiler.stop()
```
```Python
from scalene.scalene_profiler import enable_profiling
with enable_profiling():
# do something
```
Using Scalene to profile only specific functions via @profile:
Just preface any functions you want to profile with the `@profile` decorator and run it with Scalene:
```Python
# do not import profile!
@profile
def slow_function():
import time
time.sleep(3)
```
#### Web-based GUI
Scalene has both a CLI and a web-based GUI [(demo here)](https://scalene-gui.github.io/scalene-gui/).
By default, once Scalene has profiled your program, it will open a
tab in a web browser with an interactive user interface (all processing is done
locally). Hover over bars to see breakdowns of CPU and memory
consumption, and click on underlined column headers to sort the
columns. The GUI works fully offline with no internet connection required.
Use `scalene view --standalone` to generate a completely self-contained HTML file with all assets embedded, perfect for sharing or archiving.
[](https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/scalene-gui-example-full.png)
## Scalene Overview
### Scalene talk (PyCon US 2021)
[This talk](https://youtu.be/5iEf-_7mM1k) presented at PyCon 2021 walks through Scalene's advantages and how to use it to debug the performance of an application (and provides some technical details on its internals). We highly recommend watching this video!
[](https://youtu.be/5iEf-_7mM1k "Scalene presentation at PyCon 2021")
### Fast and Accurate
- Scalene is **_fast_**. It uses sampling instead of instrumentation or relying on Python's tracing facilities. Its overhead is typically no more than 10-20% (and often less).
- Scalene is **accurate**. We tested CPU profiler accuracy and found that Scalene is among the most accurate profilers, correctly measuring time taken.

- Scalene performs profiling **_at the line level_** _and_ **_per function_**, pointing to the functions and the specific lines of code responsible for the execution time in your program.
### CPU profiling
- Scalene **separates out time spent in Python from time in native code** (including libraries). Most Python programmers aren't going to optimize the performance of native code (which is usually either in the Python implementation or external libraries), so this helps developers focus their optimization efforts on the code they can actually improve.
- Scalene **highlights hotspots** (code accounting for significant percentages of CPU time or memory allocation) in red, making them even easier to spot.
- Scalene also separates out **system time**, making it easy to find I/O bottlenecks.
### GPU profiling
- Scalene reports **GPU time** (currently limited to NVIDIA-based systems).
### Memory profiling
- Scalene **profiles memory usage**. In addition to tracking CPU usage, Scalene also points to the specific lines of code responsible for memory growth. It accomplishes this via an included specialized memory allocator.
- Scalene separates out the percentage of **memory consumed by Python code vs. native code**.
- Scalene produces **_per-line_ memory profiles**.
- Scalene **identifies lines with likely memory leaks**.
- Scalene **profiles _copying volume_**, making it easy to spot inadvertent copying, especially due to crossing Python/library boundaries (e.g., accidentally converting `numpy` arrays into Python arrays, and vice versa).
### Other features
- Scalene can produce **reduced profiles** (via `--reduced-profile`) that only report lines that consume more than 1% of CPU or perform at least 100 allocations.
- Scalene supports `@profile` decorators to profile only specific functions.
- When Scalene is profiling a program launched in the background (via `&`), you can **suspend and resume profiling**.
# Comparison to Other Profilers
## Performance and Features
Below is a table comparing the **performance and features** of various profilers to Scalene.

- **Slowdown**: the slowdown when running a benchmark from the Pyperformance suite. Green means less than 2x overhead. Scalene's overhead is just a 35% slowdown.
Scalene has all of the following features, many of which only Scalene supports:
- **Lines or functions**: does the profiler report information only for entire functions, or for every line -- Scalene does both.
- **Unmodified Code**: works on unmodified code.
- **Threads**: supports Python threads.
- **Multiprocessing**: supports use of the `multiprocessing` library -- _Scalene only_
- **Python vs. C time**: breaks out time spent in Python vs. native code (e.g., libraries) -- _Scalene only_
- **System time**: breaks out system time (e.g., sleeping or performing I/O) -- _Scalene only_
- **Profiles memory**: reports memory consumption per line / function
- **GPU**: reports time spent on an NVIDIA GPU (if present) -- _Scalene only_
- **Memory trends**: reports memory use over time per line / function -- _Scalene only_
- **Copy volume**: reports megabytes being copied per second -- _Scalene only_
- **Detects leaks**: automatically pinpoints lines responsible for likely memory leaks -- _Scalene only_
## Output
If you include the `--cli` option, Scalene prints annotated source code for the program being profiled
(as text, JSON (`--json`), or HTML (`--html`)) and any modules it
uses in the same directory or subdirectories (you can optionally have
it `--profile-all` and only include files with at least a
`--cpu-percent-threshold` of time). Here is a snippet from
`pystone.py`.

* **Memory usage at the top**: Visualized by "sparklines", memory consumption over the runtime of the profiled code.
* **"Time Python"**: How much time was spent in Python code.
* **"native"**: How much time was spent in non-Python code (e.g., libraries written in C/C++).
* **"system"**: How much time was spent in the system (e.g., I/O).
* **"GPU"**: (not shown here) How much time spent on the GPU, if your system has an NVIDIA GPU installed.
* **"Memory Python"**: How much of the memory allocation happened on the Python side of the code, as opposed to in non-Python code (e.g., libraries written in C/C++).
* **"net"**: Positive net memory numbers indicate total memory allocation in megabytes; negative net memory numbers indicate memory reclamation.
* **"timeline / %"**: Visualized by "sparklines", memory consumption generated by this line over the program runtime, and the percentages of total memory activity this line represents.
* **"Copy (MB/s)"**: The amount of megabytes being copied per second (see "About Scalene").
## Scalene
The following command runs Scalene on a provided example program.
```console
scalene test/testme.py
```
Click to see all Scalene's options (available by running with --help)
```console
% scalene --help
Scalene: a high-precision CPU and memory profiler, version 1.5.51 (2025.01.29)
https://github.com/plasma-umass/scalene
commands:
run Profile a Python program (saves to scalene-profile.json)
view View an existing profile in browser or terminal
examples:
% scalene run your_program.py # profile, save to scalene-profile.json
% scalene view # view scalene-profile.json in browser
% scalene view --cli # view profile in terminal
in Jupyter, line mode:
%scrun [options] statement
in Jupyter, cell mode:
%%scalene [options]
your code here
% scalene run --help
Profile a Python program with Scalene.
examples:
% scalene run prog.py # profile, save to scalene-profile.json
% scalene run -o my.json prog.py # save to custom file
% scalene run --cpu-only prog.py # profile CPU only (faster)
% scalene run -c scalene.yaml prog.py # load options from config file
% scalene run prog.py --- --arg # pass args to program
% scalene run --help-advanced # show advanced options
options:
-h, --help show this help message and exit
-o, --outfile OUTFILE output file (default: scalene-profile.json)
--cpu-only only profile CPU time (no memory/GPU)
-c, --config FILE load options from YAML config file
--help-advanced show advanced options
% scalene run --help-advanced
Advanced options for scalene run:
background profiling:
Use --off to start with profiling disabled, then control it from another terminal:
% scalene run --off prog.py # start with profiling off
% python3 -m scalene.profile --on --pid # resume profiling
% python3 -m scalene.profile --off --pid # suspend profiling
options:
--profile-all profile all code, not just the target program
--profile-only PATH only profile files containing these strings (comma-separated)
--profile-exclude PATH exclude files containing these strings (comma-separated)
--profile-system-libraries profile Python stdlib and installed packages (default: skip)
--gpu profile GPU time and memory
--memory profile memory usage
--stacks collect stack traces
--profile-interval N output profiles every N seconds (default: inf)
--use-virtual-time measure only CPU time, not I/O or blocking
--cpu-percent-threshold N only report lines with at least N% CPU (default: 1%)
--cpu-sampling-rate N CPU sampling rate in seconds (default: 0.01)
--allocation-sampling-window N allocation sampling window in bytes
--malloc-threshold N only report lines with at least N allocations (default: 100)
--program-path PATH directory containing code to profile
--memory-leak-detector EXPERIMENTAL: report likely memory leaks
--on start with profiling on (default)
--off start with profiling off
% scalene view --help
View an existing Scalene profile.
examples:
% scalene view # open in browser
% scalene view --cli # view in terminal
% scalene view --html # save to scalene-profile.html
% scalene view --standalone # save as self-contained HTML
% scalene view myprofile.json # open specific profile in browser
options:
-h, --help show this help message and exit
--cli display profile in the terminal
--html save to scalene-profile.html (no browser)
--standalone save as self-contained HTML with all assets embedded
-r, --reduced only show lines with activity (--cli mode)
```
### Scalene with Jupyter
Instructions for installing and using Scalene with Jupyter notebooks
[This notebook](https://nbviewer.jupyter.org/github/plasma-umass/scalene/blob/master/docs/scalene-demo.ipynb) illustrates the use of Scalene in Jupyter.
Installation:
```console
!pip install scalene
%load_ext scalene
```
Line mode:
```console
%scrun [options] statement
```
Cell mode:
```console
%%scalene [options]
code...
code...
```
## Installation
Using pip (Mac OS X, Linux, Windows, and WSL2)
Scalene is distributed as a `pip` package and works on Mac OS X, Linux (including Ubuntu in [Windows WSL2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-index)) and Windows platforms.
> **Note for Windows users**
>
> Starting with Scalene 2.0, Windows supports full memory profiling. If you
> encounter issues, ensure you have the [Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe)
> installed. If building from source, you will need Visual C++ Build Tools and CMake.
>
You can install it as follows:
```console
% pip install -U scalene
```
or
```console
% python3 -m pip install -U scalene
```
You may need to install some packages first.
See https://stackoverflow.com/a/19344978/4954434 for full instructions for all Linux flavors.
For Ubuntu/Debian:
```console
% sudo apt install git python3-all-dev
```
Using conda (Mac OS X, Linux, Windows, and WSL2)
```console
% conda install -c conda-forge scalene
```
Scalene is distributed as a `conda` package and works on Mac OS X, Linux (including Ubuntu in [Windows WSL2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-index)) and Windows platforms.
> **Note for Windows users**
>
> Starting with Scalene 2.0, Windows supports full memory profiling. If you
> encounter issues, ensure you have the [Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe)
> installed.
>
On ArchLinux
You can install Scalene on Arch Linux via the [AUR
package](https://aur.archlinux.org/packages/python-scalene-git/). Use your favorite AUR helper, or
manually download the `PKGBUILD` and run `makepkg -cirs` to build. Note that this will place
`libscalene.so` in `/usr/lib`; modify the below usage instructions accordingly.
# Frequently Asked Questions
Can I use Scalene with PyTest?
**A:** Yes! You can run it as follows (for example):
`scalene run -m pytest your_test.py`
or
`python3 -m scalene run -m pytest your_test.py`
Is there any way to get shorter profiles or do more targeted profiling?
**A:** Yes! There are several options:
1. Use `--reduced-profile` to include only lines and files with memory/CPU/GPU activity.
2. Use `--profile-only` to include only filenames containing specific strings (as in, `--profile-only foo,bar,baz`).
3. Decorate functions of interest with `@profile` to have Scalene report _only_ those functions.
4. Turn profiling on and off programmatically by importing Scalene profiler (`from scalene import scalene_profiler`) and then turning profiling on and off via `scalene_profiler.start()` and `scalene_profiler.stop()`. By default, Scalene runs with profiling on, so to delay profiling until desired, use the `--off` command-line option (`scalene run --off yourprogram.py`).
How do I run Scalene in PyCharm?
**A:** In PyCharm, you can run Scalene at the command line by opening the terminal at the bottom of the IDE and running a Scalene command (e.g., `scalene run `). Then use `scalene view --html` to generate an HTML file (`scalene-profile.html`) that you can view in the IDE.
How do I use Scalene with Django?
**A:** Pass in the `--noreload` option (see https://github.com/plasma-umass/scalene/issues/178).
Does Scalene work with gevent/Greenlets?
**A:** Yes! Put the following code in the beginning of your program, or modify the call to `monkey.patch_all` as below:
```python
from gevent import monkey
monkey.patch_all(thread=False)
```
How do I use Scalene with PyTorch on the Mac?
**A:** Scalene works with PyTorch version 1.5.1 on Mac OS X. There's a bug in newer versions of PyTorch (https://github.com/pytorch/pytorch/issues/57185) that interferes with Scalene (discussion here: https://github.com/plasma-umass/scalene/issues/110), but only on Macs.
# Technical Information
For details about how Scalene works, please see the following paper, which won the Jay Lepreau Best Paper Award at [OSDI 2023](https://www.usenix.org/conference/osdi23/presentation/berger): [Triangulating Python Performance Issues with Scalene](https://arxiv.org/pdf/2212.07597). (Note that this paper does not include information about the AI-driven proposed optimizations.)
To cite Scalene in an academic paper, please use the following:
```latex
@inproceedings{288540,
author = {Emery D. Berger and Sam Stern and Juan Altmayer Pizzorno},
title = {Triangulating Python Performance Issues with {S}calene},
booktitle = {{17th USENIX Symposium on Operating Systems Design and Implementation (OSDI 23)}},
year = {2023},
isbn = {978-1-939133-34-2},
address = {Boston, MA},
pages = {51--64},
url = {https://www.usenix.org/conference/osdi23/presentation/berger},
publisher = {USENIX Association},
month = jul
}
```
# Success Stories
If you use Scalene to successfully debug a performance problem, please [add a comment to this issue](https://github.com/plasma-umass/scalene/issues/58)!
# Acknowledgements
Logo created by [Sophia Berger](https://www.linkedin.com/in/sophia-berger/).
This material is based upon work supported by the National Science
Foundation under Grant No. 1955610. Any opinions, findings, and
conclusions or recommendations expressed in this material are those of
the author(s) and do not necessarily reflect the views of the National
Science Foundation.
================================================
FILE: Scalene-Agents.md
================================================
# Scalene Profiling Guide
## Basic Usage
```bash
python3 -m scalene --cli --json --outfile profile.json script.py
```
## Understanding Python vs C (Native) Time
Scalene's key differentiator is separating Python time from C/native time:
- **`n_cpu_percent_python`**: Time spent executing Python bytecode - **this is your optimization target**
- **`n_cpu_percent_c`**: Time spent in C extensions/native code - generally NOT optimizable at the Python level
**Critical insight**: Focus optimization efforts on code with high Python time. Code spending most of its time in C is already running native code and can only be improved by:
1. Reducing the number of calls to the C code (algorithmic changes)
2. Using the library more efficiently (e.g., batching operations)
3. Switching to a different library
For example, Python's slice reversal `perm[:k+1] = perm[k::-1]` shows high C time because it's implemented in C. Replacing it with a Python loop makes performance *worse* because it moves work from fast C code to slow Python code.
## Memory Profiling Metrics
Scalene tracks detailed memory behavior:
- **`n_malloc_mb`**: Memory allocated on this line
- **`n_peak_mb`**: Peak memory usage attributed to this line
- **`n_avg_mb`**: Average memory footprint
- **`n_growth_mb`**: Net memory growth (allocations minus frees) - useful for detecting memory leaks
- **`n_usage_fraction`**: Fraction of total memory used by this line
**When to focus on memory**:
- High `n_growth_mb` with `n_python_fraction` near 1.0 indicates Python objects accumulating (potential leak)
- High `n_peak_mb` suggests opportunities to reduce memory footprint by processing data in chunks
## Copy Volume Tracking
- **`n_copy_mb_s`**: Rate of memory copying in MB/s attributed to this line
**Why this matters**: High copy volume indicates inefficient data handling:
- Unnecessary string concatenation in loops (use `join()` or `io.StringIO`)
- Repeated array/list copies (use views, in-place operations, or pre-allocation)
- Passing large objects by value when references would suffice
Example: A line showing 100+ MB/s copy volume in a data processing loop suggests refactoring to avoid intermediate copies.
## GPU Metrics (if applicable)
- **`n_gpu_percent`**: Percentage of GPU time
- **`n_gpu_avg_memory_mb`**: Average GPU memory usage
- **`n_gpu_peak_memory_mb`**: Peak GPU memory usage
## System Time
- **`n_sys_percent`**: Time spent in system calls (I/O, etc.)
High system time may indicate:
- Excessive file I/O (batch reads/writes)
- Too many small network requests (batch API calls)
- Suboptimal disk access patterns
## Optimization Decision Tree
1. **Check Python vs C time split**
- High Python time → Optimize the Python code
- High C time → Consider algorithmic changes or different libraries
2. **Check memory growth**
- Sustained growth → Look for leaks, unbounded caches, or accumulating data structures
3. **Check copy volume**
- High copy rate → Refactor to use views, in-place operations, or pre-allocation
4. **Check system time**
- High system time → Batch I/O operations, use async I/O, or optimize file access patterns
================================================
FILE: Scalene-Debugging.md
================================================
# Debugging Patterns for Scalene
## Signal Handler Debugging
The CPU signal handler (`cpu_signal_handler`) receives `this_frame` as the raw frame parameter. The `compute_frames_to_record()` function filters this down to user-only frames via `_should_trace()`.
**Critical gotcha**: When the main thread is idle in the event loop (the exact case async profiling needs to detect), there are NO user frames — asyncio/selector frames are all filtered out. So `frames` from `compute_frames_to_record()` is empty. Must use `this_frame` directly for event loop detection.
## Async Profiling Debugging
To verify async profiling is working:
1. Create a test program with known behavior (fast I/O, slow I/O, CPU-bound)
2. Profile: `python3 -m scalene run --async test/test_async_demo.py`
3. Check JSON: `python3 -m scalene view --cli` should show Await % column
4. Verify proportions: slow_io >> mixed_work >> fast_io, cpu_work = 0% await
To debug zero-await-data:
- Check `is_in_event_loop()` returns True when event loop is idle
- Check `_poll_suspended_tasks()` finds tasks
- Verify the signal handler is using `this_frame`, not filtered `frames`
## Profile Output Pipeline
There are **three separate renderers** for profile output. All must be updated when adding new columns:
- **JSON output**: `scalene_json.py:output_profiles()` → `output_profile_line()`
- **CLI viewer**: `scalene_parseargs.py:_display_profile_cli()` — used by `scalene view --cli`
- **HTML/GUI output**: `scalene_output.py:output_profiles()` — used by `scalene view --html`
- **GUI (browser)**: `scalene-gui.ts:makeProfileLine()` → embedded Vega-Lite charts via `vegaEmbed()`
- **Standalone HTML**: `scalene_utility.py:generate_html(standalone=True)` embeds all assets inline
Note: `_display_profile_cli()` in `scalene_parseargs.py` is completely separate from `scalene_output.py`. This is easy to miss.
## Unbounded Growth Prevention
Any dict or set that accumulates per-sample data must be bounded:
- **Dicts keyed by (filename, lineno)**: Inherently bounded by source code size — OK.
- **Sets of names/strings**: Must be capped (e.g., `async_task_names` capped at 100 per location).
- **Tracking dicts** (e.g., `_suspended_tasks`): Must be capped and cleared when exceeded.
- **`RunningStats`**: Fixed-size (count, mean, M2) — OK.
- **`ScaleneSigQueue`**: Uses `SimpleQueue` with continuous consumer drain — OK.
================================================
FILE: Scalene-GUI.md
================================================
# GUI Development Patterns
## Adding a New Column
1. **`gui-elements.ts`**: Add chart function (e.g., `makeAwaitPie`) following existing patterns
2. **`scalene-gui.ts`**:
- Add to imports
- Add chart array (e.g., `const await_pies: (unknown | null)[] = []`)
- Add column in `makeTableHeader()`
- Add cell rendering in `makeProfileLine()` — push chart specs to array
- Pass array through both call sites (line profile loop + function profile loop)
- Add `embedCharts(await_pies, "await_pie")` at the end
3. **Rebuild**: `npx esbuild scalene-gui.ts --bundle --outfile=scalene-gui-bundle.js --format=iife --global-name=ScaleneGUI`
4. **`scalene_json.py`**: Add field to `FunctionDetail`, compute in payload
5. **`scalene_output.py`**: Add column for CLI `--html` output
6. **`scalene_parseargs.py`**: Add column in `_display_profile_cli()` for `scalene view --cli`
## Chart Types (Vega-Lite)
All charts are Vega-Lite specs rendered via `vegaEmbed()` after DOM insertion.
- **Bar**: `makeBar()` — stacked horizontal bar (CPU time: Python/native/system)
- **Pie**: `makeGPUPie()`, `makeAwaitPie()`, `makeMemoryPie()` — arc charts
- **Sparkline**: `makeSparkline()` — line chart for memory timeline
- **NRT/NC bars**: `makeNRTBar()`, `makeNCTimeBar()` — Neuron time bars
- **Standard dimensions**: 20px height, various widths
## Pie Chart Best Practices
- Always use **two data values** (filled + remaining) for a complete circle. Single-value pies with `scale: { domain: [0, 100] }` show partial arcs with gaps — looks bad.
- For **rotating pies** (each row's wedge starts where previous ended): use `scale: { range: [startAngle, startAngle + 2*PI] }` on the theta encoding. Track cumulative angle:
```typescript
pieAngles.await += (pct / 100) * 2 * Math.PI;
```
- Reset angle state per table (line profile and function profile tables get separate `pieAngles` objects).
## Chart Rendering Flow
1. `makeProfileLine()` builds HTML string with `` placeholders
2. Chart specs are pushed to arrays (e.g., `cpu_bars`, `gpu_pies`, `await_pies`)
3. After all HTML is inserted into DOM, `embedCharts(array, "prefix")` calls `vegaEmbed()` for each spec
4. SVGs render asynchronously — Selenium tests need explicit waits to verify SVG content
## makeProfileLine Call Sites
This function has many parameters. When adding new ones, append to the end with defaults. The two call sites are:
- Line profile loop: creates `linePieAngles = { await: 0, gpu: 0 }` before the loop
- Function profile loop: creates `fnPieAngles = { await: 0, gpu: 0 }` before the loop
================================================
FILE: agents/windows-memory-profiling-port.md
================================================
# Windows Memory Profiling Port - Progress and Plans
## Overview
Porting Scalene's memory profiling from Linux/macOS to Windows. On Unix systems, Scalene uses `LD_PRELOAD`/`DYLD_INSERT_LIBRARIES` to interpose on malloc/free. Windows doesn't support this mechanism, so we use Python's allocator API instead.
## Architecture
### Unix Approach
- `libscalene.so`/`libscalene.dylib` is preloaded via environment variables
- Interposes on malloc/free/realloc at the C library level
- Uses Unix signals (SIGXCPU, SIGXFSZ) to communicate with Python
- Uses POSIX shared memory (`/tmp/scalene-*`) for data transfer
### Windows Approach
- `libscalene.dll` is loaded explicitly via ctypes
- Uses Python's `PyMem_SetAllocator` API to intercept allocations
- Uses Windows Events instead of Unix signals (but currently using polling)
- Uses Windows Named Shared Memory (`Local\scalene-*`) for data transfer
## Files Created/Modified
### New Files
- `src/source/libscalene_windows.cpp` - Main Windows DLL implementation (includes Detours native hooks)
- `src/include/samplefile_win.hpp` - Windows shared memory implementation
- `src/include/common_win.hpp` - Windows compatibility macros
- `src/include/mallocrecursionguard_win.hpp` - Windows TLS-based recursion guard
- `scalene/scalene_windows.py` - Python helper for Windows memory profiling
- `vendor/Detours/` - Microsoft Detours library for native malloc/free hooking (vendored)
### Modified Files
- `CMakeLists.txt` - Cross-platform build configuration with Detours integration
- `src/include/pywhere.hpp` - Windows DLL export/import macros
- `src/source/pywhere.cpp` - Windows symbol lookup via accessor functions
- `scalene/scalene_profiler.py` - Windows DLL loading and initialization
- `scalene/scalene_mapfile.py` - Windows named shared memory support
- `scalene/scalene_signal_manager.py` - Windows memory polling thread
- `scalene/scalene_preload.py` - Case-insensitive ARM64 detection
- `scalene/scalene_arguments.py` - Enable memory profiling on Windows
## Current Status (2024-12-17) - FULLY WORKING WITH NATIVE LIBRARY SUPPORT!
### All Core Features Working
1. ✅ DLL builds successfully with CMake/MSBuild for ARM64
2. ✅ DLL loads without crashing
3. ✅ Python allocator hooks are installed via `PyMem_SetAllocator`
4. ✅ Allocation size tracking implemented (hash map with critical section)
5. ✅ Shared memory objects created successfully (both malloc and memcpy)
6. ✅ ScaleneMapFile opens shared memory from Python side successfully
7. ✅ All `thread_local` variables removed (caused crashes with dynamically loaded DLLs on Windows)
8. ✅ Data format updated to match Unix (comma-separated, 9 fields for malloc, 6 for memcpy)
9. ✅ Windows memory polling thread added to `scalene_signal_manager.py`
10. ✅ **64-bit pointer handling fixed in ctypes code**
11. ✅ Memory profiling working - samples being collected and logged
12. ✅ **Native library tracking (numpy, etc.) via Microsoft Detours**
13. ✅ **Proper free tracking with manual size tracking hash map**
### Test Results (2024-12-17)
```
alloc_samples: 203
max_footprint_mb: 152.71
max_footprint_python_fraction: 0.000288
Native fraction: 99.97%
```
The profiler now correctly tracks memory allocations from native libraries like numpy, with proper line attribution.
### Known Limitation
- Console output may fail with `UnicodeEncodeError` on Windows consoles using CP1252 encoding
- This is not a profiler bug - it's a Windows console limitation
- **Workaround**: Set `PYTHONIOENCODING=utf-8` environment variable or use `--html` or `--json` output
## The Critical Bug Fix (2024-12-16)
### Root Cause: ctypes 64-bit Pointer Truncation
The Access Violation crash (exit code 3221225477 = 0xC0000005) was caused by a **ctypes bug** where 64-bit pointers were being truncated to 32-bit values.
**Problem**: By default, ctypes assumes Windows API functions return `c_int` (32-bit). On 64-bit Windows, `MapViewOfFile` returns a 64-bit pointer. Without explicit return type declaration, the high 32 bits were truncated, causing invalid memory addresses.
**Example of bug**:
```
MapViewOfFile returns: 0x00007FFBF2650B90 (valid 64-bit pointer)
ctypes stored as: 0x00000000F2650B90 (truncated to 32-bit, invalid!)
```
### The Fix (scalene_mapfile.py)
Added proper return type declarations before calling Windows API functions:
```python
from ctypes import wintypes
kernel32 = ctypes.windll.kernel32
# IMPORTANT: Set proper return types for Windows API functions
# Default ctypes return type is c_int (32-bit) which truncates 64-bit pointers
kernel32.OpenFileMappingW.restype = wintypes.HANDLE
kernel32.MapViewOfFile.restype = ctypes.c_void_p
kernel32.UnmapViewOfFile.argtypes = [ctypes.c_void_p]
kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
```
This fix is in `scalene/scalene_mapfile.py` in the `_init_windows()` method.
## Native Library Memory Tracking (2024-12-17)
### The Problem
The original Windows implementation only tracked Python allocations via `PyMem_SetAllocator`. Native library allocations (numpy arrays, pandas dataframes, etc.) went untracked because they bypass Python's allocator and call the C runtime `malloc`/`free` directly.
**Before**: Only Python allocations tracked (0.03% of actual memory usage)
**After**: All allocations tracked including native libraries (99.97% native, 0.03% Python)
### Solution: Microsoft Detours
We use [Microsoft Detours](https://github.com/microsoft/Detours) to intercept `malloc`/`free`/`realloc`/`calloc` at the C runtime level. Detours works by rewriting the first few bytes of target functions with a jump to our hooks.
**Why Detours over alternatives:**
- **MinHook**: Does NOT support ARM64 (only x86/x64)
- **IAT Hooking**: Complex, requires hooking each loaded module separately
- **ETW (Event Tracing)**: Requires admin privileges, high overhead
- **Detours**: Supports ARM64, x64, x86, ARM - official Microsoft library, MIT licensed
### Implementation
#### Files Modified/Added
- `vendor/Detours/` - Microsoft Detours source (vendored)
- `CMakeLists.txt` - Added Detours to Windows build with architecture-specific disassembler
- `src/source/libscalene_windows.cpp` - Added native hooks using Detours
#### CMakeLists.txt Changes
```cmake
# Microsoft Detours sources for native malloc/free hooking
set(DETOURS_SOURCES
vendor/Detours/src/detours.cpp
vendor/Detours/src/modules.cpp
vendor/Detours/src/disasm.cpp
vendor/Detours/src/image.cpp
vendor/Detours/src/creatwth.cpp
)
# Add architecture-specific disassembler
if(SCALENE_ARCH STREQUAL "ARM64")
list(APPEND DETOURS_SOURCES vendor/Detours/src/disolarm64.cpp)
elseif(SCALENE_ARCH STREQUAL "X64")
list(APPEND DETOURS_SOURCES vendor/Detours/src/disolx64.cpp)
elseif(SCALENE_ARCH STREQUAL "X86")
list(APPEND DETOURS_SOURCES vendor/Detours/src/disolx86.cpp)
endif()
target_compile_definitions(scalene PRIVATE DETOURS_INTERNAL)
```
#### Native Hook Implementation
```cpp
#include "detours.h"
// Original function pointers (Detours fills these with trampolines)
static void* (__cdecl *Real_malloc)(size_t) = malloc;
static void (__cdecl *Real_free)(void*) = free;
static void* (__cdecl *Real_realloc)(void*, size_t) = realloc;
static void* (__cdecl *Real_calloc)(size_t, size_t) = calloc;
// Recursion guard - CRITICAL for preventing infinite loops
static bool g_in_native_hook = false;
// Coordination with Python allocator hooks
static bool g_in_python_allocator = false;
static void* __cdecl Hooked_malloc(size_t size) {
// Check recursion guard FIRST - track_native_alloc may call malloc internally
if (g_in_native_hook || g_in_python_allocator) {
return Real_malloc(size);
}
g_in_native_hook = true;
void* ptr = Real_malloc(size);
if (ptr) {
track_native_alloc(ptr, size);
if (!p_scalene_done) {
TheHeapWrapper::register_malloc(size, ptr, false); // false = native
}
}
g_in_native_hook = false;
return ptr;
}
bool install_native_hooks() {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Real_malloc, Hooked_malloc);
DetourAttach(&(PVOID&)Real_free, Hooked_free);
DetourAttach(&(PVOID&)Real_realloc, Hooked_realloc);
DetourAttach(&(PVOID&)Real_calloc, Hooked_calloc);
return DetourTransactionCommit() == NO_ERROR;
}
```
### Critical Bug Fix: Recursion Guard Order
**Problem**: The native hooks use `std::unordered_map` for size tracking, which internally calls `malloc`. If the recursion guard was checked AFTER calling tracking functions, infinite recursion occurred:
1. User code calls `malloc`
2. `Hooked_malloc` is called
3. `track_native_alloc(ptr, size)` is called (hash map insert)
4. Hash map internally calls `malloc` for bucket allocation
5. `Hooked_malloc` is called again (recursion!)
6. Since `g_in_native_hook` wasn't set yet, we recurse infinitely → stack overflow
**Fix**: Check and set `g_in_native_hook` at the VERY BEGINNING of each hook, BEFORE any operations that might allocate:
```cpp
static void* __cdecl Hooked_malloc(size_t size) {
// MUST check recursion guard FIRST
if (g_in_native_hook || g_in_python_allocator) {
return Real_malloc(size); // Bypass hook
}
g_in_native_hook = true; // Set BEFORE any allocating operations
// ... rest of hook logic ...
g_in_native_hook = false;
return ptr;
}
```
### Free Size Tracking
**Problem**: `_msize()` doesn't work reliably for custom allocators (numpy uses aligned allocations with `_aligned_malloc`).
**Solution**: Manual size tracking with a hash map:
```cpp
static std::unordered_map g_native_alloc_sizes;
static CRITICAL_SECTION g_native_alloc_sizes_lock;
static void track_native_alloc(void* ptr, size_t size) {
EnterCriticalSection(&g_native_alloc_sizes_lock);
g_native_alloc_sizes[ptr] = size;
LeaveCriticalSection(&g_native_alloc_sizes_lock);
}
static size_t untrack_native_alloc(void* ptr) {
EnterCriticalSection(&g_native_alloc_sizes_lock);
auto it = g_native_alloc_sizes.find(ptr);
size_t size = (it != g_native_alloc_sizes.end()) ? it->second : 0;
if (it != g_native_alloc_sizes.end()) g_native_alloc_sizes.erase(it);
LeaveCriticalSection(&g_native_alloc_sizes_lock);
return size;
}
```
### Coordination Between Python and Native Hooks
To prevent double-counting allocations that go through both Python's allocator AND the native malloc:
1. Python allocator hooks set `g_in_python_allocator = true` when active
2. Native malloc hooks check this flag and skip if Python allocator is handling it
3. Each allocation is counted exactly once
```cpp
// In Python allocator hook:
static void* scalene_malloc(void* ctx, size_t len) {
g_in_python_allocator = true; // Prevent native hooks
void* ptr = g_original_mem_allocator.malloc(...);
// ... tracking code ...
g_in_python_allocator = false;
return ptr;
}
```
## Fixes Applied
### 1. **ctypes 64-bit Pointer Fix** (Critical)
- Added `restype` declarations for all Windows API functions that return handles or pointers
- `MapViewOfFile.restype = ctypes.c_void_p` - returns memory address
- `OpenFileMappingW.restype = wintypes.HANDLE` - returns handle
- Also set `argtypes` for functions taking pointers
### 2. Data Format Fix
Changed malloc/free output from tab-separated 4-field format to comma-separated 9-field format matching Unix:
```
M,alloc_time,count,python_fraction,pid,pointer,filename,lineno,bytei\n\n
```
### 3. Removed `thread_local` Variables
Windows DLLs loaded with `LoadLibrary`/ctypes don't properly support `thread_local` variables. Changed all to static variables:
- `mallocSampler` and `memcpySampler`
- `g_pythonCount`, `g_cCount`
- `g_lastMallocTrigger`, `g_freedLastMallocTrigger`
- `g_memcpyOps`
- `inMalloc` (for recursion guard)
### 4. Added Windows Memory Polling
Since Unix signals (SIGXCPU/SIGXFSZ) don't exist on Windows, added a polling thread in `scalene_signal_manager.py`:
- `_windows_memory_poll_loop()` - polls every 10ms
- Triggers `_alloc_sigqueue_processor` and `_memcpy_sigqueue_processor`
- Started when memory profiling is enabled on Windows
### 5. Safety Checks in Allocator Hooks
Added null checks for original allocator function pointers to prevent crashes if allocation hooks are called before initialization.
## Test Results
Running the profiler now shows memory profiling data being collected:
```
malloc_calls=113807912, samples=595, logged=595
```
The profiler correctly tracks:
- Python vs native time
- Memory allocations with line attribution
- Memory timeline/growth rate
## Build Instructions
```bash
# Configure with CMake (for ARM64 native)
cmake -B build -A ARM64 -DPython3_ROOT_DIR="C:\Users\emery\AppData\Local\Programs\Python\Python311-arm64"
# Build the DLL
MSBuild.exe build/scalene.sln -p:Configuration=Release -p:Platform=ARM64 -t:scalene
# DLL is automatically placed in scalene\ directory
# Run profiler
python -m scalene --cli --cpu --memory test\testme.py
```
## Key Differences from Unix Implementation
| Aspect | Unix | Windows |
|--------|------|---------|
| Native malloc hooking | LD_PRELOAD | **Microsoft Detours** (inline function hooking) |
| Python allocator | PyMem_SetAllocator | PyMem_SetAllocator (same) |
| Signals | SIGXCPU/SIGXFSZ | Polling thread |
| Shared Memory | /tmp files + mmap | Named shared memory |
| Symbol Lookup | dlsym(RTLD_DEFAULT) | GetProcAddress + accessor functions |
| Size Tracking | malloc_usable_size | Manual hash map (\_msize unreliable) |
| Thread-local | `thread_local` | Static variables (GIL protects) |
| Pointer handling | Native 64-bit | **Requires explicit ctypes declarations** |
| Architecture support | All | ARM64, x64, x86 (via Detours) |
## Learnings
### 1. ctypes Default Return Types Are Dangerous on 64-bit Windows
- **Always** set `restype` for any Windows API function that returns a handle or pointer
- Default `c_int` (32-bit) silently truncates 64-bit values
- This causes delayed crashes that are hard to debug (crash happens when truncated pointer is used, not when it's returned)
- Use `ctypes.c_void_p` for memory addresses, `wintypes.HANDLE` for handles
### 2. Debugging Methodology That Worked
The crash was isolated using **systematic component elimination**:
1. First confirmed DLL was the cause by renaming it (profiler ran without crash)
2. Tested with allocator hooks disabled - still crashed (ruled out hooks as cause)
3. Tested with only shared memory initialization - still crashed (narrowed to shared memory)
4. Examined shared memory code and found the ctypes issue
### 3. Windows DLL Loading Constraints
- `thread_local` variables don't work reliably in DLLs loaded via `LoadLibrary`/ctypes
- Static variables work fine since Python's GIL serializes access
- DLL entry point (`DllMain`) has severe restrictions - avoid complex initialization there
### 4. Build System Considerations
- CMake generates Visual Studio solutions that work well for cross-platform builds
- ARM64 native builds require explicit `-A ARM64` and matching Python version
- MSBuild can be invoked directly for rebuilds without re-running CMake
### 5. Windows vs Unix IPC
- Named shared memory on Windows uses `Local\` prefix for per-session namespace
- Windows Events can replace Unix signals but polling is simpler for this use case
- Mutexes on Windows are more heavyweight than Unix futexes
### 6. Recursion Guards in malloc Hooks Must Come FIRST
- **Critical**: Any code in a malloc hook that uses STL containers (std::unordered_map, std::vector, etc.) may internally call malloc
- The recursion guard (`g_in_native_hook`) MUST be checked and set BEFORE any other operations
- Failing to do this causes infinite recursion → stack overflow → exit code 127 or crash
- Pattern: `if (guard) return original(); guard = true; ... ; guard = false; return result;`
### 7. MinHook Does NOT Support ARM64
- MinHook is a popular inline hooking library but only supports x86 and x64
- Microsoft Detours supports ARM64, ARM, x86, x64, and IA64
- Detours is MIT licensed (open source since 2018) and very well tested
- Use architecture-specific disassemblers: `disolarm64.cpp` for ARM64, `disolx64.cpp` for x64
### 8. _msize() Is Unreliable for Custom Allocators
- `_msize()` only works for standard CRT heap allocations
- numpy and other libraries use aligned allocations (`_aligned_malloc`) which `_msize` doesn't handle
- Solution: Manual size tracking with a hash map, storing size at allocation time
- This adds ~10% overhead but is necessary for accurate free tracking
### 9. Coordination Between Multiple Hook Layers
- When hooking at both Python allocator level AND native malloc level, coordination is essential
- Use a flag (`g_in_python_allocator`) to prevent native hooks from double-counting Python allocations
- Pattern: Set flag before calling original allocator, clear after
- This ensures each allocation is tracked exactly once
## Next Steps
### High Priority
1. **x64 Build and Testing**: Current implementation tested only on ARM64. Need to verify x64 builds work correctly with Detours.
2. **Unicode Console Output**: The `UnicodeEncodeError` for sparkline characters could be handled more gracefully:
- Detect console encoding and fall back to ASCII sparklines
- Or auto-set `PYTHONIOENCODING=utf-8` when running on Windows
3. **Performance Optimization**: The polling thread polls every 10ms. Consider:
- Using Windows Events for more efficient signaling
- Adaptive polling rate based on allocation frequency
### Medium Priority
4. **Multi-Process Support**: Test and fix any issues with profiling child processes on Windows (the Unix `redirect_python` mechanism may need Windows adaptation).
5. **GPU Profiling on Windows**: Verify NVIDIA GPU profiling works on Windows (pynvml should work but needs testing).
6. **CI/CD Integration**: Add Windows builds to GitHub Actions workflow:
- Build DLL for both x64 and ARM64
- Run tests on Windows
- Include DLL in wheel packages
### Low Priority
7. **Windows Event-Based Signaling**: Replace polling with proper Windows Events for lower latency and CPU usage:
- DLL already creates events (`ScaleneMallocEvent`, etc.)
- Python side would use `WaitForMultipleObjects` instead of polling
8. **Memory Leak Detection**: The `--memory-leak-detector` feature may need Windows-specific testing.
9. **Web UI Testing**: Verify the web-based GUI works correctly on Windows (browser launching, port binding).
### Completed
- ~~**Native Library Memory Tracking**: Implement malloc/free hooking for numpy, pandas, etc.~~ ✅ Done (2024-12-17) - Using Microsoft Detours
## Debugging Tips for Future Issues
### Useful Debug Techniques
```python
# Add to scalene_mapfile.py to debug shared memory issues
print(f"Handle value: {handle:#x}", file=sys.stderr)
print(f"View address: {view:#x}", file=sys.stderr)
# Check if pointer looks valid (should have high bits set on 64-bit)
if view < 0x100000000:
print("WARNING: Pointer may be truncated!", file=sys.stderr)
```
### Building with Debug Output
```cpp
// In libscalene_windows.cpp, temporarily add:
fprintf(stderr, "DEBUG: ptr=%p, size=%zu\n", ptr, size);
```
Then rebuild with:
```bash
MSBuild.exe build/scalene.sln -p:Configuration=Release -p:Platform=ARM64 -t:scalene
```
### Common Windows Error Codes
- `0xC0000005` (3221225477) - Access Violation (invalid memory access)
- `0xC0000008` - Invalid Handle
- `0xC000001D` - Illegal Instruction (wrong architecture)
- Error 193 - "Not a valid Win32 application" (architecture mismatch)
## References
- Python Memory Allocator API: https://docs.python.org/3/c-api/memory.html
- Windows Named Shared Memory: https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
- CMake Windows DLL: https://cmake.org/cmake/help/latest/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.html
- Windows thread_local issues: https://devblogs.microsoft.com/cppblog/c11-thread-local-storage-and-dll-load-failure/
- **ctypes 64-bit pointers**: https://docs.python.org/3/library/ctypes.html#return-types
- **Microsoft Detours**: https://github.com/microsoft/Detours - Official Microsoft library for inline function hooking (MIT license)
- Detours Wiki: https://github.com/microsoft/Detours/wiki - API documentation and examples
================================================
FILE: benchmarks/bench_torch_memory.py
================================================
"""Torch-heavy workload that exposes profiler memory explosion (#991).
Run under Scalene to observe memory behaviour:
scalene run benchmarks/bench_torch_memory.py
On master (before the fix), the Scalene process RSS grows continuously
because:
1. torch.profiler accumulates events with full Python stacks for
every torch operation for the entire profiling duration.
2. cpu_samples_list appends a wallclock timestamp on every CPU sample
without any bound.
After the fix, both are bounded via reservoir sampling / periodic
profiler flushing, so RSS stays roughly constant.
Use ``benchmarks/measure_profiler_memory.py`` to automatically measure
and compare peak RSS.
"""
import sys
import time
try:
import torch
except ImportError:
print("ERROR: PyTorch is required. pip install torch", file=sys.stderr)
sys.exit(1)
DURATION_SECONDS = 60 # wall-clock runtime (longer = more event accumulation)
MATRIX_SIZE = 256 # small matrices -> many ops per second
def main() -> None:
print(f"Running torch workload for ~{DURATION_SECONDS}s "
f"(matrix size {MATRIX_SIZE}) ...")
ops = 0
t0 = time.perf_counter()
deadline = t0 + DURATION_SECONDS
a = torch.randn(MATRIX_SIZE, MATRIX_SIZE)
b = torch.randn(MATRIX_SIZE, MATRIX_SIZE)
while time.perf_counter() < deadline:
# Each iteration generates multiple torch profiler events
c = a @ b
c = c + a
c = c.relu()
a, b = b, c
ops += 3 # matmul + add + relu
# Re-normalise occasionally to avoid overflow / underflow
if ops % 3000 == 0:
a = torch.randn(MATRIX_SIZE, MATRIX_SIZE)
b = torch.randn(MATRIX_SIZE, MATRIX_SIZE)
elapsed = time.perf_counter() - t0
print(f"Completed {ops:,} torch ops in {elapsed:.1f}s "
f"({ops / elapsed:,.0f} ops/s)")
if __name__ == "__main__":
main()
================================================
FILE: benchmarks/benchmark.py
================================================
import os
import sys
import re
import subprocess
import traceback
import statistics
python = "python3"
progname = os.path.join(os.path.dirname(__file__), "julia1_nopil.py")
number_of_runs = 1 # We take the average of this many runs.
# Output timing string from the benchmark.
result_regexp = re.compile(
"calculate_z_serial_purepython took ([0-9]*\.[0-9]+) seconds"
)
# Characteristics of the tools.
line_level = {}
cpu_profiler = {}
separate_profiler = {}
memory_profiler = {}
unmodified_code = {}
timing = {}
line_level["baseline"] = None
line_level["cProfile"] = False
line_level["Profile"] = False
line_level["line_profiler"] = True
line_level["pyinstrument"] = False
line_level["yappi_cputime"] = False
line_level["yappi_wallclock"] = False
line_level["pprofile_deterministic"] = True
line_level["pprofile_statistical"] = True
line_level["py_spy"] = True
line_level["memory_profiler"] = True
line_level["scalene_cpu"] = True
line_level["scalene_cpu_memory"] = True
cpu_profiler["baseline"] = None
cpu_profiler["cProfile"] = True
cpu_profiler["Profile"] = True
cpu_profiler["pyinstrument"] = True
cpu_profiler["line_profiler"] = True
cpu_profiler["yappi_cputime"] = True
cpu_profiler["yappi_wallclock"] = True
cpu_profiler["pprofile_deterministic"] = True
cpu_profiler["pprofile_statistical"] = True
cpu_profiler["py_spy"] = True
cpu_profiler["memory_profiler"] = False
cpu_profiler["scalene_cpu"] = True
cpu_profiler["scalene_cpu_memory"] = True
separate_profiler["baseline"] = None
separate_profiler["cProfile"] = False
separate_profiler["Profile"] = False
separate_profiler["pyinstrument"] = False
separate_profiler["line_profiler"] = False
separate_profiler["yappi_cputime"] = False
separate_profiler["yappi_wallclock"] = False
separate_profiler["pprofile_deterministic"] = False
separate_profiler["pprofile_statistical"] = False
separate_profiler["py_spy"] = False
separate_profiler["memory_profiler"] = False
separate_profiler["scalene_cpu"] = True
separate_profiler["scalene_cpu_memory"] = True
memory_profiler["baseline"] = None
memory_profiler["cProfile"] = False
memory_profiler["Profile"] = False
memory_profiler["pyinstrument"] = False
memory_profiler["line_profiler"] = False
memory_profiler["yappi_cputime"] = False
memory_profiler["yappi_wallclock"] = False
memory_profiler["pprofile_deterministic"] = False
memory_profiler["pprofile_statistical"] = False
memory_profiler["py_spy"] = False
memory_profiler["memory_profiler"] = True
memory_profiler["scalene_cpu"] = False
memory_profiler["scalene_cpu_memory"] = True
unmodified_code["baseline"] = None
unmodified_code["cProfile"] = True
unmodified_code["Profile"] = True
unmodified_code["pyinstrument"] = True
unmodified_code["line_profiler"] = False
unmodified_code["yappi_cputime"] = True
unmodified_code["yappi_wallclock"] = True
unmodified_code["pprofile_deterministic"] = True
unmodified_code["pprofile_statistical"] = True
unmodified_code["py_spy"] = True
unmodified_code["memory_profiler"] = False
unmodified_code["scalene_cpu"] = True
unmodified_code["scalene_cpu_memory"] = True
# how the profilers measure time
# - wall clock only
# - virtual (process) time only
# - either one
WallClock = 1
VirtualTime = 2
Either = 3
timing["baseline"] = None
timing["cProfile"] = WallClock
timing["Profile"] = VirtualTime
timing["pyinstrument"] = WallClock
timing["line_profiler"] = WallClock
timing["yappi_cputime"] = Either
timing["yappi_wallclock"] = Either
timing["pprofile_deterministic"] = WallClock
timing["pprofile_statistical"] = WallClock
timing["py_spy"] = Either
timing["memory_profiler"] = None
timing["scalene_cpu"] = Either
timing["scalene_cpu_memory"] = Either
# Command lines for the various tools.
baseline = f"{python} {progname}"
cprofile = f"{python} -m cProfile {progname}"
profile = f"{python} -m profile {progname}"
pyinstrument = f"pyinstrument {progname}"
line_profiler = f"{python} -m kernprof -l -v {progname}"
pprofile_deterministic = f"pprofile {progname}"
pprofile_statistical = f"pprofile --statistic 0.001 {progname}" # Same as Scalene
yappi_cputime = f"yappi {progname}"
yappi_wallclock = f"yappi -c wall {progname}"
py_spy = f"py-spy record -f raw -o foo.txt -- python3.7 {progname}"
scalene_cpu = f"{python} -m scalene {progname}"
scalene_cpu_memory = (
f"{python} -m scalene {progname}" # see below for environment variables
)
benchmarks = [
(baseline, "baseline", "_original program_"),
(cprofile, "cProfile", "`cProfile`"),
(profile, "Profile", "`Profile`"),
(pyinstrument, "pyinstrument", "`pyinstrument`"),
(line_profiler, "line_profiler", "`line_profiler`"),
(pprofile_deterministic, "pprofile_deterministic", "`pprofile` _(deterministic)_"),
(pprofile_statistical, "pprofile_statistical", "`pprofile` _(statistical)_"),
(yappi_cputime, "yappi_cputime", "`yappi` _(CPU)_"),
(yappi_wallclock, "yappi_wallclock", "`yappi` _(wallclock)_"),
(scalene_cpu, "scalene_cpu", "`scalene` _(CPU only)_"),
(scalene_cpu_memory, "scalene_cpu_memory", "`scalene` _(CPU + memory)_"),
]
# benchmarks = [(baseline, "baseline", "_original program_"), (pprofile_deterministic, "`pprofile` _(deterministic)_")]
# benchmarks = [(baseline, "baseline", "_original program_"), (pprofile_statistical, "pprofile_statistical", "`pprofile` _(statistical)_")]
benchmarks = [
(baseline, "baseline", "_original program_"),
(py_spy, "py_spy", "`py-spy`"),
(scalene_cpu, "scalene_cpu", "`scalene` _(CPU only)_"),
(scalene_cpu_memory, "scalene_cpu_memory", "`scalene` _(CPU + memory)_"),
]
average_time = {}
check = ":heavy_check_mark:"
print(
"| | Time | Slowdown | Line-level? | CPU? | Python vs. C? | Memory? | Unmodified code? |"
)
print("| :--- | ---: | ---: | :---: | :---: | :---: | :---: | :---: |")
for bench in benchmarks:
print(bench)
times = []
for i in range(0, number_of_runs):
my_env = os.environ.copy()
if bench[1] == "scalene_cpu_memory":
my_env["PYTHONMALLOC"] = "malloc"
if sys.platform == "darwin":
my_env["DYLD_INSERT_LIBRARIES"] = "./libscalene.dylib"
if sys.platform == "linux":
my_env["LD_PRELOAD"] = "./libscalene.so"
result = subprocess.run(
bench[0].split(),
env=my_env,
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
)
output = result.stdout.decode("utf-8")
print(output)
match = result_regexp.search(output)
if match is not None:
times.append(round(100 * float(match.group(1))) / 100.0)
else:
print("failed run")
average_time[bench[1]] = statistics.mean(times) # sum_time / (number_of_runs * 1.0)
print(str(average_time[bench[1]]))
if bench[1] == "baseline":
print(f"| {bench[2]} | {average_time[bench[1]]}s | 1.0x | | | | | |")
print("| | | | | |")
else:
try:
if bench[1].find("scalene") >= 0:
if bench[1].find("scalene_cpu") >= 0:
print("| | | | | |")
print(
f"| {bench[2]} | {average_time[bench[1]]}s | **{round(100 * average_time[bench[1]] / average_time['baseline']) / 100}x** | {check if line_level[bench[1]] else 'function-level'} | {check if cpu_profiler[bench[1]] else ''} | {check if separate_profiler[bench[1]] else ''} | {check if memory_profiler[bench[1]] else ''} | {check if unmodified_code[bench[1]] else 'needs `@profile` decorators'} |"
)
else:
print(
f"| {bench[2]} | {average_time[bench[1]]}s | {round(100 * average_time[bench[1]] / average_time['baseline']) / 100}x | {check if line_level[bench[1]] else 'function-level'} | {check if cpu_profiler[bench[1]] else ''} | {check if separate_profiler[bench[1]] else ''} | {check if memory_profiler[bench[1]] else ''} | {check if unmodified_code[bench[1]] else 'needs `@profile` decorators'} |"
)
except Exception as err:
traceback.print_exc()
print("err = " + str(err))
print("WOOPS")
# print(bench[1] + " = " + str(sum_time / 5.0))
================================================
FILE: benchmarks/julia1_nopil.py
================================================
import sys
# Disable the @profile decorator if none has been declared.
try:
# Python 2
import __builtin__ as builtins
except ImportError:
# Python 3
import builtins
try:
builtins.profile
except AttributeError:
# No line profiler, provide a pass-through version
def profile(func):
return func
builtins.profile = profile
# Pasted from Chapter 2, High Performance Python - O'Reilly Media;
# minor modifications for Python 3 by Emery Berger
"""Julia set generator without optional PIL-based image drawing"""
import time
# area of complex space to investigate
x1, x2, y1, y2 = -1.8, 1.8, -1.8, 1.8
c_real, c_imag = -0.62772, -0.42193
@profile
def calculate_z_serial_purepython(maxiter, zs, cs):
"""Calculate output list using Julia update rule"""
output = [0] * len(zs)
for i in range(len(zs)):
n = 0
z = zs[i]
c = cs[i]
while abs(z) < 2 and n < maxiter:
z = z * z + c
n += 1
output[i] = n
return output
@profile
def calc_pure_python(desired_width, max_iterations):
"""Create a list of complex coordinates (zs) and complex
parameters (cs), build Julia set, and display"""
x_step = float(x2 - x1) / float(desired_width)
y_step = float(y1 - y2) / float(desired_width)
x = []
y = []
ycoord = y2
while ycoord > y1:
y.append(ycoord)
ycoord += y_step
xcoord = x1
while xcoord < x2:
x.append(xcoord)
xcoord += x_step
# Build a list of coordinates and the initial condition for each cell.
# Note that our initial condition is a constant and could easily be removed;
# we use it to simulate a real-world scenario with several inputs to
# our function.
zs = []
cs = []
for ycoord in y:
for xcoord in x:
zs.append(complex(xcoord, ycoord))
cs.append(complex(c_real, c_imag))
print("Length of x:", len(x))
print("Total elements:", len(zs))
start_time = time.process_time()
output = calculate_z_serial_purepython(max_iterations, zs, cs)
end_time = time.process_time()
secs = end_time - start_time
sys.stdout.flush()
sys.stderr.flush()
output_str = "calculate_z_serial_purepython took " + str(secs) + " seconds"
print(output_str, file=sys.stderr)
sys.stderr.flush()
# This sum is expected for a 1000^2 grid with 300 iterations.
# It catches minor errors we might introduce when we're
# working on a fixed set of inputs.
### assert sum(output) == 33219980
if __name__ == "__main__":
# Calculate the Julia set using a pure Python solution with
# reasonable defaults for a laptop
calc_pure_python(desired_width=1000, max_iterations=300)
sys.exit(-1) # To force output from py-spy
================================================
FILE: benchmarks/measure_profiler_memory.py
================================================
"""Measure Scalene's peak RSS while profiling a torch-heavy workload.
Usage
-----
# On the current branch (should be the fix branch):
python benchmarks/measure_profiler_memory.py
# Compare against master:
python benchmarks/measure_profiler_memory.py --compare-master
The ``--compare-master`` flag will:
1. Run the benchmark on the *current* branch and record peak RSS.
2. Check out ``master``, run the benchmark again, then restore the
original branch.
3. Print a side-by-side comparison.
Without the flag it simply profiles and reports peak RSS for the
current checkout.
Requirements: torch (``pip install torch``).
"""
from __future__ import annotations
import argparse
import os
import platform
import resource
import shutil
import subprocess
import sys
import tempfile
import threading
import time
BENCH_SCRIPT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bench_torch_memory.py")
SAMPLE_INTERVAL = 0.5 # seconds between RSS samples
# --- RSS monitoring ----------------------------------------------------------
def _get_rss_mb(pid: int) -> float | None:
"""Return the RSS of *pid* in MiB, or None if unavailable."""
try:
if platform.system() == "Darwin":
# macOS: use ps (reading /proc is not available)
out = subprocess.check_output(
["ps", "-o", "rss=", "-p", str(pid)],
stderr=subprocess.DEVNULL,
)
return int(out.strip()) / 1024 # ps reports KiB on macOS
else:
# Linux: read from /proc
with open(f"/proc/{pid}/status") as f:
for line in f:
if line.startswith("VmRSS:"):
return int(line.split()[1]) / 1024 # KiB -> MiB
except (subprocess.CalledProcessError, FileNotFoundError, ProcessLookupError,
ValueError, OSError):
pass
return None
class RSSMonitor:
"""Sample RSS of a subprocess at regular intervals in a background thread."""
def __init__(self, pid: int, interval: float = SAMPLE_INTERVAL) -> None:
self.pid = pid
self.interval = interval
self.samples: list[float] = []
self._stop = threading.Event()
self._thread = threading.Thread(target=self._run, daemon=True)
def start(self) -> None:
self._thread.start()
def stop(self) -> None:
self._stop.set()
self._thread.join(timeout=5)
def _run(self) -> None:
while not self._stop.is_set():
rss = _get_rss_mb(self.pid)
if rss is not None:
self.samples.append(rss)
self._stop.wait(self.interval)
@property
def peak_mb(self) -> float:
return max(self.samples) if self.samples else 0.0
@property
def final_mb(self) -> float:
return self.samples[-1] if self.samples else 0.0
# --- Run benchmark under Scalene --------------------------------------------
def run_scalene_benchmark(bench_script: str) -> tuple[float, float, float]:
"""Profile the workload with Scalene and return (peak_rss_mb, final_rss_mb, elapsed_s)."""
# Run in a temp dir so scalene-profile.json doesn't pollute the repo
work_dir = tempfile.mkdtemp(prefix="scalene-bench-")
cmd = [
sys.executable, "-m", "scalene", "run",
bench_script,
]
print(f" Command: {' '.join(cmd)}")
t0 = time.perf_counter()
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=work_dir,
)
monitor = RSSMonitor(proc.pid)
monitor.start()
stdout, _ = proc.communicate()
monitor.stop()
elapsed = time.perf_counter() - t0
# Print the workload output (indented)
for line in stdout.decode(errors="replace").splitlines():
print(f" {line}")
# Also grab rusage as a cross-check
rusage = resource.getrusage(resource.RUSAGE_CHILDREN)
rusage_bytes = rusage.ru_maxrss
if platform.system() != "Darwin":
# Linux reports KiB; convert to bytes
rusage_bytes *= 1024
rusage_mib = rusage_bytes / (1024 * 1024)
print(f" RSS samples collected: {len(monitor.samples)}")
print(f" Peak RSS (sampled): {monitor.peak_mb:,.1f} MiB")
print(f" Final RSS (sampled): {monitor.final_mb:,.1f} MiB")
print(f" Peak RSS (rusage): {rusage_mib:,.1f} MiB")
print(f" Wall time: {elapsed:.1f}s")
# Clean up temp dir
shutil.rmtree(work_dir, ignore_errors=True)
return monitor.peak_mb, monitor.final_mb, elapsed
# --- Git helpers for --compare-master ----------------------------------------
def git(*args: str) -> str:
return subprocess.check_output(
["git", *args], stderr=subprocess.STDOUT,
).decode().strip()
def compare_master() -> None:
original_branch = git("rev-parse", "--abbrev-ref", "HEAD")
print(f"Current branch: {original_branch}\n")
# Copy the benchmark script to a temp file so it's available on both branches
tmp_fd, tmp_bench_name = tempfile.mkstemp(prefix="bench_torch_memory_", suffix=".py")
os.close(tmp_fd)
try:
shutil.copy2(BENCH_SCRIPT, tmp_bench_name)
# --- Run on current branch -------------------------------------------
print(f"=== Benchmarking on {original_branch} ===")
fix_peak, fix_final, fix_elapsed = run_scalene_benchmark(tmp_bench_name)
# --- Switch to master ------------------------------------------------
print()
print("=== Benchmarking on master ===")
git("checkout", "master")
try:
master_peak, master_final, master_elapsed = run_scalene_benchmark(tmp_bench_name)
finally:
# Always restore original branch
print(f"\nRestoring branch {original_branch} ...")
git("checkout", original_branch)
finally:
os.unlink(tmp_bench_name)
# --- Report --------------------------------------------------------------
print()
print("=" * 60)
print(f"{'':30s} {'master':>12s} {'fix':>12s}")
print("-" * 60)
print(f"{'Peak RSS (MiB)':30s} {master_peak:12,.1f} {fix_peak:12,.1f}")
print(f"{'Final RSS (MiB)':30s} {master_final:12,.1f} {fix_final:12,.1f}")
print(f"{'Wall time (s)':30s} {master_elapsed:12.1f} {fix_elapsed:12.1f}")
if master_peak > 0:
reduction = (1 - fix_peak / master_peak) * 100
print(f"{'Peak RSS reduction':30s} {reduction:11.1f}%")
print("=" * 60)
# --- Main --------------------------------------------------------------------
def main() -> None:
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"--compare-master", action="store_true",
help="Run on both the current branch and master, then compare.",
)
args = parser.parse_args()
if args.compare_master:
compare_master()
else:
print("=== Benchmarking on current checkout ===")
run_scalene_benchmark(BENCH_SCRIPT)
if __name__ == "__main__":
main()
================================================
FILE: benchmarks/new_benchmark.py
================================================
import json
import subprocess
import re
import statistics
from glob import glob
from collections import defaultdict
import sys
cmds = {
# "baseline": ["python3"],
# "scalene": ["python3", "-m", "scalene", "--json", "--outfile", "/dev/null"],
# "scalene-cpu": ["python3", "-m", "scalene", "--json", "--cpu", "--outfile", "/dev/null"],
# "scalene-cpu-gpu": ["python3", "-m", "scalene", "--json", "--cpu", "--gpu", "--outfile", "/dev/null"],
# "scalene-5M": ["python3", "-m", "scalene", "--json", "--outfile", "/dev/null", "--allocation-sampling-window", "5242883"],
# "scalene-10M": ["python3", "-m", "scalene", "--json", "--outfile", "/dev/null", "--allocation-sampling-window", "10485767"],
# "scalene-20M": ["python3", "-m", "scalene", "--json", "--outfile", "/dev/null", "--allocation-sampling-window","20971529"],
# "memray": [
# "python3",
# "-m",
# "memray",
# "run",
# "--trace-python-allocators",
# "-f",
# "-o",
# "/tmp/memray.out",
# ],
# "fil": ["fil-profile", "-o", "/tmp/abc", '--no-browser', "run"],
# "austin_full": ["austin", "-o", "/dev/null", "-f"],
# "austin_cpu": ["austin", "-o", "/dev/null"],
# 'py-spy': ['py-spy', 'record', '-o', '/tmp/profile.svg', '--', 'python3'],
# 'cProfile': ['python3', '-m', 'cProfile', '-o', '/dev/null'],
"yappi_wall": ["python3", "-m", "yappi", "-o", "/dev/null", "-c", "wall"],
"yappi_cpu": ["python3", "-m", "yappi", "-o", "/dev/null", "-c", "cpu"],
# 'pprofile_det': ['pprofile', '-o', '/dev/null'],
# 'pprofile_stat': ['pprofile', '-o', '/dev/null', '-s', '0.001'],
# 'line_profiler': ['kernprof', '-l', '-o', '/dev/null', '-v'],
# 'profile': ['python3', '-m', 'profile', '-o', '/dev/null']
}
result_regexp = re.compile(r"Time elapsed:\s+([0-9]*\.[0-9]+)")
def main():
out = defaultdict(lambda: {})
for progname in [
# "./test/expensive_benchmarks/bm_mdp.py",
# "./test/expensive_benchmarks/bm_async_tree_io.py none",
# "./test/expensive_benchmarks/bm_async_tree_io.py io",
# "./test/expensive_benchmarks/bm_async_tree_io.py cpu_io_mixed",
# "./test/expensive_benchmarks/bm_async_tree_io.py memoization",
# "./test/expensive_benchmarks/bm_fannukh.py",
# "./test/expensive_benchmarks/bm_pprint.py",
# "./test/expensive_benchmarks/bm_raytrace.py",
# "./test/expensive_benchmarks/bm_sympy.py",
"./test/expensive_benchmarks/bm_docutils.py"
]:
for profile_name, profile_cmd in cmds.items():
times = []
for i in range(5):
print(
f"Running {profile_name} on {progname} using \"{' '.join(profile_cmd + progname.split(' '))}\"...",
end="",
flush=True,
)
result = subprocess.run(
profile_cmd + progname.split(" "),
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
)
output = result.stdout.decode("utf-8")
# print(output)
match = result_regexp.search(output)
if match is not None:
print(
f"... {match.group(1)}",
end=("\n" if profile_name != "memray" else ""),
)
times.append(round(100 * float(match.group(1))) / 100.0)
if profile_name == "memray":
res2 = subprocess.run(
[
"time",
sys.executable,
"-m",
"memray",
"flamegraph",
"-f",
"/tmp/memray.out",
],
capture_output=True,
env={"TIME": "Time elapsed: %e"},
)
output2 = res2.stderr.decode("utf-8")
match2 = result_regexp.search(output2)
if match2 is not None:
print(f"... {match2.group(1)}")
times[-1] += round(100 * float(match2.group(1))) / 100.0
else:
print("... RUN FAILED")
# exit(1)
else:
print("RUN FAILED")
# exit(1)
out[profile_name][progname] = times
with open("yappi.json", "w+") as f:
json.dump(dict(out), f)
if __name__ == "__main__":
main()
================================================
FILE: benchmarks/pystone.py
================================================
#! /usr/bin/env python3
"""
"PYSTONE" Benchmark Program
Version: Python/1.1 (corresponds to C/1.1 plus 2 Pystone fixes)
Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013.
Translated from ADA to C by Rick Richardson.
Every method to preserve ADA-likeness has been used,
at the expense of C-ness.
Translated from C to Python by Guido van Rossum.
Version History:
Version 1.1 corrects two bugs in version 1.0:
First, it leaked memory: in Proc1(), NextRecord ends
up having a pointer to itself. I have corrected this
by zapping NextRecord.PtrComp at the end of Proc1().
Second, Proc3() used the operator != to compare a
record to None. This is rather inefficient and not
true to the intention of the original benchmark (where
a pointer comparison to None is intended; the !=
operator attempts to find a method __cmp__ to do value
comparison of the record). Version 1.1 runs 5-10
percent faster than version 1.0, so benchmark figures
of different versions can't be compared directly.
"""
LOOPS = 500000
import time # from time import clock
__version__ = "1.1"
[Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6)
class Record:
def __init__(self, PtrComp=None, Discr=0, EnumComp=0, IntComp=0, StringComp=0):
self.PtrComp = PtrComp
self.Discr = Discr
self.EnumComp = EnumComp
self.IntComp = IntComp
self.StringComp = StringComp
def copy(self):
return Record(
self.PtrComp, self.Discr, self.EnumComp, self.IntComp, self.StringComp
)
TRUE = 1
FALSE = 0
def main(loops=LOOPS):
benchtime, stones = pystones(loops)
print("Pystone(%s) time for %d passes = %g" % (__version__, loops, benchtime))
print("This machine benchmarks at %g pystones/second" % stones)
def pystones(loops=LOOPS):
return Proc0(loops)
IntGlob = 0
BoolGlob = FALSE
Char1Glob = "\0"
Char2Glob = "\0"
Array1Glob = [0] * 51
Array2Glob = [x[:] for x in [Array1Glob] * 51]
PtrGlb = None
PtrGlbNext = None
def Proc0(loops=LOOPS):
global IntGlob
global BoolGlob
global Char1Glob
global Char2Glob
global Array1Glob
global Array2Glob
global PtrGlb
global PtrGlbNext
starttime = time.perf_counter()
for i in range(loops):
pass
nulltime = time.perf_counter() - starttime
PtrGlbNext = Record()
PtrGlb = Record()
PtrGlb.PtrComp = PtrGlbNext
PtrGlb.Discr = Ident1
PtrGlb.EnumComp = Ident3
PtrGlb.IntComp = 40
PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING"
String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING"
Array2Glob[8][7] = 10
starttime = time.perf_counter()
for i in range(loops):
Proc5()
Proc4()
IntLoc1 = 2
IntLoc2 = 3
String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING"
EnumLoc = Ident2
BoolGlob = not Func2(String1Loc, String2Loc)
while IntLoc1 < IntLoc2:
IntLoc3 = 5 * IntLoc1 - IntLoc2
IntLoc3 = Proc7(IntLoc1, IntLoc2)
IntLoc1 = IntLoc1 + 1
Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3)
PtrGlb = Proc1(PtrGlb)
CharIndex = "A"
while CharIndex <= Char2Glob:
if EnumLoc == Func1(CharIndex, "C"):
EnumLoc = Proc6(Ident1)
CharIndex = chr(ord(CharIndex) + 1)
IntLoc3 = IntLoc2 * IntLoc1
IntLoc2 = IntLoc3 / IntLoc1
IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1
IntLoc1 = Proc2(IntLoc1)
benchtime = time.perf_counter() - starttime - nulltime
if benchtime == 0.0:
loopsPerBenchtime = 0.0
else:
loopsPerBenchtime = loops / benchtime
return benchtime, loopsPerBenchtime
def Proc1(PtrParIn):
PtrParIn.PtrComp = NextRecord = PtrGlb.copy()
PtrParIn.IntComp = 5
NextRecord.IntComp = PtrParIn.IntComp
NextRecord.PtrComp = PtrParIn.PtrComp
NextRecord.PtrComp = Proc3(NextRecord.PtrComp)
if NextRecord.Discr == Ident1:
NextRecord.IntComp = 6
NextRecord.EnumComp = Proc6(PtrParIn.EnumComp)
NextRecord.PtrComp = PtrGlb.PtrComp
NextRecord.IntComp = Proc7(NextRecord.IntComp, 10)
else:
PtrParIn = NextRecord.copy()
NextRecord.PtrComp = None
return PtrParIn
def Proc2(IntParIO):
IntLoc = IntParIO + 10
while 1:
if Char1Glob == "A":
IntLoc = IntLoc - 1
IntParIO = IntLoc - IntGlob
EnumLoc = Ident1
if EnumLoc == Ident1:
break
return IntParIO
def Proc3(PtrParOut):
global IntGlob
if PtrGlb is not None:
PtrParOut = PtrGlb.PtrComp
else:
IntGlob = 100
PtrGlb.IntComp = Proc7(10, IntGlob)
return PtrParOut
def Proc4():
global Char2Glob
BoolLoc = Char1Glob == "A"
BoolLoc = BoolLoc or BoolGlob
Char2Glob = "B"
def Proc5():
global Char1Glob
global BoolGlob
Char1Glob = "A"
BoolGlob = FALSE
def Proc6(EnumParIn):
EnumParOut = EnumParIn
if not Func3(EnumParIn):
EnumParOut = Ident4
if EnumParIn == Ident1:
EnumParOut = Ident1
elif EnumParIn == Ident2:
if IntGlob > 100:
EnumParOut = Ident1
else:
EnumParOut = Ident4
elif EnumParIn == Ident3:
EnumParOut = Ident2
elif EnumParIn == Ident4:
pass
elif EnumParIn == Ident5:
EnumParOut = Ident3
return EnumParOut
def Proc7(IntParI1, IntParI2):
IntLoc = IntParI1 + 2
IntParOut = IntParI2 + IntLoc
return IntParOut
def Proc8(Array1Par, Array2Par, IntParI1, IntParI2):
global IntGlob
IntLoc = IntParI1 + 5
Array1Par[IntLoc] = IntParI2
Array1Par[IntLoc + 1] = Array1Par[IntLoc]
Array1Par[IntLoc + 30] = IntLoc
for IntIndex in range(IntLoc, IntLoc + 2):
Array2Par[IntLoc][IntIndex] = IntLoc
Array2Par[IntLoc][IntLoc - 1] = Array2Par[IntLoc][IntLoc - 1] + 1
Array2Par[IntLoc + 20][IntLoc] = Array1Par[IntLoc]
IntGlob = 5
def Func1(CharPar1, CharPar2):
CharLoc1 = CharPar1
CharLoc2 = CharLoc1
if CharLoc2 != CharPar2:
return Ident1
else:
return Ident2
def Func2(StrParI1, StrParI2):
IntLoc = 1
while IntLoc <= 1:
if Func1(StrParI1[IntLoc], StrParI2[IntLoc + 1]) == Ident1:
CharLoc = "A"
IntLoc = IntLoc + 1
if CharLoc >= "W" and CharLoc <= "Z":
IntLoc = 7
if CharLoc == "X":
return TRUE
else:
if StrParI1 > StrParI2:
IntLoc = IntLoc + 7
return TRUE
else:
return FALSE
def Func3(EnumParIn):
EnumLoc = EnumParIn
if EnumLoc == Ident3:
return TRUE
return FALSE
if __name__ == "__main__":
import sys
def error(msg):
print(msg, end=" ", file=sys.stderr)
print("usage: %s [number_of_loops]" % sys.argv[0], file=sys.stderr)
sys.exit(100)
nargs = len(sys.argv) - 1
if nargs > 1:
error("%d arguments are too many;" % nargs)
elif nargs == 1:
try:
loops = int(sys.argv[1])
except ValueError:
error("Invalid argument %r;" % sys.argv[1])
else:
loops = LOOPS
main(loops)
================================================
FILE: demo_torch_jit.py
================================================
"""Test script to verify PyTorch JIT profiling works with Scalene."""
import torch
@torch.jit.script
def compute_intensive(x: torch.Tensor) -> torch.Tensor:
"""A compute-intensive JIT-compiled function."""
for _ in range(50):
x = x @ x.T # Line 9: matrix multiplication
x = torch.relu(x) # Line 10: relu
x = x / x.max() # Line 11: normalize
return x
def main():
print("Testing PyTorch JIT profiling with Scalene...")
x = torch.randn(500, 500)
print(f"Running compute_intensive on 500x500 tensor...")
for i in range(100):
result = compute_intensive(x) # Line 21: call site
print("Testing torch.jit.save/load...")
torch.jit.save(torch.jit.script(compute_intensive), "/tmp/test_model.pt")
loaded = torch.jit.load("/tmp/test_model.pt")
test_result = loaded(torch.randn(10, 10))
print(f"Loaded model output shape: {test_result.shape}")
print("Done!")
if __name__ == "__main__":
main()
================================================
FILE: docs/scalene-demo.ipynb
================================================
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "verbal-arrival",
"metadata": {},
"outputs": [],
"source": [
"# An example program to profile\n",
"\n",
"import numpy as np\n",
"\n",
"def test_me():\n",
" for i in range(6):\n",
" x = np.array(range(10**7))\n",
" y = np.array(np.random.uniform(0, 100, size=(10**8)))\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "lesbian-premium",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The scalene extension is already loaded. To reload it, use:\n",
" %reload_ext scalene\n"
]
}
],
"source": [
"# Load Scalene\n",
"%load_ext scalene"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "listed-keyboard",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
[1]: % of time = 100.00% out of 6.02s. \n",
" ╷ ╷ ╷ ╷ \n",
" Line │Time │–––––– │–––––– │ \n",
" │Python│native│system│[1] \n",
"╺━━━━━━━┿━━━━━━━━┿━━━━━━━┿━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸\n",
" 1 │ │ │ │# An example program to profile \n",
" 2 │ │ │ │ \n",
" 3 │ │ │ │import numpy as np \n",
" 4 │ │ │ │ \n",
" 5 │ │ │ │def test_me(): \n",
" 6 │ │ │ │for i inrange(6): \n",
" 7 │ 1% │ 35% │ 7% │ x = np.array(range(10**7)) \n",
" 8 │ 2% │ 55% │ │ y = np.array(np.random.uniform(0, 100, size=(10**8))) \n",
" │ │ │ │ \n",
"╶───────┼────────┼───────┼───────┼────────────────────────────────────────────────────────────────────────────────────────────────╴\n",
" │ │ │ │function summary for <ipython-input-14-3a53cdc5d2d5> \n",
" 5 │ 3% │ 91% │ 6% │test_me \n",
" ╵ ╵ ╵ ╵ \n",
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Profile just one line of code\n",
"%scrun test_me()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "digital-ratio",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"usage: scalene [-h] [--version] [--outfile OUTFILE] [--html]\n",
" [--reduced-profile] [--profile-interval PROFILE_INTERVAL]\n",
" [--cpu-only] [--profile-all] [--profile-only PROFILE_ONLY]\n",
" [--use-virtual-time]\n",
" [--cpu-percent-threshold CPU_PERCENT_THRESHOLD]\n",
" [--cpu-sampling-rate CPU_SAMPLING_RATE]\n",
" [--malloc-threshold MALLOC_THRESHOLD]\n",
"\n",
"Scalene: a high-precision CPU and memory profiler, version 1.3.2\n",
"https://github.com/plasma-umass/scalene\n",
"\n",
"command-line:\n",
" % scalene [options] yourprogram.py\n",
"or\n",
" % python3 -m scalene [options] yourprogram.py\n",
"\n",
"in Jupyter, line mode:\n",
" %scrun [options] statement\n",
"\n",
"in Jupyter, cell mode:\n",
" %%scalene [options]\n",
" code...\n",
" code...\n",
"\n",
"optional arguments:\n",
" -h, --help show this help message and exit\n",
" --version prints the version number for this release of Scalene and exits\n",
" --outfile OUTFILE file to hold profiler output (default: stdout)\n",
" --html output as HTML (default: text)\n",
" --reduced-profile generate a reduced profile, with non-zero lines only (default: False)\n",
" --profile-interval PROFILE_INTERVAL\n",
" output profiles every so many seconds (default: inf)\n",
" --cpu-only only profile CPU time (default: profile CPU, memory, and copying)\n",
" --profile-all profile all executed code, not just the target program (default: only the target program)\n",
" --profile-only PROFILE_ONLY\n",
" profile only code in files matching the given strings, separated by commas (default: no restrictions)\n",
" --use-virtual-time measure only CPU time, not time spent in I/O or blocking (default: False)\n",
" --cpu-percent-threshold CPU_PERCENT_THRESHOLD\n",
" only report profiles with at least this percent of CPU time (default: 1%)\n",
" --cpu-sampling-rate CPU_SAMPLING_RATE\n",
" CPU sampling rate (default: every 0.01s)\n",
" --malloc-threshold MALLOC_THRESHOLD\n",
" only report profiles with at least this many allocations (default: 100)\n",
"\n",
"When running Scalene in the background, you can suspend/resume profiling\n",
"for the process ID that Scalene reports. For example:\n",
"\n",
" % python3 -m scalene [options] yourprogram.py &\n",
" Scalene now profiling process 12345\n",
" to suspend profiling: python3 -m scalene.profile --off --pid 12345\n",
" to resume profiling: python3 -m scalene.profile --on --pid 12345\n"
]
}
],
"source": [
"# A full list of options\n",
"%scrun --help"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "radio-feelings",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%scalene --reduced-profile\n",
"# Profile more than one line of code in a cell\n",
"x = 0\n",
"for i in range(1000):\n",
" for j in range(1000):\n",
" x += 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "hungry-yesterday",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
================================================
FILE: index.rst
================================================
.. figure::
https://github.com/plasma-umass/scalene/raw/master/docs/scalene-icon-white.png
:alt: scalene
scalene
Scalene: a Python CPU+GPU+memory profiler with AI-powered optimization proposals
================================================================================
by `Emery Berger `__, `Sam
Stern `__, and `Juan Altmayer
Pizzorno `__.
|Scalene community Slack|\ `Scalene community
Slack `__
|PyPI Latest Release|\ |Anaconda-Server Badge| |Downloads|\ |Anaconda
downloads| |image1| |Python versions|\ |Visual Studio Code Extension
version| |License|
.. figure::
https://github.com/plasma-umass/scalene/raw/master/docs/Ozsvald-tweet.png
:alt: Ozsvald tweet
Ozsvald tweet
(tweet from Ian Ozsvald, author of `High Performance
Python `__)
.. figure::
https://github.com/plasma-umass/scalene/raw/master/docs/semantic-scholar-success.png
:alt: Semantic Scholar success story
Semantic Scholar success story
**Scalene web-based user interface:**
http://plasma-umass.org/scalene-gui/
About Scalene
-------------
Scalene is a high-performance CPU, GPU *and* memory profiler for Python
that does a number of things that other Python profilers do not and
cannot do. It runs orders of magnitude faster than many other profilers
while delivering far more detailed information. It is also the first
profiler ever to incorporate AI-powered proposed optimizations.
AI-powered optimization suggestions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Note**
To enable AI-powered optimization suggestions, you need to enter an
`OpenAI key `__ in the box under “Advanced
options”. *Your account will need to have a positive balance for this
to work* (check your balance at
https://platform.openai.com/account/usage).
Once you’ve entered your OpenAI key (see above), click on the lightning
bolt (⚡) beside any line or the explosion (💥) for an entire region of
code to generate a proposed optimization. Click on a proposed
optimization to copy it to the clipboard.
You can click as many times as you like on the lightning bolt or
explosion, and it will generate different suggested optimizations. Your
mileage may vary, but in some cases, the suggestions are quite
impressive (e.g., order-of-magnitude improvements).
Quick Start
~~~~~~~~~~~
Installing Scalene:
^^^^^^^^^^^^^^^^^^^
.. code:: console
python3 -m pip install -U scalene
or
.. code:: console
conda install -c conda-forge scalene
Using Scalene:
^^^^^^^^^^^^^^
After installing Scalene, you can use Scalene at the command line, or as
a Visual Studio Code extension.
.. raw:: html
.. raw:: html
Using the Scalene VS Code Extension:
.. raw:: html
First, install the Scalene extension from the VS Code Marketplace or by
searching for it within VS Code by typing Command-Shift-X (Mac) or
Ctrl-Shift-X (Windows). Once that’s installed, click Command-Shift-P or
Ctrl-Shift-P to open the Command Palette. Then select “Scalene:
AI-powered profiling…” (you can start typing Scalene and it will pop up
if it’s installed). Run that and, assuming your code runs for at least a
second, a Scalene profile will appear in a webview.
.. raw:: html
.. raw:: html
.. raw:: html
Commonly used command-line options:
.. raw:: html
Scalene uses a verb-based command structure with two main commands: ``run`` (to profile) and ``view`` (to display results).
.. code:: console
# Profile a program (saves to scalene-profile.json)
scalene run your_prog.py
python3 -m scalene run your_prog.py # equivalent alternative
# View a profile
scalene view # open profile in browser
scalene view --cli # view in terminal
scalene view --html # save to scalene-profile.html
# Common profiling options
scalene run --cpu-only your_prog.py # only profile CPU (faster)
scalene run -o results.json your_prog.py # custom output filename
scalene run -c config.yaml your_prog.py # load options from config file
# Pass arguments to your program (use --- separator)
scalene run your_prog.py --- --arg1 --arg2
# Get help
scalene --help # main help
scalene run --help # profiling options
scalene run --help-advanced # advanced profiling options
scalene view --help # viewing options
.. raw:: html
.. raw:: html
.. raw:: html
Using Scalene programmatically in your code:
.. raw:: html
Invoke using ``scalene`` as above and then:
.. code:: python
from scalene import scalene_profiler
# Turn profiling on
scalene_profiler.start()
# your code
# Turn profiling off
scalene_profiler.stop()
.. code:: python
from scalene.scalene_profiler import enable_profiling
with enable_profiling():
# do something
.. raw:: html
.. raw:: html
.. raw:: html
Using Scalene to profile only specific functions via @profile:
.. raw:: html
Just preface any functions you want to profile with the ``@profile``
decorator and run it with Scalene:
.. code:: python
# do not import profile!
@profile
def slow_function():
import time
time.sleep(3)
.. raw:: html
Web-based GUI
^^^^^^^^^^^^^
Scalene has both a CLI and a web-based GUI `(demo
here) `__.
By default, once Scalene has profiled your program, it will open a tab
in a web browser with an interactive user interface (all processing is
done locally). Hover over bars to see breakdowns of CPU and memory
consumption, and click on underlined column headers to sort the columns.
The generated file ``profile.html`` is self-contained and can be saved
for later use.
|Scalene web GUI|
Scalene Overview
----------------
Scalene talk (PyCon US 2021)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`This talk `__ presented at PyCon 2021
walks through Scalene’s advantages and how to use it to debug the
performance of an application (and provides some technical details on
its internals). We highly recommend watching this video!
|Scalene presentation at PyCon 2021|
Fast and Accurate
~~~~~~~~~~~~~~~~~
- Scalene is **fast**. It uses sampling instead of instrumentation or
relying on Python’s tracing facilities. Its overhead is typically no
more than 10-20% (and often less).
- Scalene is **accurate**. We tested CPU profiler accuracy and found
that Scalene is among the most accurate profilers, correctly
measuring time taken.
.. figure::
https://github.com/plasma-umass/scalene/raw/master/docs/cpu-accuracy-comparison.png
:alt: Profiler accuracy
Profiler accuracy
- Scalene performs profiling **at the line level** *and* **per
function**, pointing to the functions and the specific lines of code
responsible for the execution time in your program.
CPU profiling
~~~~~~~~~~~~~
- Scalene **separates out time spent in Python from time in native
code** (including libraries). Most Python programmers aren’t going to
optimize the performance of native code (which is usually either in
the Python implementation or external libraries), so this helps
developers focus their optimization efforts on the code they can
actually improve.
- Scalene **highlights hotspots** (code accounting for significant
percentages of CPU time or memory allocation) in red, making them
even easier to spot.
- Scalene also separates out **system time**, making it easy to find
I/O bottlenecks.
GPU profiling
~~~~~~~~~~~~~
- Scalene reports **GPU time** (currently limited to NVIDIA-based
systems).
Memory profiling
~~~~~~~~~~~~~~~~
- Scalene **profiles memory usage**. In addition to tracking CPU usage,
Scalene also points to the specific lines of code responsible for
memory growth. It accomplishes this via an included specialized
memory allocator.
- Scalene separates out the percentage of **memory consumed by Python
code vs. native code**.
- Scalene produces **per-line memory profiles**.
- Scalene **identifies lines with likely memory leaks**.
- Scalene **profiles copying volume**, making it easy to spot
inadvertent copying, especially due to crossing Python/library
boundaries (e.g., accidentally converting ``numpy`` arrays into
Python arrays, and vice versa).
Other features
~~~~~~~~~~~~~~
- Scalene can produce **reduced profiles** (via ``--reduced-profile``)
that only report lines that consume more than 1% of CPU or perform at
least 100 allocations.
- Scalene supports ``@profile`` decorators to profile only specific
functions.
- When Scalene is profiling a program launched in the background (via
``&``), you can **suspend and resume profiling**.
Comparison to Other Profilers
=============================
Performance and Features
------------------------
Below is a table comparing the **performance and features** of various
profilers to Scalene.
.. figure::
https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/images/profiler-comparison.png
:alt: Performance and feature comparison
Performance and feature comparison
- **Slowdown**: the slowdown when running a benchmark from the
Pyperformance suite. Green means less than 2x overhead. Scalene’s
overhead is just a 35% slowdown.
Scalene has all of the following features, many of which only Scalene
supports:
- **Lines or functions**: does the profiler report information only for
entire functions, or for every line – Scalene does both.
- **Unmodified Code**: works on unmodified code.
- **Threads**: supports Python threads.
- **Multiprocessing**: supports use of the ``multiprocessing`` library
– *Scalene only*
- **Python vs. C time**: breaks out time spent in Python vs. native
code (e.g., libraries) – *Scalene only*
- **System time**: breaks out system time (e.g., sleeping or performing
I/O) – *Scalene only*
- **Profiles memory**: reports memory consumption per line / function
- **GPU**: reports time spent on an NVIDIA GPU (if present) – *Scalene
only*
- **Memory trends**: reports memory use over time per line / function –
*Scalene only*
- **Copy volume**: reports megabytes being copied per second – *Scalene
only*
- **Detects leaks**: automatically pinpoints lines responsible for
likely memory leaks – *Scalene only*
Output
------
If you include the ``--cli`` option, Scalene prints annotated source
code for the program being profiled (as text, JSON (``--json``), or HTML
(``--html``)) and any modules it uses in the same directory or
subdirectories (you can optionally have it ``--profile-all`` and only
include files with at least a ``--cpu-percent-threshold`` of time). Here
is a snippet from ``pystone.py``.
.. figure::
https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/images/sample-profile-pystone.png
:alt: Example profile
Example profile
- **Memory usage at the top**: Visualized by “sparklines”, memory
consumption over the runtime of the profiled code.
- **“Time Python”**: How much time was spent in Python code.
- **“native”**: How much time was spent in non-Python code (e.g.,
libraries written in C/C++).
- **“system”**: How much time was spent in the system (e.g., I/O).
- **“GPU”**: (not shown here) How much time spent on the GPU, if your
system has an NVIDIA GPU installed.
- **“Memory Python”**: How much of the memory allocation happened on
the Python side of the code, as opposed to in non-Python code (e.g.,
libraries written in C/C++).
- **“net”**: Positive net memory numbers indicate total memory
allocation in megabytes; negative net memory numbers indicate memory
reclamation.
- **“timeline / %”**: Visualized by “sparklines”, memory consumption
generated by this line over the program runtime, and the percentages
of total memory activity this line represents.
- **“Copy (MB/s)”**: The amount of megabytes being copied per second
(see “About Scalene”).
Scalene
-------
The following command runs Scalene on a provided example program.
.. code:: console
scalene test/testme.py
.. raw:: html
.. raw:: html
Click to see all Scalene’s options (available by running with –help)
.. raw:: html
.. code:: console
% scalene --help
Scalene: a high-precision CPU and memory profiler
https://github.com/plasma-umass/scalene
commands:
run Profile a Python program (saves to scalene-profile.json)
view View an existing profile in browser or terminal
examples:
% scalene run your_program.py # profile, save to scalene-profile.json
% scalene view # view scalene-profile.json in browser
% scalene view --cli # view profile in terminal
in Jupyter, line mode:
%scrun [options] statement
in Jupyter, cell mode:
%%scalene [options]
your code here
% scalene run --help
Profile a Python program with Scalene.
examples:
% scalene run prog.py # profile, save to scalene-profile.json
% scalene run -o my.json prog.py # save to custom file
% scalene run --cpu-only prog.py # profile CPU only (faster)
% scalene run -c scalene.yaml prog.py # load options from config file
% scalene run prog.py --- --arg # pass args to program
% scalene run --help-advanced # show advanced options
options:
-h, --help show this help message and exit
-o, --outfile OUTFILE output file (default: scalene-profile.json)
--cpu-only only profile CPU time (no memory/GPU)
-c, --config FILE load options from YAML config file
--help-advanced show advanced options
% scalene run --help-advanced
Advanced options for scalene run:
background profiling:
Use --off to start with profiling disabled, then control from another terminal:
% scalene run --off prog.py # start with profiling off
% python3 -m scalene.profile --on --pid # resume profiling
% python3 -m scalene.profile --off --pid # suspend profiling
options:
--profile-all profile all code, not just the target program
--profile-only PATH only profile files containing these strings (comma-separated)
--profile-exclude PATH exclude files containing these strings (comma-separated)
--profile-system-libraries profile Python stdlib and installed packages (default: skip)
--gpu profile GPU time and memory
--memory profile memory usage
--stacks collect stack traces
--profile-interval N output profiles every N seconds (default: inf)
--use-virtual-time measure only CPU time, not I/O or blocking
--cpu-percent-threshold N only report lines with at least N% CPU (default: 1%)
--cpu-sampling-rate N CPU sampling rate in seconds (default: 0.01)
--malloc-threshold N only report lines with at least N allocations (default: 100)
--memory-leak-detector EXPERIMENTAL: report likely memory leaks
--on start with profiling on (default)
--off start with profiling off
% scalene view --help
View an existing Scalene profile.
examples:
% scalene view # open in browser
% scalene view --cli # view in terminal
% scalene view --html # save to scalene-profile.html
% scalene view myprofile.json # open specific profile in browser
options:
-h, --help show this help message and exit
--cli display profile in the terminal
--html save to scalene-profile.html (no browser)
-r, --reduced only show lines with activity (--cli mode)
.. raw:: html
Scalene with Jupyter
~~~~~~~~~~~~~~~~~~~~
.. raw:: html
.. raw:: html
Instructions for installing and using Scalene with Jupyter notebooks
.. raw:: html
`This
notebook `__
illustrates the use of Scalene in Jupyter.
Installation:
.. code:: console
!pip install scalene
%load_ext scalene
Line mode:
.. code:: console
%scrun [options] statement
Cell mode:
.. code:: console
%%scalene [options]
code...
code...
.. raw:: html
Installation
------------
.. raw:: html
.. raw:: html
Using pip (Mac OS X, Linux, Windows, and WSL2)
.. raw:: html
Scalene is distributed as a ``pip`` package and works on Mac OS X, Linux
(including Ubuntu in `Windows
WSL2 `__) and
(with limitations) Windows platforms.
**Note**
The Windows version currently only supports CPU and GPU profiling,
but not memory or copy profiling.
You can install it as follows:
.. code:: console
% pip install -U scalene
or
.. code:: console
% python3 -m pip install -U scalene
You may need to install some packages first.
See https://stackoverflow.com/a/19344978/4954434 for full instructions
for all Linux flavors.
For Ubuntu/Debian:
.. code:: console
% sudo apt install git python3-all-dev
.. raw:: html
.. raw:: html
.. raw:: html
Using conda (Mac OS X, Linux, Windows, and WSL2)
.. raw:: html
.. code:: console
% conda install -c conda-forge scalene
Scalene is distributed as a ``conda`` package and works on Mac OS X,
Linux (including Ubuntu in `Windows
WSL2 `__) and
(with limitations) Windows platforms.
**Note**
The Windows version currently only supports CPU and GPU profiling,
but not memory or copy profiling.
.. raw:: html
.. raw:: html
.. raw:: html
On ArchLinux
.. raw:: html
You can install Scalene on Arch Linux via the `AUR
package `__. Use
your favorite AUR helper, or manually download the ``PKGBUILD`` and run
``makepkg -cirs`` to build. Note that this will place ``libscalene.so``
in ``/usr/lib``; modify the below usage instructions accordingly.
.. raw:: html
Frequently Asked Questions
==========================
.. raw:: html
.. raw:: html
Can I use Scalene with PyTest?
.. raw:: html
**A:** Yes! You can run it as follows (for example):
``scalene run -m pytest your_test.py``
.. raw:: html
.. raw:: html
.. raw:: html
Is there any way to get shorter profiles or do more targeted profiling?
.. raw:: html
**A:** Yes! There are several options:
1. Use ``--reduced-profile`` to include only lines and files with
memory/CPU/GPU activity.
2. Use ``--profile-only`` to include only filenames containing specific
strings (as in, ``--profile-only foo,bar,baz``).
3. Decorate functions of interest with ``@profile`` to have Scalene
report *only* those functions.
4. Turn profiling on and off programmatically by importing Scalene
profiler (``from scalene import scalene_profiler``) and then turning
profiling on and off via ``scalene_profiler.start()`` and
``scalene_profiler.stop()``. By default, Scalene runs with profiling
on, so to delay profiling until desired, use the ``--off``
command-line option (``scalene run --off yourprogram.py``).
.. raw:: html
.. raw:: html
.. raw:: html
How do I run Scalene in PyCharm?
.. raw:: html
**A:** In PyCharm, you can run Scalene at the command line by opening
the terminal at the bottom of the IDE and running a Scalene command
(e.g., ``scalene run ``). Then use ``scalene view --html``
to generate an HTML file (``scalene-profile.html``) that you can view in the IDE.
.. raw:: html
.. raw:: html
.. raw:: html
How do I use Scalene with Django?
.. raw:: html
**A:** Pass in the ``--noreload`` option (see
https://github.com/plasma-umass/scalene/issues/178).
.. raw:: html
.. raw:: html
.. raw:: html
Does Scalene work with gevent/Greenlets?
.. raw:: html
**A:** Yes! Put the following code in the beginning of your program, or
modify the call to ``monkey.patch_all`` as below:
.. code:: python
from gevent import monkey
monkey.patch_all(thread=False)
.. raw:: html
.. raw:: html
.. raw:: html
How do I use Scalene with PyTorch on the Mac?
.. raw:: html
**A:** Scalene works with PyTorch version 1.5.1 on Mac OS X. There’s a
bug in newer versions of PyTorch
(https://github.com/pytorch/pytorch/issues/57185) that interferes with
Scalene (discussion here:
https://github.com/plasma-umass/scalene/issues/110), but only on Macs.
.. raw:: html
Technical Information
=====================
For details about how Scalene works, please see the following paper,
which won the Jay Lepreau Best Paper Award at `OSDI
2023 `__:
`Triangulating Python Performance Issues with
Scalene `__. (Note that this paper
does not include information about the AI-driven proposed
optimizations.)
.. raw:: html
.. raw:: html
To cite Scalene in an academic paper, please use the following:
.. raw:: html
.. code:: latex
@inproceedings{288540,
author = {Emery D. Berger and Sam Stern and Juan Altmayer Pizzorno},
title = {Triangulating Python Performance Issues with {S}calene},
booktitle = {{17th USENIX Symposium on Operating Systems Design and Implementation (OSDI 23)}},
year = {2023},
isbn = {978-1-939133-34-2},
address = {Boston, MA},
pages = {51--64},
url = {https://www.usenix.org/conference/osdi23/presentation/berger},
publisher = {USENIX Association},
month = jul
}
.. raw:: html
Success Stories
===============
If you use Scalene to successfully debug a performance problem, please
`add a comment to this
issue `__!
Acknowledgements
================
Logo created by `Sophia
Berger `__.
This material is based upon work supported by the National Science
Foundation under Grant No. 1955610. Any opinions, findings, and
conclusions or recommendations expressed in this material are those of
the author(s) and do not necessarily reflect the views of the National
Science Foundation.
.. |Scalene community Slack| image:: https://github.com/plasma-umass/scalene/raw/master/docs/images/slack-logo.png
:target: https://join.slack.com/t/scaleneprofil-jge3234/shared_invite/zt-110vzrdck-xJh5d4gHnp5vKXIjYD3Uwg
.. |PyPI Latest Release| image:: https://img.shields.io/pypi/v/scalene.svg
:target: https://pypi.org/project/scalene/
.. |Anaconda-Server Badge| image:: https://img.shields.io/conda/v/conda-forge/scalene
:target: https://anaconda.org/conda-forge/scalene
.. |Downloads| image:: https://static.pepy.tech/badge/scalene
:target: https://pepy.tech/project/scalene
.. |Anaconda downloads| image:: https://img.shields.io/conda/d/conda-forge/scalene?logo=conda
:target: https://anaconda.org/conda-forge/scalene
.. |image1| image:: https://static.pepy.tech/badge/scalene/month
:target: https://pepy.tech/project/scalene
.. |Python versions| image:: https://img.shields.io/pypi/pyversions/scalene.svg?style=flat-square
.. |Visual Studio Code Extension version| image:: https://img.shields.io/visual-studio-marketplace/v/emeryberger.scalene?logo=visualstudiocode
:target: https://marketplace.visualstudio.com/items?itemName=EmeryBerger.scalene
.. |License| image:: https://img.shields.io/github/license/plasma-umass/scalene
.. |Scalene web GUI| image:: https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/scalene-gui-example.png
:target: https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/scalene-gui-example-full.png
.. |Scalene presentation at PyCon 2021| image:: https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/images/scalene-video-img.png
:target: https://youtu.be/5iEf-_7mM1k
================================================
FILE: mypy.ini
================================================
[mypy]
scripts_are_modules = True
show_traceback = True
plugins = pydantic.mypy
# Options to make the checking stricter.
check_untyped_defs = True
disallow_any_unimported = True
disallow_untyped_defs = True
disallow_any_generics = True
warn_no_return = True
no_implicit_optional = True
warn_return_any = True
disallow_untyped_calls = True
disallow_incomplete_defs = True
warn_redundant_casts = True
# Display the codes needed for # type: ignore[code] annotations.
show_error_codes = True
# It's useful to try this occasionally, and keep it clean; but when
# someone fixes a type error we don't want to add a burden for them.
warn_unused_ignores = True
# We use a lot of third-party libraries we don't have stubs for, as
# well as a handful of our own modules that we haven't told mypy how
# to find. Ignore them. (For some details, see:
# `git log -p -S ignore_missing_imports mypy.ini`.)
#
# This doesn't get in the way of using the stubs we *do* have.
ignore_missing_imports = True
# Warn of unreachable or redundant code.
warn_unreachable = False
# was True
strict_optional = True
================================================
FILE: pyproject.toml
================================================
[project]
name = "scalene"
description = "Scalene: A high-resolution, low-overhead CPU, GPU, and memory profiler for Python with AI-powered optimization suggestions"
readme = "README.md"
keywords = ["performance", "profiler", "optimization", "CPU", "GPU", "memory", "LLM"]
authors = [
{name = "Emery Berger", email = "emery@cs.umass.edu"},
{name = "Sam Stern", email = "jstern@umass.edu"},
{name = "Juan Altmayer Pizzorno", email = "juan@altmayer.com"},
]
requires-python = ">=3.8,!=3.11.0"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: IPython",
"Framework :: Jupyter",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"Topic :: Software Development",
"Topic :: Software Development :: Debuggers",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"License :: OSI Approved :: Apache Software License",
"Operating System :: POSIX :: Linux",
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows"
]
# see https://peps.python.org/pep-0508/#environment-markers for conditional syntax
dependencies = [
"rich>=10.7.0",
"cloudpickle>=2.2.1",
# "pynvml>=11.0.0,<=11.5",
"nvidia-ml-py>=12.555.43; platform_system !='Darwin'",
"Jinja2>=3.0.3",
"psutil>=5.9.2",
"numpy>=1.24.0,!=1.27; python_version < '3.14'",
"numpy>=2.3.4; python_version >= '3.14'",
"astunparse>=1.6.3; python_version < '3.9'",
"pydantic>=2.6",
"pyyaml>=6.0",
]
dynamic = ["version"] # computed by setup.py
[project.optional-dependencies]
test = [
"pytest>=7.0",
"pytest-asyncio>=0.21",
"hypothesis>=6.0",
# TensorFlow for testing library profiler integration
# TensorFlow doesn't support Python 3.14+ yet
"tensorflow>=2.15; python_version < '3.14' and platform_system != 'Windows'",
# JAX for testing library profiler integration
# JAX doesn't support Windows
"jax>=0.4.20; python_version < '3.14' and platform_system != 'Windows'",
"jaxlib>=0.4.20; python_version < '3.14' and platform_system != 'Windows'",
]
[project.urls]
"Homepage" = "https://github.com/plasma-umass/scalene"
"Repository" = "https://github.com/plasma-umass/scalene"
[project.scripts]
scalene = "scalene.__main__:main"
[build-system]
build-backend = "setuptools.build_meta"
requires = [
"setuptools>=70.1",
"setuptools_scm>=8",
"cython",
]
================================================
FILE: pyrightconfig.json
================================================
{
"include": ["scalene"],
"useLibraryCodeForTypes": true,
"reportInvalidStringEscapeSequence": false,
"typeCheckingMode" : "basic"
}
================================================
FILE: pytest.ini
================================================
[tool:pytest]
norecursedirs = tests/*
================================================
FILE: refactoring_todo.md
================================================
# Scalene Profiler Refactoring Plan
## Goal
Refactor `scalene/scalene_profiler.py` into multiple files with clear separation of concerns.
## Status: ✅ COMPLETE
All verification checks pass:
- `pytest tests/` - 147 tests passed
- `mypy scalene` - No issues found
- `ruff check scalene` - All checks passed
## File Sizes
| File | Lines |
|------|-------|
| `scalene_profiler.py` | 1,584 (was 1,885) |
| `scalene_cpu_profiler.py` | 228 (new) |
| `scalene_tracing.py` | 225 (new) |
| `scalene_lifecycle.py` | 198 (new) |
**Net reduction**: ~300 lines from main profiler, with reusable logic extracted
## New Modules Created
### 1. `scalene_cpu_profiler.py` ✅
- **Class**: `ScaleneCPUProfiler`
- **Purpose**: CPU profiling sample processing
- **Key methods**:
- `process_cpu_sample` - Main CPU sample handler
- `_update_main_thread_stats` - Main thread statistics
- `_update_thread_stats` - Other thread statistics
### 2. `scalene_tracing.py` ✅
- **Class**: `ScaleneTracing`
- **Purpose**: Tracing decisions and file filtering with `lru_cache`
- **Key methods**:
- `should_trace` - Main entry point (cached)
- `_passes_exclusion_rules` - Library exclusions
- `_should_trace_by_location` - Path-based filtering
- `_is_system_library` - System library detection
### 3. `scalene_lifecycle.py` ✅
- **Class**: `ScaleneLifecycle`
- **Purpose**: Profiler lifecycle management (prepared for future use)
## Architecture
```
scalene_profiler.py (Scalene class)
├── ScaleneCPUProfiler (CPU sample processing)
├── ScaleneTracing (file/function filtering)
├── ScaleneMemoryProfiler (already existed)
└── ScaleneSignalManager (already existed)
```
## Completed Tasks
- [x] Extracted CPU profiling logic (~150 lines)
- [x] Extracted tracing/filtering logic (~150 lines)
- [x] Created lifecycle module for future use
- [x] Updated type signatures to use `Filename` consistently
- [x] Applied proper `lru_cache` usage
- [x] All tests passing (147/147)
- [x] Type checking passing (mypy)
- [x] Linting passing (ruff)
================================================
FILE: requirements.txt
================================================
astunparse>=1.6.3; python_version < '3.9'
cloudpickle>=2.2.1
Cython>=0.29.28
ipython>=8.10
Jinja2>=3.0.3
lxml>=5.1.0
packaging>=24
psutil>=5.9.2
pyperf>=2.0.0
rich>=10.7.0
setuptools>=65.5.1
nvidia-ml-py>=12.555.43; platform_system !='Darwin'
wheel>=0.43.0
# Per https://github.com/pypa/setuptools/issues/4483#issuecomment-2236528158
ordered-set>=3.1.1
more_itertools>=8.8
jaraco.text>=3.7
importlib_resources>=5.10.2
importlib_metadata>=6
tomli>=2.0.1
platformdirs >= 2.6.2
================================================
FILE: ruff.toml
================================================
line-length = 88
indent-width = 4
exclude = ["test", "tests", "node_modules", "benchmarks"]
[lint]
select = ["E", "F", "B", "I", "SIM", "UP"]
ignore = ["E101", "E402", "E501", "E701", "E741", "F401", "F403", "F405", "B028"]
================================================
FILE: scalene/README.md
================================================
### Helper functions:
* `adaptive.py`:
`Adaptive` maintains samples used for memory footprint sparklines.
* `profile.py`:
used to suspend/resume profiling of Scalene when run in the background (with `&`).
* `replacement_*.py`:
Scalene needs to interpose on a variety of functions; this functionality is in these files.
* `runningstats.py`:
`RunningStats` takes input samples and incrementally computes average and other statistics in a fixed amount of space.
* `sparkline.py`:
Functions to generate sparklines, used to display memory consumption over time.
* `syntaxline.py`:
A helper function for pretty-printing with the Rich library.
### Core Scalene functions:
* `scalene_arguments.py`:
`ScaleneArguments` holds command-line arguments and their default values.
* `scalene_cpu_profiler.py`:
`ScaleneCPUProfiler` handles CPU profiling sample processing, including main thread and background thread statistics collection. Extracted from `scalene_profiler.py` for separation of concerns.
* `scalene_gpu.py`:
`ScaleneGPU` wraps the NVIDIA library to conveniently provide access to GPU statistics required by Scalene.
* `scalene_lifecycle.py`:
`ScaleneLifecycle` manages profiler lifecycle operations including start, stop, and signal management.
* `scalene_magics.py`:
Sets up the "magics" for using Scalene within Jupyter notebooks (`%scrun` and `%%scalene`).
* `scalene_memory_profiler.py`:
`ScaleneMemoryProfiler` handles memory profiling sample processing for malloc, free, and memcpy operations.
* `scalene_output.py`:
`ScaleneOutput` encapsulates functions used for generating Scalene's profiles either as text or HTML.
* `scalene_profiler.py`:
The core of the Scalene profiler. Coordinates CPU, memory, and GPU profiling by delegating to specialized modules (`ScaleneCPUProfiler`, `ScaleneTracing`, `ScaleneMemoryProfiler`).
* `scalene_signals.py`:
Defines the Unix signals that Scalene uses (some of which must be kept in sync with `include/sampleheap.hpp`).
* `scalene_statistics.py`:
Operations for managing the statistics generated by Scalene.
* `scalene_tracing.py`:
`ScaleneTracing` handles tracing decisions and file filtering. Determines which files and functions should be profiled based on exclusion rules, profile-only patterns, and system library detection. Uses `lru_cache` for performance.
* `scalene_version.py`:
The version number of Scalene which ultimately is reflected on `pypi` (for `pip` installs, used by `setup.py` in the top level directory).
================================================
FILE: scalene/__init__.py
================================================
# Work around this bug: https://github.com/NVIDIA/cuda-python/issues/29
import os
os.environ["LC_ALL"] = "POSIX"
# Jupyter support
from scalene.scalene_magics import *
================================================
FILE: scalene/__main__.py
================================================
import sys
import traceback
def main() -> None:
try:
from scalene import scalene_profiler
scalene_profiler.Scalene.main()
except SystemExit:
raise
except Exception as exc:
sys.stderr.write(f"ERROR: Calling Scalene main function failed: {exc}\n")
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()
================================================
FILE: scalene/adaptive.py
================================================
from typing import List
class Adaptive:
"""Implements sampling to achieve the effect of a uniform random sample."""
def __init__(self, size: int) -> None:
# size must be a power of two
self.max_samples = size
self.current_index = 0
self.sample_array = [0.0] * size
def __add__(self: "Adaptive", other: "Adaptive") -> "Adaptive":
n = Adaptive(self.max_samples)
for i in range(0, self.max_samples):
n.sample_array[i] = self.sample_array[i] + other.sample_array[i]
n.current_index = max(self.current_index, other.current_index)
return n
def __iadd__(self: "Adaptive", other: "Adaptive") -> "Adaptive":
for i in range(0, self.max_samples):
self.sample_array[i] += other.sample_array[i]
self.current_index = max(self.current_index, other.current_index)
return self
def add(self, value: float) -> None:
if self.current_index >= self.max_samples:
# Decimate
new_array = [0.0] * self.max_samples
for i in range(0, self.max_samples // 3):
arr = [self.sample_array[i * 3 + j] for j in range(0, 3)]
arr.sort()
new_array[i] = arr[1] # Median
self.current_index = self.max_samples // 3
self.sample_array = new_array
self.sample_array[self.current_index] = value
self.current_index += 1
def get(self) -> List[float]:
return self.sample_array
def len(self) -> int:
return self.current_index
================================================
FILE: scalene/find_browser.py
================================================
import webbrowser
from typing import Optional
def find_browser(browserClass: Optional[str] = None) -> Optional[str]:
"""Find the default system browser, excluding text browsers.
If you want a specific browser, pass its class as an argument."""
text_browsers = [
"browsh",
"elinks",
"links",
"lynx",
"w3m",
]
try:
# Get the default browser object
browser = webbrowser.get(browserClass)
browser_name = browser.name if browser.name else browser.__class__.__name__
return browser_name if browser_name not in text_browsers else None
except AttributeError:
# https://github.com/plasma-umass/scalene/issues/790
# https://github.com/python/cpython/issues/105545
# MacOSXOSAScript._name was deprecated but for pre-Python 3.11,
# we need to refer to it as such to prevent this error:
# 'MacOSXOSAScript' object has no attribute 'name'
browser = webbrowser.get(browserClass)
return browser._name if browser._name not in text_browsers else None # type: ignore[attr-defined]
except webbrowser.Error:
# Return None if there is an error in getting the browser
return None
================================================
FILE: scalene/get_module_details.py
================================================
import importlib.util
import sys
from importlib.abc import SourceLoader
from importlib.machinery import ModuleSpec
from types import CodeType
from typing import (
Tuple,
Type,
)
def _get_module_details(
mod_name: str,
error: Type[Exception] = ImportError,
) -> Tuple[str, ModuleSpec, CodeType]:
"""Copy of `runpy._get_module_details`, but not private."""
if mod_name.startswith("."):
raise error("Relative module names not supported")
pkg_name, _, _ = mod_name.rpartition(".")
if pkg_name:
# Try importing the parent to avoid catching initialization errors
try:
__import__(pkg_name)
except ImportError as e:
# If the parent or higher ancestor package is missing, let the
# error be raised by find_spec() below and then be caught. But do
# not allow other errors to be caught.
if e.name is None or (
e.name != pkg_name and not pkg_name.startswith(e.name + ".")
):
raise
# Warn if the module has already been imported under its normal name
existing = sys.modules.get(mod_name)
if existing is not None and not hasattr(existing, "__path__"):
from warnings import warn
msg = (
f"{mod_name!r} found in sys.modules after import of "
f"package {pkg_name!r}, but prior to execution of "
f"{mod_name!r}; this may result in unpredictable "
"behaviour"
)
warn(RuntimeWarning(msg))
try:
spec = importlib.util.find_spec(mod_name)
except (ImportError, AttributeError, TypeError, ValueError) as ex:
# This hack fixes an impedance mismatch between pkgutil and
# importlib, where the latter raises other errors for cases where
# pkgutil previously raised ImportError
msg = "Error while finding module specification for {!r} ({}: {})"
if mod_name.endswith(".py"):
msg += (
f". Try using '{mod_name[:-3]}' instead of "
f"'{mod_name}' as the module name."
)
raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex
if spec is None:
raise error(f"No module named {mod_name}")
if spec.submodule_search_locations is not None:
if mod_name == "__main__" or mod_name.endswith(".__main__"):
raise error("Cannot use package as __main__ module")
try:
pkg_main_name = mod_name + ".__main__"
return _get_module_details(pkg_main_name, error)
except error as e:
if mod_name not in sys.modules:
raise # No module loaded; being a package is irrelevant
raise error(
("%s; %r is a package and cannot " + "be directly executed")
% (e, mod_name)
) from None
loader = spec.loader
# use isinstance instead of `is None` to placate mypy
if not isinstance(loader, SourceLoader):
raise error(f"{mod_name!r} is a namespace package and cannot be executed")
try:
code = loader.get_code(mod_name)
except ImportError as e:
raise error(format(e)) from e
if code is None:
raise error(f"No code object available for {mod_name}")
return mod_name, spec, code
================================================
FILE: scalene/launchbrowser.py
================================================
import http.server
import os
import pathlib
import platform
import shutil
import socket
import socketserver
import sys
import tempfile
import threading
import time
import webbrowser
from typing import Any, NewType
from jinja2 import Environment, FileSystemLoader
def launch_browser_insecure(url: str) -> None:
if platform.system() == "Windows":
chrome_path = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
elif platform.system() == "Linux":
chrome_path = "/usr/bin/google-chrome"
elif platform.system() == "Darwin":
chrome_path = "/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome"
# Create a temporary directory
with tempfile.TemporaryDirectory() as temp_dir:
# Create a command with the required flags
chrome_cmd = (
f'{chrome_path} %s --disable-web-security --user-data-dir="{temp_dir}"'
)
# Register the new browser type
webbrowser.register(
"chrome_with_flags",
None,
webbrowser.Chrome(chrome_cmd),
preferred=True,
)
# Open a URL using the new browser type
webbrowser.get(chrome_cmd).open(url)
HOST = "localhost"
shutdown_requested = False
last_heartbeat = time.time()
server_running = True
class CustomHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self) -> Any:
global last_heartbeat
if self.path == "/heartbeat":
last_heartbeat = time.time()
self.send_response(200)
self.end_headers()
return
else:
return http.server.SimpleHTTPRequestHandler.do_GET(self)
def monitor_heartbeat() -> None:
global server_running
while server_running:
if time.time() - last_heartbeat > 60: # 60 seconds timeout
print("No heartbeat received, shutting down server...")
server_running = False
os._exit(0)
time.sleep(1)
def serve_forever(httpd: Any) -> None:
while server_running:
httpd.handle_request()
def run_server(host: str, port: int) -> None:
with socketserver.TCPServer((host, port), CustomHandler) as httpd:
print(f"Serving at http://{host}:{port}")
serve_forever(httpd)
def is_port_available(port: int) -> bool:
"""
Check if a given TCP port is available to start a server on the local machine.
:param port: Port number as an integer.
:return: True if the port is available, False otherwise.
"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
s.bind(("localhost", port))
return True
except OSError:
return False
Filename = NewType("Filename", str)
LineNumber = NewType("LineNumber", int)
def generate_html(profile_fname: Filename, output_fname: Filename) -> None:
"""Apply a template to generate a single HTML payload containing the current profile."""
try:
# Load the profile
profile_file = pathlib.Path(profile_fname)
profile = profile_file.read_text()
except FileNotFoundError:
assert profile_fname == "demo"
profile = "{}"
# return
scalene_dir = os.path.dirname(__file__)
# Put the profile and everything else into the template.
environment = Environment(
loader=FileSystemLoader(os.path.join(scalene_dir, "scalene-gui"))
)
template = environment.get_template("index.html.template")
try:
import scalene_config
except ModuleNotFoundError:
import scalene.scalene_config as scalene_config
rendered_content = template.render(
profile=profile,
scalene_version=scalene_config.scalene_version,
scalene_date=scalene_config.scalene_date,
api_keys={},
)
# Write the rendered content to the specified output file.
try:
with open(output_fname, "w", encoding="utf-8") as f:
f.write(rendered_content)
except OSError:
pass
def start(filename: str, port: int) -> None:
while not is_port_available(port):
port += 1
cwd = os.getcwd()
if filename == "demo":
generate_html(Filename("demo"), Filename("demo.html"))
filename = "demo.html"
temp_dir = tempfile.gettempdir()
shutil.copy(filename, os.path.join(temp_dir, "index.html"))
# Copy vendored assets for offline support (issue #982)
scalene_gui_dir = os.path.join(os.path.dirname(__file__), "scalene-gui")
for asset in [
"favicon.ico",
"scalene-image.png",
"jquery-3.6.0.slim.min.js",
"bootstrap.min.css",
"bootstrap.bundle.min.js",
"prism.css",
"scalene-gui-bundle.js",
]:
src = os.path.join(scalene_gui_dir, asset)
if os.path.exists(src):
shutil.copy(src, os.path.join(temp_dir, asset))
os.chdir(temp_dir)
server_thread = threading.Thread(target=run_server, args=[HOST, port])
server_thread.start()
threading.Thread(target=monitor_heartbeat).start()
webbrowser.open_new(f"http://{HOST}:{port}/")
server_thread.join()
os.chdir(cwd)
# Optional: a delay to ensure all resources are released
time.sleep(1)
os._exit(0) # Forcefully stops the program
if __name__ == "__main__":
import sys
if len(sys.argv) > 2:
filename = sys.argv[1]
port = int(sys.argv[2])
start(filename, port)
else:
print("Need to supply filename and port arguments.")
================================================
FILE: scalene/merge_scalene_neuron_profiles.py
================================================
#!/usr/bin/env python3
import bisect
import json
import sys
from pathlib import Path
from typing import List, Optional, Tuple
def parse_debug_file_programmatic(
debug_file: str, valid_filenames: List[str]
) -> Tuple[Optional[str], List[Tuple[int, str]]]:
"""Parse debug file programmatically to extract execution data"""
if not Path(debug_file).exists():
return None, []
with open(debug_file) as f:
content = f.read()
# Extract PID
import re
pid_match = re.search(r"PID: (\d+)", content)
pid = pid_match.group(1) if pid_match else None
# Extract source locations
executions = []
sections = content.split("---")
for section in sections:
if not section.strip():
continue
lines = section.strip().split("\n")
source_line = None
kernel_name = None
for line in lines:
if line.startswith("SOURCE: "):
source_info = line[8:] # Remove 'SOURCE: '
if ":" in source_info:
# Check if source matches any of the files in scalene profile
for filename in valid_filenames:
if filename in source_info:
source_line = int(source_info.split(":")[-1])
break
elif line.startswith("KERNEL: "):
kernel_name = line[8:] # Remove 'KERNEL: '
if source_line:
executions.append((source_line, kernel_name or "unknown"))
return pid, executions
def calculate_cpu_sample_overlap(
cpu_samples_list: List[float],
nc_intervals: List[Tuple[float, float]],
start_time_absolute: float,
start_time_perf: float,
) -> Tuple[int, int, float]:
"""Calculate overlap between CPU samples and nc_exec_running intervals
Args:
cpu_samples_list: List of CPU sample timestamps (perf_counter values)
nc_intervals: List of (start_time, end_time) tuples for nc_exec_running events (in seconds)
start_time_absolute: Absolute start time (Unix timestamp in seconds)
start_time_perf: Performance counter start time (in seconds)
Returns:
tuple: (overlap_count, total_count, overlap_percent)
"""
if not cpu_samples_list or not nc_intervals:
return 0, len(cpu_samples_list), 0.0
overlap_count = 0
total_count = len(cpu_samples_list)
# Sort intervals by start time for efficient searching
sorted_intervals = sorted(nc_intervals, key=lambda x: x[0])
for cpu_sample_perf in cpu_samples_list:
# Convert CPU sample to absolute time
cpu_sample_absolute = start_time_absolute + (cpu_sample_perf - start_time_perf)
# Check if CPU sample overlaps with any interval (strict overlap)
for start, end in sorted_intervals:
# Check if CPU sample falls within interval exactly
if start <= cpu_sample_absolute <= end:
overlap_count += 1
break
overlap_percent = (overlap_count / total_count * 100) if total_count > 0 else 0.0
return overlap_count, total_count, overlap_percent
def merge_neuron_into_scalene_programmatic(
scalene_file: str, neuron_file: str, output_file: str, target_rank: int = 0
) -> None:
"""Merge Neuron timing data into Scalene JSON using programmatic kernel execution data"""
# Load Scalene data
try:
with open(scalene_file) as f:
content = f.read().strip()
if "" in content:
json_start = content.find("const profile = ") + len("const profile = ")
if json_start > len("const profile = ") - 1:
brace_count = 0
json_end = json_start
for i, char in enumerate(content[json_start:]):
if char == "{":
brace_count += 1
elif char == "}":
brace_count -= 1
if brace_count == 0:
json_end = json_start + i + 1
break
content = content[json_start:json_end]
scalene_data = json.loads(content)
except json.JSONDecodeError as e:
print(f"Error parsing {scalene_file}: {e}")
return
# Load Neuron trace data
with open(neuron_file) as f:
neuron_data = json.load(f)
# Get timing information from Scalene
start_time_absolute = scalene_data.get("start_time_absolute", 0)
start_time_perf = scalene_data.get("start_time_perf", 0)
# Extract valid filenames from Scalene data
valid_filenames = []
if "files" in scalene_data:
for filename in scalene_data["files"]:
# Extract just the basename for matching
basename = Path(filename).name
valid_filenames.append(basename)
# Get kernel execution data programmatically
debug_file = f"debug_rank_{target_rank}.txt"
target_pid, spike_lines = parse_debug_file_programmatic(debug_file, valid_filenames)
if not spike_lines:
print(f"No kernel execution data found for rank {target_rank}")
return
# Extract events from Neuron trace
events_list = (
neuron_data
if isinstance(neuron_data, list)
else neuron_data.get("trace_event", [])
)
nrt_events = []
kbl_events = []
nc_events = []
nc_intervals = []
for event in events_list:
event_pid = str(event.get("process_id", ""))
if target_pid is None or event_pid == target_pid:
if event.get("name") == "nrt_execute":
nrt_events.append(
{
"name": event.get("name"),
"duration_ns": event.get("duration", 0),
"duration_ms": event.get("duration", 0) / 1000000,
"timestamp": event.get("timestamp", 0),
"process_id": event.get("process_id"),
"thread_id": event.get("thread_id"),
}
)
elif event.get("name") == "kbl_exec_pre":
exec_id = event.get("args", {}).get("exec_id") or event.get("exec_id")
kbl_events.append(
{
"name": event.get("name"),
"exec_id": exec_id,
"timestamp": event.get("timestamp", 0),
"process_id": event.get("process_id"),
"thread_id": event.get("thread_id"),
}
)
# Collect nc_exec_running events for target PID
if event.get("name") == "nc_exec_running" and (
target_pid is None or event_pid == target_pid
):
timestamp_ns = event.get("timestamp", 0)
duration_ns = event.get("duration", 0)
start_time_sec = timestamp_ns / 1e9
end_time_sec = (timestamp_ns + duration_ns) / 1e9
nc_intervals.append((start_time_sec, end_time_sec))
exec_id = event.get("args", {}).get("exec_id") or event.get("exec_id")
nc_events.append(
{
"name": event.get("name"),
"duration_ns": duration_ns,
"duration_ms": duration_ns / 1000000,
"timestamp": timestamp_ns,
"exec_id": exec_id,
"process_id": event.get("process_id"),
"thread_id": event.get("thread_id"),
}
)
nrt_events.sort(key=lambda x: x["timestamp"])
kbl_events.sort(key=lambda x: x["timestamp"])
nc_events.sort(key=lambda x: x["timestamp"])
# Create exec_id to nrt_execute mapping via kbl_exec_pre
exec_id_to_nrt_index = {}
for i, kbl_event in enumerate(kbl_events):
if i < len(nrt_events) and kbl_event["exec_id"] is not None:
exec_id_to_nrt_index[kbl_event["exec_id"]] = i
# Map kernel executions to nrt events by timestamp order
total_neuron_time = sum(event["duration_ms"] for event in nrt_events)
total_nc_time = sum(event["duration_ms"] for event in nc_events)
# Group spike lines by line number
from collections import defaultdict
line_to_events = defaultdict(list)
line_to_nc_events = defaultdict(list)
# Map nrt_execute events to spike lines consecutively
for i, (spike_line, kernel_name) in enumerate(spike_lines):
if i < len(nrt_events):
line_to_events[spike_line].append((nrt_events[i], kernel_name))
# Map nc_exec_running events to spike lines via exec_id
for nc_event in nc_events:
exec_id = nc_event.get("exec_id")
if exec_id in exec_id_to_nrt_index:
nrt_index = exec_id_to_nrt_index[exec_id]
if nrt_index < len(spike_lines):
spike_line, kernel_name = spike_lines[nrt_index]
line_to_nc_events[spike_line].append((nc_event, kernel_name))
# Process CPU sample overlap for all lines
total_cpu_samples_with_overlap = 0
total_cpu_samples = 0
# Add neuron timing to scalene structure
if "files" in scalene_data:
for filename, file_data in scalene_data["files"].items():
if "lines" in file_data:
for line_data in file_data["lines"]:
lineno = line_data.get("lineno")
cpu_samples_list = line_data.get("cpu_samples_list", [])
# Calculate CPU sample overlap with nc_exec_running for ALL lines with CPU samples
if cpu_samples_list and nc_intervals:
overlap_count, total_count, overlap_percent = (
calculate_cpu_sample_overlap(
cpu_samples_list,
nc_intervals,
start_time_absolute,
start_time_perf,
)
)
line_data["cpu_samples_nc_overlap_count"] = overlap_count
line_data["cpu_samples_total_count"] = total_count
line_data["cpu_samples_nc_overlap_percent"] = overlap_percent
total_cpu_samples_with_overlap += overlap_count
total_cpu_samples += total_count
else:
line_data["cpu_samples_nc_overlap_count"] = 0
line_data["cpu_samples_total_count"] = len(cpu_samples_list)
line_data["cpu_samples_nc_overlap_percent"] = 0.0
# Check if this line has neuron events
basename = Path(filename).name
if basename in valid_filenames and lineno in line_to_events:
events_for_line = line_to_events[lineno]
# Sum all events for this line
total_time_ms = sum(
event["duration_ms"] for event, _ in events_for_line
)
all_events = [event for event, _ in events_for_line]
kernel_name = events_for_line[0][
1
] # Use first kernel name as reference
# Process nc_exec_running events for this line
nc_events_for_line = line_to_nc_events.get(lineno, [])
total_nc_time_ms = sum(
event["duration_ms"] for event, _ in nc_events_for_line
)
all_nc_events = [event for event, _ in nc_events_for_line]
# Add neuron timing fields
line_data["nrt_time_ms"] = total_time_ms
line_data["nrt_percent"] = (
(total_time_ms / total_neuron_time) * 100
if total_neuron_time > 0
else 0
)
line_data["nrt_execute_count"] = len(all_events)
line_data["nrt_events"] = all_events
line_data["nrt_source_code"] = kernel_name
# Add nc_exec_running data
line_data["nc_time_ms"] = total_nc_time_ms
line_data["nc_percent"] = (
(total_nc_time_ms / total_nc_time) * 100
if total_nc_time > 0
else 0
)
line_data["nc_execute_count"] = len(all_nc_events)
line_data["nc_events"] = all_nc_events
# Add ratio of nc_exec time to nrt_execute time
line_data["nc_nrt_ratio"] = (
total_nc_time_ms / total_time_ms if total_time_ms > 0 else 0
)
# Keep legacy field for backward compatibility
line_data["neuron_time_ms"] = total_time_ms
# Add neuron metadata
if len(nrt_events) > 0:
scalene_data["neuron_total_time_ms"] = total_neuron_time
scalene_data["neuron_total_nc_time_ms"] = total_nc_time
scalene_data["neuron_event_count"] = len(nrt_events)
scalene_data["neuron_nc_event_count"] = len(nc_events)
scalene_data["cpu_samples_total_with_nc_overlap"] = (
total_cpu_samples_with_overlap
)
scalene_data["cpu_samples_total"] = total_cpu_samples
scalene_data["cpu_samples_nc_overlap_percent_overall"] = (
(total_cpu_samples_with_overlap / total_cpu_samples * 100)
if total_cpu_samples > 0
else 0.0
)
# Write merged data
with open(output_file, "w") as f:
json.dump(scalene_data, f, indent=2)
print(f"Merged data written to {output_file}")
print(f"Total neuron time: {total_neuron_time:.2f}ms")
print(f"Total nc_exec time: {total_nc_time:.2f}ms")
print(
f"Overall CPU sample overlap: {total_cpu_samples_with_overlap}/{total_cpu_samples} ({(total_cpu_samples_with_overlap/total_cpu_samples*100) if total_cpu_samples > 0 else 0:.1f}%)"
)
if __name__ == "__main__":
if len(sys.argv) != 4:
print(
"Usage: python merge_scalene_neuron_programmatic_with_overlap.py "
)
sys.exit(1)
scalene_file, neuron_file, output_file = sys.argv[1:4]
merge_neuron_into_scalene_programmatic(scalene_file, neuron_file, output_file)
================================================
FILE: scalene/profile.py
================================================
import argparse
import sys
from textwrap import dedent
usage = dedent("""Turn Scalene profiling on or off for a specific process.""")
parser = argparse.ArgumentParser(
prog="scalene.profile",
description=usage,
formatter_class=argparse.RawTextHelpFormatter,
allow_abbrev=False,
)
parser.add_argument("--pid", dest="pid", type=int, default=0, help="process ID")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--on", action="store_true", help="turn profiling on")
group.add_argument("--off", action="store_false", help="turn profiling off")
args, left = parser.parse_known_args()
if len(sys.argv) == 1 or args.pid == 0:
parser.print_help(sys.stderr)
sys.exit(-1)
try:
from scalene.scalene_signal_manager import ScaleneSignalManager
ScaleneSignalManager.signal_lifecycle_event(args.pid, start=args.on)
if args.on:
print("Scalene: profiling turned on.")
else:
print("Scalene: profiling turned off.")
except ProcessLookupError:
print("Process " + str(args.pid) + " not found.")
================================================
FILE: scalene/redirect_python.py
================================================
import os
import pathlib
import stat
import sys
def redirect_python(preface: str, cmdline: str, python_alias_dir: pathlib.Path) -> str:
"""
Redirects Python calls to a different command with a preface and cmdline.
Args:
preface: A string to be prefixed to the Python command.
cmdline: Additional command line arguments to be appended.
python_alias_dir: The directory where the alias scripts will be stored.
"""
base_python_extension = ".exe" if sys.platform == "win32" else ""
all_python_names = [
"python" + base_python_extension,
f"python{sys.version_info.major}{base_python_extension}",
f"python{sys.version_info.major}.{sys.version_info.minor}{base_python_extension}",
]
shebang = "@echo off" if sys.platform == "win32" else "#!/usr/bin/env bash"
all_args = "%*" if sys.platform == "win32" else '"$@"'
payload = (
f"{shebang}\n{preface} {sys.executable} -m scalene run {cmdline} {all_args}\n"
)
for name in all_python_names:
fname = python_alias_dir / name
if sys.platform == "win32":
fname = fname.with_suffix(".bat")
try:
with open(fname, "w") as file:
file.write(payload)
if sys.platform != "win32":
os.chmod(fname, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
except OSError as e:
print(f"Error writing to {fname}: {e}")
sys.path.insert(0, str(python_alias_dir))
os.environ["PATH"] = f"{python_alias_dir}{os.pathsep}{os.environ['PATH']}"
orig_sys_executable = sys.executable
# Compute the new sys executable path
sys_executable_path = python_alias_dir / all_python_names[0]
# On Windows, adjust the path to use a .bat file instead of .exe
if sys.platform == "win32" and sys_executable_path.suffix == ".exe":
sys_executable_path = sys_executable_path.with_suffix(".bat")
sys.executable = str(sys_executable_path)
return orig_sys_executable
================================================
FILE: scalene/replacement_asyncio.py
================================================
"""Scalene replacement for asyncio event loop instrumentation.
Follows the existing replacement_*.py pattern using @Scalene.shim.
When async profiling is enabled, this module activates the
ScaleneAsync instrumentation (sys.monitoring on 3.12+, polling on older).
"""
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_asyncio(scalene: Scalene) -> None:
"""Activate async profiling instrumentation when --async is enabled.
This is called during profiler initialization. The actual enable/disable
is controlled by Scalene.__init__ based on the --async flag.
ScaleneAsync.enable() installs sys.monitoring callbacks on 3.12+.
On 3.9-3.11, polling via asyncio.all_tasks() is used instead,
triggered from the signal queue processor.
"""
# Nothing to do here - activation is handled by the profiler
# based on the --async flag. This module exists as a placeholder
# following the replacement_*.py convention, and can be extended
# with additional event loop wrapping if needed.
pass
================================================
FILE: scalene/replacement_exec.py
================================================
"""Replacement for exec/eval/compile to track dynamically executed code.
This module intercepts exec(), eval(), and compile() to capture source code
that would otherwise be invisible to the profiler. When code is executed via
exec() or eval() with a string source, Python normally uses '' as the
filename, making it impossible to show line-by-line profiling.
By wrapping these builtins, we:
1. Generate unique virtual filenames that include the caller's location
2. Store the source in linecache so it can be retrieved during profiling output
3. Compile/execute using our virtual filename so profiler samples reference it
"""
import __future__
import builtins
import linecache
import os
import sys
from types import FrameType
from typing import Any, Dict, Optional
from scalene.scalene_profiler import Scalene
# Bitmask covering all __future__ compiler flags. compile() inherits these
# from the calling frame when dont_inherit=False, but our wrappers break
# that inheritance chain. We extract them from the real caller's co_flags
# to propagate them explicitly. This is the same approach CPython's doctest
# module uses and covers all past and future __future__ features.
_FUTURE_FLAGS_MASK = 0
for _name in __future__.all_feature_names:
_FUTURE_FLAGS_MASK |= getattr(__future__, _name).compiler_flag
del _name
def _caller_future_flags(frame: FrameType) -> int:
"""Extract __future__ compiler flags from a frame's code object."""
return frame.f_code.co_flags & _FUTURE_FLAGS_MASK
def _is_synthetic_filename(filename: str) -> bool:
"""Check if a filename is a Python synthetic name like ''."""
return filename.startswith("<") and filename.endswith(">")
def _register_source_in_linecache(filename: str, source: str) -> None:
"""Register source code in linecache for later retrieval."""
lines = source.splitlines(keepends=True)
# Ensure the last line has a newline
if lines and not lines[-1].endswith("\n"):
lines[-1] += "\n"
# linecache entry format: (size, mtime, lines, fullname)
# mtime=None indicates the source won't change
linecache.cache[filename] = (len(source), None, lines, filename)
def _make_virtual_filename(kind: str, caller_frame: FrameType) -> str:
"""Create a virtual filename encoding the caller's location.
Format: or
"""
caller_filename = caller_frame.f_code.co_filename
caller_lineno = caller_frame.f_lineno
# Use basename to keep the filename short
basename = os.path.basename(caller_filename)
return f"<{kind}@{basename}:{caller_lineno}>"
@Scalene.shim
def replacement_exec(scalene: Scalene) -> None: # noqa: ARG001
"""Replace exec(), eval(), and compile() to track dynamic code execution."""
orig_exec = builtins.exec
orig_eval = builtins.eval
orig_compile = builtins.compile
def exec_replacement(
__source: Any,
/,
globals: Optional[Dict[str, Any]] = None,
locals: Optional[Dict[str, Any]] = None,
**kwargs: Any,
) -> None:
"""Replacement for exec() that tracks source code.
When given a string, we compile it with a unique virtual filename
and register the source in linecache for profiling.
Note: In Python 3.14+, exec() accepts globals/locals as keyword arguments,
plus a keyword-only 'closure' parameter. We use 'globals' and 'locals'
as parameter names (shadowing builtins) to match the built-in signature.
"""
# Get caller frame - needed both for virtual filename and for
# getting globals/locals when not provided
caller_frame = sys._getframe(1)
if isinstance(__source, str):
virtual_filename = _make_virtual_filename("exec", caller_frame)
_register_source_in_linecache(virtual_filename, __source)
# Propagate the caller's __future__ flags (e.g. annotations)
# so that code compiled here behaves the same as if exec()
# compiled it directly in the caller's context.
flags = _caller_future_flags(caller_frame)
code_obj = orig_compile(
__source,
virtual_filename,
"exec",
flags=flags,
dont_inherit=True,
)
__source = code_obj
# When globals/locals are not specified, exec() uses the caller's frame.
# Since we're wrapping exec, we need to explicitly get the caller's frame.
if globals is None:
globals = caller_frame.f_globals
if locals is None:
locals = caller_frame.f_locals
if locals is None:
orig_exec(__source, globals, **kwargs)
else:
orig_exec(__source, globals, locals, **kwargs)
def eval_replacement(
__source: Any,
/,
globals: Optional[Dict[str, Any]] = None,
locals: Optional[Dict[str, Any]] = None,
) -> Any:
"""Replacement for eval() that tracks source code.
When given a string, we compile it with a unique virtual filename
and register the source in linecache for profiling.
Note: In Python 3.14+, eval() accepts globals/locals as keyword arguments.
We use 'globals' and 'locals' as parameter names (shadowing builtins)
to match the built-in signature exactly.
"""
# Get caller frame - needed both for virtual filename and for
# getting globals/locals when not provided
caller_frame = sys._getframe(1)
if isinstance(__source, str):
virtual_filename = _make_virtual_filename("eval", caller_frame)
_register_source_in_linecache(virtual_filename, __source)
flags = _caller_future_flags(caller_frame)
code_obj = orig_compile(
__source,
virtual_filename,
"eval",
flags=flags,
dont_inherit=True,
)
__source = code_obj
# When globals/locals are not specified, eval() uses the caller's frame.
# Since we're wrapping eval, we need to explicitly get the caller's frame.
if globals is None:
globals = caller_frame.f_globals
if locals is None:
locals = caller_frame.f_locals
if locals is None:
return orig_eval(__source, globals)
else:
return orig_eval(__source, globals, locals)
def compile_replacement(
source: Any,
filename: str,
mode: str,
flags: int = 0,
dont_inherit: bool = False,
optimize: int = -1,
**kwargs: Any,
) -> Any:
"""Replacement for compile() that tracks source code.
When the filename is a synthetic name like '' and we have
a string source, we register it in linecache with the given filename.
This handles cases where users call compile() directly.
"""
if isinstance(source, str) and _is_synthetic_filename(filename):
_register_source_in_linecache(filename, source)
if not dont_inherit:
# The real compile() would inherit __future__ flags from its
# caller's frame. Since our wrapper is now the immediate caller,
# we must manually propagate flags from the real caller.
caller_frame = sys._getframe(1)
flags |= _caller_future_flags(caller_frame)
dont_inherit = True
return orig_compile(
source, filename, mode, flags, dont_inherit, optimize, **kwargs
)
builtins.exec = exec_replacement # type: ignore[assignment]
builtins.eval = eval_replacement # type: ignore[assignment]
builtins.compile = compile_replacement # type: ignore[assignment]
================================================
FILE: scalene/replacement_exit.py
================================================
import os
import sys
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_exit(scalene: Scalene) -> None:
"""
Shims out the unconditional exit with
the "neat exit" (which raises the SystemExit error and
allows Scalene to exit neatly)
"""
# Note: MyPy doesn't like this, but it works because passing an int
# to sys.exit does the right thing
os._exit = sys.exit # type: ignore
================================================
FILE: scalene/replacement_fork.py
================================================
import os
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_fork(scalene: Scalene) -> None:
"""
Executes Scalene fork() handling.
Works just like os.register_at_fork(), but unlike that also provides the child PID.
"""
orig_fork = os.fork
def fork_replacement() -> int:
scalene.before_fork()
child_pid = orig_fork()
if child_pid == 0:
scalene.after_fork_in_child()
else:
scalene.after_fork_in_parent(child_pid)
return child_pid
os.fork = fork_replacement
================================================
FILE: scalene/replacement_get_context.py
================================================
import multiprocessing
from typing import Any
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_mp_get_context(scalene: Scalene) -> None:
old_get_context = multiprocessing.get_context
def replacement_get_context(method: Any = None) -> Any:
# Respect the user's requested method instead of forcing fork
return old_get_context(method)
multiprocessing.get_context = replacement_get_context
================================================
FILE: scalene/replacement_lock.py
================================================
import contextlib
import sys
import threading
import time
from typing import Any
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_lock(scalene: Scalene) -> None:
class ReplacementLock:
"""Replace lock with a version that periodically yields and updates sleeping status."""
def __init__(self) -> None:
# Cache the original lock (which we replace)
# print("INITIALIZING LOCK")
self.__lock: threading.Lock = scalene.get_original_lock()
def acquire(self, blocking: bool = True, timeout: float = -1) -> bool:
tident = threading.get_ident()
if blocking == 0:
blocking = False
start_time = time.perf_counter()
if blocking:
if timeout < 0:
interval = sys.getswitchinterval()
else:
interval = min(timeout, sys.getswitchinterval())
else:
interval = -1
while True:
scalene.set_thread_sleeping(tident)
acquired_lock = self.__lock.acquire(blocking, interval)
scalene.reset_thread_sleeping(tident)
if acquired_lock:
return True
if not blocking:
return False
# If a timeout was specified, check to see if it's expired.
if timeout != -1:
end_time = time.perf_counter()
if end_time - start_time >= timeout:
return False
def release(self) -> None:
self.__lock.release()
def locked(self) -> bool:
return self.__lock.locked()
def _at_fork_reinit(self) -> None:
with contextlib.suppress(AttributeError):
self.__lock._at_fork_reinit() # type: ignore
def __enter__(self) -> None:
self.acquire()
def __exit__(self, type: str, value: str, traceback: Any) -> None:
self.release()
threading.Lock = ReplacementLock # type: ignore
================================================
FILE: scalene/replacement_mp_lock.py
================================================
import multiprocessing.synchronize
# import _multiprocessing
# The _multiprocessing module is entirely undocumented-- the header of the
# acquire function is
# static PyObject * _multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking, PyObject *timeout_obj)
#
# timeout_obj is parsed as a double
from scalene.replacement_sem_lock import ReplacementSemLock
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_mp_semlock(scalene: Scalene) -> None:
ReplacementSemLock.__qualname__ = "replacement_semlock.ReplacementSemLock"
multiprocessing.synchronize.Lock = ReplacementSemLock # type: ignore
================================================
FILE: scalene/replacement_pjoin.py
================================================
import multiprocessing
import os
import sys
import threading
import time
from scalene.scalene_profiler import Scalene
minor_version = sys.version_info.minor
@Scalene.shim
def replacement_pjoin(scalene: Scalene) -> None:
def replacement_process_join(self, timeout: float = -1) -> None: # type: ignore
"""
A drop-in replacement for multiprocessing.Process.join
that periodically yields to handle signals
"""
# print(multiprocessing.process.active_children())
if minor_version >= 7:
self._check_closed()
assert self._parent_pid == os.getpid(), "can only join a child process"
assert self._popen is not None, "can only join a started process"
tident = threading.get_ident()
if timeout < 0:
interval = sys.getswitchinterval()
else:
interval = min(timeout, sys.getswitchinterval())
start_time = time.perf_counter()
while True:
scalene.set_thread_sleeping(tident)
res = self._popen.wait(interval)
if res is not None:
from multiprocessing.process import _children # type: ignore
scalene.remove_child_pid(self.pid)
_children.discard(self)
return
scalene.reset_thread_sleeping(tident)
# I think that this should be timeout--
# Interval is the sleep time per-tic,
# but timeout determines whether it returns
if timeout != -1:
end_time = time.perf_counter()
if end_time - start_time >= timeout:
from multiprocessing.process import ( # type: ignore
_children,
)
_children.discard(self)
return
multiprocessing.Process.join = replacement_process_join # type: ignore
================================================
FILE: scalene/replacement_poll_selector.py
================================================
import selectors
import sys
import threading
import time
from typing import List, Optional, Tuple
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_poll_selector(scalene: Scalene) -> None:
"""
A replacement for selectors.PollSelector that
periodically wakes up to accept signals
"""
class ReplacementPollSelector(selectors.PollSelector):
def select(
self, timeout: Optional[float] = -1
) -> List[Tuple[selectors.SelectorKey, int]]:
tident = threading.get_ident()
start_time = time.perf_counter()
if not timeout or timeout < 0:
interval = sys.getswitchinterval()
else:
interval = min(timeout, sys.getswitchinterval())
while True:
scalene.set_thread_sleeping(tident)
selected = super().select(interval)
scalene.reset_thread_sleeping(tident)
if selected or timeout == 0:
return selected
end_time = time.perf_counter()
if timeout and timeout != -1 and end_time - start_time >= timeout:
return [] # None
ReplacementPollSelector.__qualname__ = (
"replacement_poll_selector.ReplacementPollSelector"
)
selectors.PollSelector = ReplacementPollSelector # type: ignore
================================================
FILE: scalene/replacement_sem_lock.py
================================================
import multiprocessing.context
import multiprocessing.synchronize
import random
import sys
import threading
from typing import Any, Callable, Optional, Tuple, Union
from scalene.scalene_profiler import Scalene
def _make_replacement_semlock(method: Optional[str] = None) -> "ReplacementSemLock":
# Create lock using the specified context method for spawn-safety
ctx = multiprocessing.get_context(method)
return ReplacementSemLock(ctx=ctx)
class ReplacementSemLock(multiprocessing.synchronize.Lock):
def __init__(
self,
ctx: Optional[
Union[
multiprocessing.context.DefaultContext,
multiprocessing.context.BaseContext,
]
] = None,
) -> None:
# Ensure to use the appropriate context while initializing
if ctx is None:
ctx = multiprocessing.get_context()
# Store the context method for pickling (spawn-safety)
self._ctx_method: Optional[str] = getattr(ctx, "_name", None)
super().__init__(ctx=ctx)
def __enter__(self) -> bool:
switch_interval = sys.getswitchinterval()
max_timeout = switch_interval
tident = threading.get_ident()
while True:
timeout = random.random() * max_timeout
Scalene.set_thread_sleeping(tident)
acquired = self._semlock.acquire(timeout=timeout) # type: ignore
Scalene.reset_thread_sleeping(tident)
if acquired:
return True
else:
max_timeout *= 2 # Exponential backoff
# Cap timeout at 1 second
if max_timeout >= 1.0:
max_timeout = 1.0
def __exit__(self, *args: Any) -> None:
super().__exit__(*args)
def __reduce__(self) -> Tuple[Callable[..., Any], Tuple[Any, ...]]:
# Pass the context method to preserve it across spawn
return (_make_replacement_semlock, (self._ctx_method,))
# important: force the class to live in the module name that workers will import
ReplacementSemLock.__module__ = "scalene.replacement_sem_lock"
================================================
FILE: scalene/replacement_signal_fns.py
================================================
import os
import signal
import sys
from typing import Any, Dict, Optional, Set, Tuple
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_signal_fns(scalene: Scalene) -> None:
scalene_signals = scalene.get_signals()
expected_handlers_map = {
scalene_signals.malloc_signal: scalene.malloc_signal_handler,
scalene_signals.free_signal: scalene.free_signal_handler,
scalene_signals.memcpy_signal: scalene.memcpy_signal_handler,
signal.SIGTERM: scalene.term_signal_handler,
scalene_signals.cpu_signal: scalene.cpu_signal_handler,
}
old_signal = signal.signal
old_raise_signal = signal.raise_signal
old_kill = os.kill
if sys.platform != "win32":
new_cpu_signal = signal.SIGUSR1
else:
new_cpu_signal = signal.SIGFPE
# Track which warnings we've already printed to avoid spam
_warned_signals: Set[int] = set()
# On Linux, we can use real-time signals (SIGRTMIN+n) for cleaner signal redirection.
# Real-time signals are guaranteed to be delivered and queued, and are rarely used by libraries.
# On other platforms (macOS, Windows), we fall back to signal handler chaining.
_use_rt_signals = sys.platform == "linux" and hasattr(signal, "SIGRTMIN")
# Map original signals to their alternate (redirected) signals
# On Linux: use real-time signals; on other platforms: None (use chaining)
_signal_redirects: Dict[int, int] = {}
if _use_rt_signals:
# Allocate real-time signals for each Scalene signal that might conflict
# SIGRTMIN+0 is often used by threading libraries, so start from SIGRTMIN+1
rt_base = getattr(signal, "SIGRTMIN") + 1 # noqa: B009
start_signal, stop_signal = scalene.get_lifecycle_signals()
# Map lifecycle and memory signals to real-time signals
rt_offset = 0
for sig in [
start_signal,
stop_signal,
scalene_signals.memcpy_signal,
scalene_signals.malloc_signal,
scalene_signals.free_signal,
]:
if sig is not None:
_signal_redirects[sig] = rt_base + rt_offset
rt_offset += 1
# Store chained handlers for platforms without real-time signal support
# Maps signal number -> user's handler
_chained_handlers: Dict[int, Any] = {}
def _make_chained_handler(scalene_handler: Any, user_handler: Any) -> Any:
"""Create a handler that calls both Scalene's handler and the user's handler."""
import contextlib
from types import FrameType
from typing import Optional
def chained_handler(sig: int, frame: Optional[FrameType]) -> None:
# Call Scalene's handler first (don't let errors break user code)
with contextlib.suppress(Exception):
scalene_handler(sig, frame)
# Then call the user's handler (don't let errors propagate)
if callable(user_handler):
with contextlib.suppress(Exception):
user_handler(sig, frame)
return chained_handler
def replacement_signal(signum: int, handler: Any) -> Any:
all_signals = scalene.get_all_signals_set()
timer_signal, cpu_signal = scalene.get_timer_signals()
timer_signal_str = signal.strsignal(signum)
start_signal, stop_signal = scalene.get_lifecycle_signals()
# Handle CPU profiling signal - redirect to an alternate signal
# This allows both Scalene and user code to use timer-based profiling
if signum == cpu_signal:
if signum not in _warned_signals:
print(
f"WARNING: Scalene uses {timer_signal_str} to profile.\n"
f"If your code raises {timer_signal_str} from non-Python code, use SIGUSR1.\n"
"Code that raises signals from within Python code will be rerouted."
)
_warned_signals.add(signum)
return old_signal(new_cpu_signal, handler)
# Handle lifecycle signals (SIGILL, SIGBUS) - allow co-existence with user code
if start_signal is not None and signum == start_signal:
return _handle_signal_coexistence(signum, handler, timer_signal_str)
if stop_signal is not None and signum == stop_signal:
return _handle_signal_coexistence(signum, handler, timer_signal_str)
# Fallthrough condition-- if we haven't dealt with the signal at this point in the call and the handler is
# a NOP-like, then we can ignore it. It can't have been set already, and the expected return value is the
# previous handler, so this behavior is reasonable
if signum in all_signals and (
handler is signal.SIG_IGN or handler is signal.SIG_DFL
):
return handler
# If trying to "reset" to a handler that we already set it to, ignore
if (
signal.Signals(signum) in expected_handlers_map
and expected_handlers_map[signal.Signals(signum)] is handler
):
return signal.SIG_IGN
# Handle memory profiling signals (SIGPROF, SIGXCPU, SIGXFSZ) - allow co-existence
if signum in all_signals:
return _handle_signal_coexistence(signum, handler, timer_signal_str)
return old_signal(signum, handler)
def _handle_signal_coexistence(
signum: int, handler: Any, signal_name: "Optional[str]"
) -> Any:
"""Handle a signal that both Scalene and user code want to use.
On Linux: Redirect user's handler to a real-time signal for clean separation.
On other platforms: Chain handlers so both get called.
"""
if signum not in _warned_signals:
sig_str = signal_name or f"signal {signum}"
if _use_rt_signals and signum in _signal_redirects:
print(
f"WARNING: {sig_str} is also used by Scalene.\n"
"Your code's handler will be redirected to an alternate signal."
)
else:
print(
f"WARNING: {sig_str} is also used by Scalene.\n"
"Both Scalene and your code will handle this signal."
)
_warned_signals.add(signum)
# On Linux with real-time signals: redirect to alternate signal
if _use_rt_signals and signum in _signal_redirects:
return old_signal(_signal_redirects[signum], handler)
# On other platforms: chain handlers
if handler in (signal.SIG_IGN, signal.SIG_DFL):
return old_signal(signum, handler)
scalene_handler = expected_handlers_map.get(signal.Signals(signum))
if scalene_handler:
old_user_handler = _chained_handlers.get(signum)
_chained_handlers[signum] = handler
chained = _make_chained_handler(scalene_handler, handler)
old_signal(signum, chained)
return old_user_handler if old_user_handler else signal.SIG_DFL
return old_signal(signum, handler)
def replacement_raise_signal(signum: int) -> None:
_, cpu_signal = scalene.get_timer_signals()
if signum == cpu_signal:
old_raise_signal(new_cpu_signal)
return
# On Linux, redirect to real-time signal if applicable
if _use_rt_signals and signum in _signal_redirects:
old_raise_signal(_signal_redirects[signum])
return
old_raise_signal(signum)
def replacement_kill(pid: int, signum: int) -> None:
_, cpu_signal = scalene.get_timer_signals()
is_self_or_child = pid == os.getpid() or pid in scalene.child_pids
if is_self_or_child and signum == cpu_signal:
return old_kill(pid, new_cpu_signal)
# On Linux, redirect to real-time signal if applicable
if is_self_or_child and _use_rt_signals and signum in _signal_redirects:
return old_kill(pid, _signal_redirects[signum])
old_kill(pid, signum)
if sys.platform != "win32":
old_setitimer = signal.setitimer
old_siginterrupt = signal.siginterrupt
def replacement_siginterrupt(signum: int, flag: bool) -> None:
_, cpu_signal = scalene.get_timer_signals()
if signum == cpu_signal:
return old_siginterrupt(new_cpu_signal, flag)
# On Linux, redirect to real-time signal if applicable
if _use_rt_signals and signum in _signal_redirects:
return old_siginterrupt(_signal_redirects[signum], flag)
return old_siginterrupt(signum, flag)
def replacement_setitimer(
which: int, seconds: float, interval: float = 0.0
) -> Tuple[float, float]:
timer_signal, cpu_signal = scalene.get_timer_signals()
if which == timer_signal:
old = scalene.client_timer.get_itimer()
if seconds == 0:
scalene.client_timer.reset()
else:
scalene.client_timer.set_itimer(seconds, interval)
return old
return old_setitimer(which, seconds, interval)
signal.setitimer = replacement_setitimer
signal.siginterrupt = replacement_siginterrupt
signal.signal = replacement_signal # type: ignore[unused-ignore,assignment]
signal.raise_signal = replacement_raise_signal
os.kill = replacement_kill
================================================
FILE: scalene/replacement_thread_join.py
================================================
import sys
import threading
import time
from typing import Optional
from scalene.scalene_profiler import Scalene
@Scalene.shim
def replacement_thread_join(scalene: Scalene) -> None:
orig_thread_join = threading.Thread.join
def thread_join_replacement(
self: threading.Thread, timeout: Optional[float] = None
) -> None:
"""We replace threading.Thread.join with this method which always
periodically yields."""
start_time = time.perf_counter()
interval = sys.getswitchinterval()
while self.is_alive():
scalene.set_thread_sleeping(threading.get_ident())
orig_thread_join(self, interval)
scalene.reset_thread_sleeping(threading.get_ident())
# If a timeout was specified, check to see if it's expired.
if timeout is not None:
end_time = time.perf_counter()
if end_time - start_time >= timeout:
return None
return None
threading.Thread.join = thread_join_replacement # type: ignore
================================================
FILE: scalene/runningstats.py
================================================
# Simplified running statistics - only computes mean and peak
# (variance/skewness/kurtosis removed as they were unused)
class RunningStats:
"""Incrementally compute mean and peak statistics using Welford's algorithm."""
__slots__ = ("_n", "_m1", "_peak")
def __init__(self) -> None:
self._n: int = 0
self._m1: float = 0.0
self._peak: float = 0.0
def __add__(self: "RunningStats", other: "RunningStats") -> "RunningStats":
s = RunningStats()
if other._n > 0:
total_n = self._n + other._n
s._m1 = (self._m1 * self._n + other._m1 * other._n) / total_n
s._n = total_n
s._peak = max(self._peak, other._peak)
else:
s._n = self._n
s._m1 = self._m1
s._peak = self._peak
return s
def clear(self) -> None:
"""Reset for new samples."""
self._n = 0
self._m1 = 0.0
self._peak = 0.0
def push(self, x: float) -> None:
"""Add a sample using Welford's online algorithm for mean."""
if x > self._peak:
self._peak = x
self._n += 1
# Welford's algorithm: mean += (x - mean) / n
self._m1 += (x - self._m1) / self._n
def peak(self) -> float:
"""The maximum sample seen."""
return self._peak
def size(self) -> int:
"""The number of samples."""
return self._n
def mean(self) -> float:
"""Arithmetic mean (average)."""
return self._m1
================================================
FILE: scalene/scalene-gui/README.md
================================================
This repository holds the [Scalene](https://github.com/plasma-umass/scalene) GUI.
[](https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/scalene-gui-example-full.png)
To use the interactive demo, go to the [Scalene GUI](https://plasma-umass.org/scalene-gui/) site.
# Acknowledgements
Scalene's web GUI makes use of the following wonderful systems. Many thanks to their authors.
- [Vega-Lite](https://vega.github.io/vega-lite/) for rendering graphs
- [Prism](https://prismjs.com/) for code highlighting
- [tablesort](https://github.com/tristen/tablesort) for sorting tables by columns
This material is based upon work supported by the National Science
Foundation under Grant No. 1955610. Any opinions, findings, and
conclusions or recommendations expressed in this material are those of
the author(s) and do not necessarily reflect the views of the National
Science Foundation.
================================================
FILE: scalene/scalene-gui/TODO-TypeScript.md
================================================
# TypeScript Conversion Plan for Scalene GUI
## Overview
Converting the Scalene GUI JavaScript files to TypeScript for improved type safety, better IDE support, and easier maintenance.
## Build Configuration
- **Bundler**: esbuild (fast, simple, no webpack overhead)
- **Type Checker**: TypeScript compiler (tsc --noEmit)
- **Target**: ES2020
- **Module System**: ESNext with bundler resolution
### package.json Scripts
```json
{
"scripts": {
"build": "esbuild scalene-gui.ts --bundle --minify --sourcemap --target=es2020 --outfile=scalene-gui-bundle.js",
"build:dev": "esbuild scalene-gui.ts --bundle --sourcemap --target=es2020 --outfile=scalene-gui-bundle.js",
"watch": "esbuild scalene-gui.ts --bundle --sourcemap --target=es2020 --outfile=scalene-gui-bundle.js --watch",
"typecheck": "tsc --noEmit"
}
}
```
## Conversion Status
### Completed
- [x] `utils.ts` - Utility functions (escapeHTML, extractCode, makeTextRecursivelySelectable)
- [x] `openai.ts` - OpenAI API integration with proper interfaces
- [x] `ollama.ts` - Ollama local LLM integration
- [x] `amazon.ts` - AWS Bedrock integration (Anthropic and OpenAI-style responses)
- [x] `azure.ts` - Azure OpenAI integration
- [x] `persistence.ts` - LocalStorage state persistence
- [x] `gui-elements.ts` - Vega-Lite chart builders with LineProfile/FileProfile interfaces
- [x] `optimizations.ts` - AI optimization request handling
- [x] `scalene-gui.ts` - Main entry point (largest file, imports all others)
- [x] `scalene-demo.ts` - Demo functionality
- [x] `scalene-fetch.ts` - Profile fetching utilities
- [x] `prism.d.ts` - Type declarations for Prism.js
- [x] `tablesort.d.ts` - Type declarations for Tablesort.js
### External Libraries (Kept as JS with type declarations)
- `prism.js` - Syntax highlighting (external library, with prism.d.ts declarations)
- `tablesort.js` - Table sorting (external library, with tablesort.d.ts declarations)
## Type Definitions Added
### Interfaces
- `OpenAIChoice`, `OpenAIResponse` - OpenAI API responses
- `OllamaModel`, `OllamaTagsResponse`, `OllamaMessage`, `OllamaResponse` - Ollama API
- `AnthropicResponse`, `OpenAIStyleResponse` - Amazon Bedrock responses
- `AzureOpenAIChoice`, `AzureOpenAIResponse` - Azure API responses
- `LineProfile`, `FileProfile`, `ChartParams` - Profile data structures for Vega-Lite charts
- `LineData`, `FunctionData`, `FileData`, `Profile` - Main profile data types
- `Column`, `TableParams`, `OptimizationParams` - GUI-specific types
### DOM Element Types
All DOM element access uses proper type assertions:
```typescript
const element = document.getElementById("my-id") as HTMLInputElement | null;
```
## Dependencies
```json
{
"devDependencies": {
"@types/node": "^20.10.0",
"@types/prismjs": "^1.26.0",
"esbuild": "^0.24.0",
"typescript": "^5.3.3"
},
"dependencies": {
"@aws-sdk/client-bedrock-runtime": "^3.729.0",
"buffer": "^6.0.3",
"vega": "^5.30.0",
"vega-embed": "^6.28.0",
"vega-lite": "^5.21.0"
}
}
```
## Build Steps
1. Install dependencies: `npm install`
2. Type check: `npm run typecheck`
3. Build bundle: `npm run build`
4. Development build (unminified): `npm run build:dev`
5. Watch mode: `npm run watch`
## Notes
- Using `strictNullChecks: true` for better null safety
- All external API responses have explicit interface definitions
- DOM element access uses null-safe patterns with optional chaining
- External JS libraries (`prism.js`, `tablesort.js`) kept as-is with `.d.ts` declaration files
- Window functions exposed globally for HTML onclick handlers
- Build produces ~1.1MB minified bundle with source maps
## Migration Complete
All JavaScript files have been successfully converted to TypeScript. The original `.js` files can be removed once the TypeScript version is verified in production.
================================================
FILE: scalene/scalene-gui/amazon.ts
================================================
import {
BedrockRuntimeClient,
InvokeModelCommand,
} from "@aws-sdk/client-bedrock-runtime";
interface AnthropicResponse {
content: Array<{ text: string }>;
}
interface OpenAIStyleResponse {
choices: Array<{
message: {
content: string;
};
}>;
}
export async function sendPromptToAmazon(prompt: string): Promise {
const accessKeyIdElement = document.getElementById("aws-access-key") as HTMLInputElement | null;
const secretAccessKeyElement = document.getElementById("aws-secret-key") as HTMLInputElement | null;
const regionElement = document.getElementById("aws-region") as HTMLInputElement | null;
const accessKeyId =
accessKeyIdElement?.value ||
localStorage.getItem("aws-access-key") ||
"";
const secretAccessKey =
secretAccessKeyElement?.value ||
localStorage.getItem("aws-secret-key") ||
"";
const region =
regionElement?.value ||
localStorage.getItem("aws-region") ||
"us-east-1";
// Configure AWS Credentials
const credentials = {
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey,
};
// Initialize the Bedrock Runtime Client
const client = new BedrockRuntimeClient({
region: region,
credentials: credentials,
});
let body: Record = {};
const max_tokens = 65536; // arbitrary large number
const modelElement = document.getElementById("language-model-amazon") as HTMLSelectElement | null;
const modelId = modelElement?.value ?? "";
if (modelId.startsWith("us.anthropic")) {
body = {
anthropic_version: "bedrock-2023-05-31",
max_tokens: max_tokens,
messages: [
{
role: "user",
content: [
{
type: "text",
text: prompt,
},
],
},
],
};
} else {
body = {
max_completion_tokens: max_tokens,
messages: [
{
role: "user",
content: [
{
type: "text",
text: prompt,
},
],
},
],
};
}
const params = {
modelId: modelId,
body: JSON.stringify(body),
};
try {
const command = new InvokeModelCommand(params);
const response = await client.send(command);
// Convert the response body to text
const responseBlob = new Blob([response.body as BlobPart]);
const responseText = await responseBlob.text();
const parsedResponse = JSON.parse(responseText);
console.log("parsedResponse = " + responseText);
if (modelId.startsWith("us.anthropic")) {
const anthropicResponse = parsedResponse as AnthropicResponse;
const responseContents = anthropicResponse.content[0].text;
return responseContents.trim();
} else {
const openaiResponse = parsedResponse as OpenAIStyleResponse;
const responseContents = openaiResponse.choices[0].message.content.replace(
/[\s\S]*?<\/reasoning>/g,
""
);
return responseContents.trim();
}
} catch (err) {
const error = err as Error;
console.error(err);
return `# Error: ${error.message}`;
}
}
================================================
FILE: scalene/scalene-gui/anthropic.ts
================================================
interface AnthropicErrorResponse {
error?: {
type?: string;
message?: string;
};
}
interface AnthropicContentBlock {
type: string;
text: string;
}
interface AnthropicResponse extends AnthropicErrorResponse {
content?: AnthropicContentBlock[];
}
export async function sendPromptToAnthropic(
prompt: string,
apiKey: string
): Promise {
// Check for custom URL override (for Anthropic-compatible servers)
const customUrlElement = document.getElementById("anthropic-custom-url") as HTMLInputElement | null;
const customUrl = customUrlElement?.value?.trim() || "";
const endpoint = customUrl || "https://api.anthropic.com/v1/messages";
// Check for custom model override
const customModelElement = document.getElementById("anthropic-custom-model") as HTMLInputElement | null;
const customModel = customModelElement?.value?.trim() || "";
const modelElement = document.getElementById("language-model-anthropic") as HTMLSelectElement | null;
const model = customModel || modelElement?.value || "claude-sonnet-4-5-20250929";
const body = JSON.stringify({
model: model,
max_tokens: 4096,
messages: [
{
role: "user",
content: prompt,
},
],
system:
"You are a Python programming assistant who ONLY responds with blocks of commented, optimized code. You never respond with text. Just code, starting with ``` and ending with ```.",
});
console.log(body);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
"anthropic-version": "2023-06-01",
"anthropic-dangerous-direct-browser-access": "true",
},
body: body,
});
const data: AnthropicResponse = await response.json();
if (data.error) {
console.error("Anthropic API error:", data.error);
if (data.error.type === "authentication_error") {
alert("Invalid Anthropic API key. Please check your API key and try again.");
} else if (data.error.type === "rate_limit_error") {
alert("Rate limit exceeded. Please wait a moment and try again.");
} else {
alert(`Anthropic API error: ${data.error.message || "Unknown error"}`);
}
return "";
}
try {
if (data.content && data.content[0]) {
console.log(
`Debugging info: Retrieved ${JSON.stringify(data.content[0], null, 4)}`
);
return data.content[0].text.replace(/^\s*[\r\n]/gm, "");
}
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
} catch {
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
}
}
================================================
FILE: scalene/scalene-gui/azure.ts
================================================
interface AzureOpenAIChoice {
message: {
content: string;
};
}
interface AzureOpenAIResponse {
error?: {
code?: string;
};
choices?: AzureOpenAIChoice[];
}
export async function sendPromptToAzureOpenAI(
prompt: string,
apiKey: string,
apiUrl: string,
aiModel: string
): Promise {
const apiVersionElement = document.getElementById("azure-api-version") as HTMLInputElement | null;
const apiVersion = apiVersionElement?.value ?? "2024-02-15-preview";
const endpoint = `${apiUrl}/openai/deployments/${aiModel}/chat/completions?api-version=${apiVersion}`;
const body = JSON.stringify({
messages: [
{
role: "system",
content:
"You are a Python programming assistant who ONLY responds with blocks of commented, optimized code. You never respond with text. Just code, starting with ``` and ending with ```.",
},
{
role: "user",
content: prompt,
},
],
user: "scalene-user",
});
console.log(body);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
"api-key": apiKey,
},
body: body,
});
const data: AzureOpenAIResponse = await response.json();
if (data.error) {
if (
data.error.code &&
data.error.code in {
invalid_request_error: true,
model_not_found: true,
insufficient_quota: true,
}
) {
return "";
}
}
try {
if (data.choices && data.choices[0]) {
console.log(
`Debugging info: Retrieved ${JSON.stringify(data.choices[0], null, 4)}`
);
}
} catch {
console.log(
`Debugging info: Failed to retrieve data.choices from the server. data = ${JSON.stringify(data)}`
);
}
try {
if (data.choices && data.choices[0]) {
return data.choices[0].message.content.replace(/^\s*[\r\n]/gm, "");
}
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
} catch {
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
}
}
================================================
FILE: scalene/scalene-gui/example-profile.js
================================================
const example_profile = {
elapsed_time_sec: 12.696948051452637,
memory: true,
files: {
"./test/testme.py": {
imports: [],
functions: [
{
line: "doit1",
lineno: 8,
memory_samples: [
[428532500, 9.570051193237305],
[445064208, 11.226824760437012],
[467929458, 9.749224662780762],
[467933333, 7.894305229187012],
[651147208, 9.467050552368164],
[661861583, 11.117934226989746],
[668149041, 9.640334129333496],
[668150333, 7.785323143005371],
[810188791, 9.357297897338867],
[819091291, 11.008158683776855],
[827225333, 9.530558586120605],
[827227250, 7.6755781173706055],
[964097833, 9.248224258422852],
[973085041, 10.89908504486084],
[981253250, 9.42148494720459],
[981254500, 7.56650447845459],
[1113670791, 9.138654708862305],
[1126232208, 10.789484977722168],
[1140849791, 9.311884880065918],
[1140851041, 7.456873893737793],
[1267816125, 9.028757095336914],
[1278337458, 10.679617881774902],
[1294287916, 9.202017784118652],
[1294289166, 7.347006797790527],
[1424228291, 8.919004440307617],
[1433313750, 10.569865226745605],
[1441482708, 9.092265129089355],
[1441483875, 7.2372541427612305],
[1576166708, 8.809465408325195],
[1586517375, 10.460295677185059],
[1594678416, 8.982695579528809],
[1594679583, 7.127715110778809],
[1730114333, 8.699773788452148],
[1739212375, 10.350634574890137],
[1747344291, 8.873034477233887],
[1747345666, 7.018054008483887],
[1883137000, 8.589975357055664],
[1898345333, 10.240836143493652],
[1898347625, 8.763236045837402],
[1898349000, 6.908255577087402],
[2042904500, 8.480405807495117],
[2042907958, 10.037023544311523],
[2053159625, 8.653666496276855],
[2053160916, 6.7986555099487305],
[2196880416, 8.370790481567383],
[2196883625, 9.927408218383789],
[2204029583, 8.544051170349121],
[2204030875, 6.689040184020996],
[2338301750, 8.261251449584961],
[2352917083, 9.912020683288574],
[2359497791, 8.434420585632324],
[2359499000, 6.579440116882324],
[2501090625, 8.151735305786133],
[2510295291, 9.802596092224121],
[2519173666, 8.324995994567871],
[2519174875, 6.470015525817871],
[2651119791, 8.042112350463867],
[2663691041, 9.69294261932373],
[2672632583, 8.21534252166748],
[2672633833, 6.3603315353393555],
[2808274125, 7.932390213012695],
[2817241083, 9.583250999450684],
[2825362500, 8.105650901794434],
[2825363708, 6.250670433044434],
[2967276500, 7.823369979858398],
[2967280416, 9.379987716674805],
[2976146916, 7.996630668640137],
[2976148208, 6.141619682312012],
[3109490458, 7.713602066040039],
[3122068833, 9.364432334899902],
[3130361916, 7.886832237243652],
[3130363083, 6.031821250915527],
[3265027166, 7.603918075561523],
[3271320291, 9.254679679870605],
[3282568291, 7.7770795822143555],
[3282569458, 5.9220991134643555],
[3422217791, 7.494386672973633],
[3437609416, 9.145247459411621],
[3437611583, 7.667647361755371],
[3437613041, 5.812666893005371],
[3575513458, 7.384756088256836],
[3584540708, 9.035616874694824],
[3592703166, 7.558016777038574],
[3592704333, 5.703036308288574],
[3723742875, 7.275102615356445],
[3734449208, 8.925963401794434],
[3745659166, 7.448363304138184],
[3745660250, 5.593352317810059],
[3881893166, 7.165685653686523],
[3897173333, 8.816546440124512],
[3897175416, 7.338946342468262],
[3897176666, 5.483965873718262],
[4034441041, 7.056039810180664],
[4050005958, 8.706870079040527],
[4050007583, 7.229269981384277],
[4050008958, 5.374289512634277],
[4184483375, 6.946355819702148],
[4197052708, 8.59711742401123],
[4205576916, 7.1195173263549805],
[4205578166, 5.2645063400268555],
[4347725000, 6.836626052856445],
[4347728041, 8.393243789672852],
[4358553500, 7.009886741638184],
[4358554583, 5.154875755310059],
[4492837750, 6.727071762084961],
[4502908041, 8.377902030944824],
[4511011375, 6.900301933288574],
[4511012541, 5.045321464538574],
[4646531000, 6.617380142211914],
[4661992208, 8.268240928649902],
[4661994166, 6.790640830993652],
[4661995500, 4.935660362243652],
[4805872333, 6.50782585144043],
[4805875458, 8.064443588256836],
[4816663458, 6.681086540222168],
[4816664916, 4.826075553894043],
[4954285750, 6.398340225219727],
[4963335000, 8.049201011657715],
[4971800083, 6.571600914001465],
[4971801291, 4.716620445251465],
[5108196500, 6.288686752319336],
[5123296458, 7.939547538757324],
[5123298416, 6.461947441101074],
[5123299708, 4.606966972351074],
[5261455875, 6.179033279418945],
[5270583000, 7.829894065856934],
[5278670500, 6.352293968200684],
[5278671833, 4.497313499450684],
[5413466541, 6.069440841674805],
[5423099541, 7.720301628112793],
[5430323333, 6.242701530456543],
[5430324625, 4.387721061706543],
[5565807583, 5.959833145141602],
[5575698250, 7.61063289642334],
[5582189041, 6.13303279876709],
[5582190291, 4.27805233001709],
[5713625000, 5.850225448608398],
[5726142000, 7.501086235046387],
[5732466750, 6.023486137390137],
[5732468041, 4.168475151062012],
[5872050708, 5.741365432739258],
[5881280666, 7.392195701599121],
[5889371000, 5.914595603942871],
[5889372208, 4.059615135192871],
[6023858541, 5.631811141967773],
[6033953416, 7.282641410827637],
[6042215291, 5.805041313171387],
[6042216500, 3.9500608444213867],
[6176588416, 5.522188186645508],
[6182908666, 7.173018455505371],
[6201797875, 5.695418357849121],
[6201799041, 3.840407371520996],
[6331915791, 5.412542343139648],
[6348609666, 7.063403129577637],
[6348611833, 5.585803031921387],
[6348613125, 3.7308225631713867],
[6484444250, 5.302881240844727],
[6496964458, 6.953742027282715],
[6506744041, 5.476141929626465],
[6506745250, 3.62113094329834],
[6638721125, 5.193334579467773],
[6651084000, 6.844195365905762],
[6659817208, 5.366595268249512],
[6659818375, 3.5115842819213867],
[6788692208, 5.083703994750977],
[6803875291, 6.73453426361084],
[6811955708, 5.25693416595459],
[6811956916, 3.401923179626465],
[6942827708, 4.974020004272461],
[6953656666, 6.624880790710449],
[6959926041, 5.147280693054199],
[6959927375, 3.292269706726074],
[7096960208, 4.864442825317383],
[7109526708, 6.515303611755371],
[7124614083, 5.037703514099121],
[7124615250, 3.182692527770996],
[7254360708, 4.754880905151367],
[7263431791, 6.4057416915893555],
[7271670041, 4.9281415939331055],
[7271671208, 3.0731611251831055],
[7408255583, 4.645288467407227],
[7417207291, 6.296149253845215],
[7425292250, 4.818549156188965],
[7425293541, 2.963568687438965],
[7557260708, 4.535665512084961],
[7569857958, 6.186495780944824],
[7585415291, 4.708895683288574],
[7585416416, 2.853884696960449],
[7714997916, 4.42607307434082],
[7730199916, 6.076933860778809],
[7730201708, 4.599333763122559],
[7730202916, 2.7443532943725586],
[7866120000, 4.316427230834961],
[7875908250, 5.967257499694824],
[7890269833, 4.489657402038574],
[7890271041, 2.634676933288574],
[8013597291, 4.206743240356445],
[8026055708, 5.857604026794434],
[8032387416, 4.380003929138184],
[8032388666, 2.5249929428100586],
[8170270500, 4.097265243530273],
[8180642250, 5.748095512390137],
[8188875500, 4.270495414733887],
[8188876625, 2.4155149459838867],
[8320641916, 3.9876651763916016],
[8332800958, 5.63852596282959],
[8342211291, 4.16092586517334],
[8342212500, 2.305914878845215],
[8473975291, 3.8780956268310547],
[8484424833, 5.528956413269043],
[8495070500, 4.051356315612793],
[8495071750, 2.196345329284668],
[8626539708, 3.7685108184814453],
[8636981708, 5.419371604919434],
[8643245333, 3.9417715072631836],
[8643246500, 2.0867605209350586],
[8783219791, 3.6589794158935547],
[8792149541, 5.309840202331543],
[8800236916, 3.832240104675293],
[8800238125, 1.977259635925293],
[8935519958, 3.5494556427001953],
[8950778666, 5.200316429138184],
[8950780791, 3.7227163314819336],
[8950782333, 1.8677358627319336],
[9087624208, 3.439970016479492],
[9096657916, 5.0908308029174805],
[9104695375, 3.6132307052612305],
[9104696583, 1.7588300704956055],
[9238711333, 3.331697463989258],
[9249853541, 4.982527732849121],
[9258138375, 3.504927635192871],
[9258139541, 1.649947166442871],
[9393347833, 3.2223033905029297],
[9409346291, 4.873133659362793],
[9409348208, 3.395533561706543],
[9409349583, 1.540553092956543],
[9542842958, 3.1133060455322266],
[9556594875, 4.76413631439209],
[9564736583, 3.28653621673584],
[9564737708, 1.4315252304077148],
[9700385875, 3.0036983489990234],
[9709378000, 4.654559135437012],
[9717558041, 3.1769590377807617],
[9717559333, 1.3219785690307617],
[9849538500, 2.894113540649414],
[9860017000, 4.544974327087402],
[9877549916, 3.0673742294311523],
[9877551125, 1.2123632431030273],
[10003729750, 2.784605026245117],
[10015718125, 4.4354658126831055],
[10022006791, 2.9578657150268555],
[10022007916, 1.1028547286987305],
[10166653041, 2.675233840942383],
[10166656458, 4.231851577758789],
[10176171416, 2.848494529724121],
[10176172583, 0.9934835433959961],
[10309492333, 2.5655269622802734],
[10322073083, 4.216357231140137],
[10343426708, 2.7387571334838867],
[10343427916, 0.8837461471557617],
[10463716625, 2.455934524536133],
[10475263291, 4.106764793395996],
[10483376500, 2.629164695739746],
[10483377708, 0.7741842269897461],
[10613975750, 2.346220016479492],
[10627739125, 3.9970502853393555],
[10635846250, 2.5194501876831055],
[10635847375, 0.6644392013549805],
[10767835750, 2.236543655395508],
[10779923500, 3.887373924255371],
[10788059083, 2.409773826599121],
[10788060250, 0.5547933578491211],
[10926140750, 2.1269893646240234],
[10935088083, 3.7778501510620117],
[10943147250, 2.3002500534057617],
[10943148708, 0.4452695846557617],
[11075597208, 2.017404556274414],
[11088158916, 3.6682348251342773],
[11096836916, 2.1906347274780273],
[11096838208, 0.33562374114990234],
[11232944875, 1.9078807830810547],
[11242620916, 3.558711051940918],
[11257050708, 2.081110954284668],
[11257052000, 0.22613048553466797],
[11384783666, 1.7982349395751953],
[11391132458, 3.4490652084350586],
[11397366583, 1.9714651107788086],
[11397367833, 0.1164541244506836],
[11573774375, 1.6887569427490234],
[11582847833, 3.3396177291870117],
[11591304416, 1.8620176315307617],
[11591305625, 0.007037162780761719],
[11737134291, 1.6248445510864258],
[11737137708, 3.181462287902832],
[11747075916, 1.798105239868164],
[11747077208, -0.05690574645996094],
[11882963625, 1.6248445510864258],
[11893308541, 3.275705337524414],
[11907866833, 1.798105239868164],
[11907868125, -0.05690574645996094],
[12037364666, 1.6248979568481445],
[12046407333, 3.275758743286133],
[12054504875, 1.7981586456298828],
[12054505958, -0.05682182312011719],
[12184473750, 1.6248140335083008],
[12196997083, 3.275674819946289],
[12203330375, 1.798074722290039],
[12203331625, -0.05693626403808594],
[12343375875, 1.6248292922973633],
[12353697041, 3.2756900787353516],
[12366382375, 1.7980899810791016],
[12366383625, -0.05689048767089844],
[12501165625, 1.6248598098754883],
[12519042541, 3.2756900787353516],
[12519044416, 1.7980899810791016],
[12519045666, -0.05689048767089844],
[12651156250, 1.6247835159301758],
[12663171666, 3.275644302368164],
[12669437708, 1.798044204711914],
[12669438958, -0.05696678161621094],
[12815936958, 1.6249208450317383],
[12815939958, 3.1815385818481445],
[12826641666, 1.7981815338134766],
[12826643083, -0.05682945251464844],
[467950083, 9.424517631530762],
[480011041, 11.200347900390625],
[501608208, 13.148506164550781],
[534547000, 15.418411254882812],
[555500041, 13.940811157226562],
[555501500, 12.463211059570312],
[555502500, 10.985610961914062],
[555503458, 9.508010864257812],
[555504583, 7.8679351806640625],
[668153375, 9.315535545349121],
[682672875, 11.09133529663086],
[693283000, 13.03952407836914],
[705307875, 15.309368133544922],
[716903083, 13.831768035888672],
[716904500, 12.354167938232422],
[716905416, 10.876567840576172],
[716906291, 9.398967742919922],
[716907375, 7.758892059326172],
[827231583, 9.205790519714355],
[834454208, 10.982154846191406],
[846991333, 12.930343627929688],
[859534666, 15.200157165527344],
[870443625, 13.722557067871094],
[870444791, 12.244956970214844],
[870445708, 10.767356872558594],
[870446708, 9.289756774902344],
[870447666, 7.649681091308594],
[981257666, 9.09671688079834],
[988426000, 10.872547149658203],
[998615708, 12.820735931396484],
[1013968958, 15.09054946899414],
[1025432666, 13.61294937133789],
[1025433833, 12.13534927368164],
[1025434833, 10.65774917602539],
[1025435791, 9.18014907836914],
[1025436791, 7.540073394775391],
[1140854333, 8.987086296081543],
[1140856500, 10.668673515319824],
[1154928250, 12.711074829101562],
[1167686333, 14.980918884277344],
[1184549000, 13.503318786621094],
[1184550416, 12.025718688964844],
[1184551458, 10.548118591308594],
[1184552458, 9.070518493652344],
[1184553458, 7.430442810058594],
[1294292791, 8.877219200134277],
[1294294875, 10.558806419372559],
[1315191416, 12.601146697998047],
[1315193375, 14.870990753173828],
[1326181208, 13.393390655517578],
[1326182500, 11.915790557861328],
[1326183625, 10.438190460205078],
[1326184458, 8.960590362548828],
[1326185583, 7.320484161376953],
[1441486833, 8.76746654510498],
[1451792333, 10.543296813964844],
[1462320958, 12.491485595703125],
[1474265541, 14.761329650878906],
[1485631291, 13.283729553222656],
[1485632291, 11.806129455566406],
[1485633291, 10.328529357910156],
[1485634291, 8.850929260253906],
[1485635291, 7.210853576660156],
[1594682500, 8.657927513122559],
[1604963750, 10.433757781982422],
[1615432250, 12.381877899169922],
[1621695125, 14.651721954345703],
[1634493000, 13.174121856689453],
[1634494125, 11.696521759033203],
[1634495083, 10.218921661376953],
[1634496041, 8.741321563720703],
[1634497041, 7.101245880126953],
[1747348541, 8.548266410827637],
[1755371166, 10.324043273925781],
[1767914291, 12.272201538085938],
[1780037375, 14.542015075683594],
[1791382833, 13.064414978027344],
[1791385000, 11.586814880371094],
[1791385958, 10.109214782714844],
[1791386875, 8.631614685058594],
[1791387875, 6.991539001464844],
[1898352000, 8.438437461853027],
[1906989791, 10.21426773071289],
[1921336458, 12.162425994873047],
[1930364750, 14.432270050048828],
[1945026333, 12.954669952392578],
[1945027666, 11.477069854736328],
[1945028583, 9.999469757080078],
[1945029458, 8.521869659423828],
[1945030375, 6.881763458251953],
[2053164416, 8.32886791229248],
[2064736083, 10.104667663574219],
[2074923416, 12.0528564453125],
[2081200625, 14.322647094726562],
[2098845208, 12.845046997070312],
[2098846416, 11.367446899414062],
[2098847500, 9.889846801757812],
[2098848500, 8.412246704101562],
[2098849500, 6.7721710205078125],
[2204033833, 8.219252586364746],
[2215335958, 9.99508285522461],
[2226162458, 11.94327163696289],
[2238716250, 14.213115692138672],
[2252120250, 12.735515594482422],
[2252121333, 11.257915496826172],
[2252122291, 9.780315399169922],
[2252123208, 8.302715301513672],
[2252124166, 6.662609100341797],
[2359502083, 8.109652519226074],
[2370129750, 9.885482788085938],
[2376411791, 11.833641052246094],
[2392833625, 14.103485107421875],
[2405350166, 12.625885009765625],
[2405351250, 11.148284912109375],
[2405352208, 9.670684814453125],
[2405353125, 8.193084716796875],
[2405354125, 6.552978515625],
[2519178875, 8.000227928161621],
[2529543875, 9.776058197021484],
[2540148041, 11.724246978759766],
[2558420583, 13.994091033935547],
[2558422291, 12.516490936279297],
[2558423416, 11.038890838623047],
[2558424500, 9.561290740966797],
[2558425541, 8.083690643310547],
[2558426625, 6.443614959716797],
[2672636833, 7.8905439376831055],
[2682918583, 9.666374206542969],
[2693627750, 11.61456298828125],
[2701119666, 13.884407043457031],
[2716928416, 12.406806945800781],
[2716929583, 10.929206848144531],
[2716930500, 9.451606750488281],
[2716931375, 7.974006652832031],
[2716932291, 6.333900451660156],
[2825367125, 7.780882835388184],
[2832063750, 9.556713104248047],
[2843282958, 11.504901885986328],
[2858265166, 13.774715423583984],
[2867822500, 12.297115325927734],
[2867823750, 10.819515228271484],
[2867824666, 9.341915130615234],
[2867825583, 7.864315032958984],
[2867826500, 6.224239349365234],
[2976151416, 7.671832084655762],
[2982453250, 9.4476318359375],
[3005093375, 11.395790100097656],
[3005095291, 13.665634155273438],
[3034657708, 12.188034057617188],
[3034659416, 10.710433959960938],
[3034660333, 9.232833862304688],
[3034661208, 7.7552337646484375],
[3034662125, 6.1151275634765625],
[3130366000, 7.562033653259277],
[3147039333, 9.33786392211914],
[3147041500, 11.286052703857422],
[3157046125, 13.555866241455078],
[3174617541, 12.078266143798828],
[3174618583, 10.600666046142578],
[3174619583, 9.123065948486328],
[3174620458, 7.645465850830078],
[3174621416, 6.005390167236328],
[3282572791, 7.4523115158081055],
[3293275416, 9.228141784667969],
[3299548708, 11.176300048828125],
[3315505500, 13.446144104003906],
[3328157916, 11.968544006347656],
[3328159291, 10.490943908691406],
[3328160333, 9.013343811035156],
[3328161333, 7.535743713378906],
[3328162333, 5.895637512207031],
[3437616291, 7.342848777770996],
[3449239000, 9.11867904663086],
[3459936166, 11.06686782836914],
[3471865958, 13.336711883544922],
[3483698333, 11.859111785888672],
[3483699416, 10.381511688232422],
[3483700375, 8.903911590576172],
[3483701250, 7.426311492919922],
[3483702208, 5.786205291748047],
[3592707750, 7.233248710632324],
[3599236458, 9.009078979492188],
[3613642500, 10.957237243652344],
[3620071666, 13.227081298828125],
[3636928458, 11.749481201171875],
[3636929625, 10.271881103515625],
[3636930541, 8.794281005859375],
[3636931416, 7.316680908203125],
[3636932333, 5.67657470703125],
[3745664583, 7.123595237731934],
[3756017250, 8.899394989013672],
[3766550750, 10.847583770751953],
[3778435291, 13.117427825927734],
[3790088583, 11.639827728271484],
[3790089625, 10.162227630615234],
[3790090583, 8.684627532958984],
[3790091541, 7.207027435302734],
[3790092458, 5.566951751708984],
[3897179625, 7.014147758483887],
[3915726791, 8.789947509765625],
[3915728708, 10.738136291503906],
[3931954708, 13.007949829101562],
[3943414666, 11.530349731445312],
[3943415833, 10.052749633789062],
[3943416833, 8.575149536132812],
[3943417791, 7.0975494384765625],
[3943418750, 5.4574737548828125],
[4050012166, 6.904471397399902],
[4059490750, 8.680301666259766],
[4072037458, 10.628459930419922],
[4084401375, 12.898273468017578],
[4095851958, 11.420673370361328],
[4095853166, 9.943073272705078],
[4095854125, 8.465473175048828],
[4095855041, 6.987873077392578],
[4095856000, 5.347797393798828],
[4205582125, 6.7947187423706055],
[4222331833, 8.570549011230469],
[4222333833, 10.51873779296875],
[4234443333, 12.788551330566406],
[4244777291, 11.310951232910156],
[4244778500, 9.833351135253906],
[4244779416, 8.355751037597656],
[4244780375, 6.878150939941406],
[4244781333, 5.238075256347656],
[4358557708, 6.685088157653809],
[4365447958, 8.460918426513672],
[4379415666, 10.409076690673828],
[4388705500, 12.678852081298828],
[4402726291, 11.201251983642578],
[4402727541, 9.723651885986328],
[4402728583, 8.246051788330078],
[4402729500, 6.768451690673828],
[4402731458, 5.128345489501953],
[4511016083, 6.575533866882324],
[4517762000, 8.351364135742188],
[4531949708, 10.299522399902344],
[4540447250, 12.569366455078125],
[4555231333, 11.091766357421875],
[4555232375, 9.614166259765625],
[4555233291, 8.136566162109375],
[4555234166, 6.658966064453125],
[4555235083, 5.01885986328125],
[4661999000, 6.465842247009277],
[4672057916, 8.24167251586914],
[4684632291, 10.189830780029297],
[4702990625, 12.459644317626953],
[4702992583, 10.982044219970703],
[4702994083, 9.504444122314453],
[4702995291, 8.026844024658203],
[4702996500, 6.549243927001953],
[4702997708, 4.909168243408203],
[4816668083, 6.356287956237793],
[4823797375, 8.132118225097656],
[4836394625, 10.080276489257812],
[4846976125, 12.350120544433594],
[4860942375, 10.872520446777344],
[4860943625, 9.394920349121094],
[4860944625, 7.917320251464844],
[4860945625, 6.439720153808594],
[4860946625, 4.799613952636719],
[4971805333, 6.246832847595215],
[4980344583, 8.022663116455078],
[4992514291, 9.97085189819336],
[5005164791, 12.24069595336914],
[5023308708, 10.76309585571289],
[5023310750, 9.28549575805664],
[5023312208, 7.807895660400391],
[5023313541, 6.330295562744141],
[5023314875, 4.690189361572266],
[5123303583, 6.137148857116699],
[5134428958, 7.9129791259765625],
[5146181666, 9.861167907714844],
[5157165708, 12.131011962890625],
[5167807208, 10.653411865234375],
[5167808375, 9.175811767578125],
[5167809291, 7.698211669921875],
[5167810166, 6.220611572265625],
[5167811083, 4.580535888671875],
[5278674916, 6.027525901794434],
[5288734833, 7.803356170654297],
[5299486333, 9.751514434814453],
[5311409083, 12.021358489990234],
[5322814041, 10.543758392333984],
[5322815333, 9.066158294677734],
[5322816250, 7.588558197021484],
[5322817208, 6.110958099365234],
[5322818250, 4.470882415771484],
[5430328083, 5.917933464050293],
[5441573958, 7.693733215332031],
[5452078208, 9.641921997070312],
[5470314583, 11.911766052246094],
[5470316416, 10.434165954589844],
[5470317708, 8.956565856933594],
[5470318833, 7.478965759277344],
[5470319958, 6.001365661621094],
[5470321125, 4.361289978027344],
[5582194000, 5.80826473236084],
[5592824666, 7.584095001220703],
[5604736458, 9.53225326538086],
[5616646666, 11.80209732055664],
[5628024000, 10.32449722290039],
[5628025125, 8.84689712524414],
[5628026208, 7.369297027587891],
[5628027291, 5.891696929931641],
[5628028375, 4.251621246337891],
[5732471291, 5.698687553405762],
[5746847625, 7.474540710449219],
[5757285625, 9.4227294921875],
[5763546125, 11.692573547363281],
[5776178166, 10.214973449707031],
[5776179291, 8.737373352050781],
[5776180291, 7.259773254394531],
[5776181208, 5.782173156738281],
[5776182166, 4.142097473144531],
[5889375500, 5.589827537536621],
[5896965125, 7.365657806396484],
[5909528000, 9.31381607055664],
[5920176500, 11.583660125732422],
[5932745458, 10.106060028076172],
[5932746541, 8.628459930419922],
[5932747583, 7.150859832763672],
[5932748541, 5.673259735107422],
[5932749541, 4.033153533935547],
[6042220375, 5.480273246765137],
[6052706708, 7.256103515625],
[6059516583, 9.204292297363281],
[6070229500, 11.474136352539062],
[6082723750, 9.996536254882812],
[6082724916, 8.518936157226562],
[6082725916, 7.0413360595703125],
[6082726791, 5.5637359619140625],
[6082727708, 3.9236602783203125],
[6201802458, 5.370619773864746],
[6201804333, 7.052206993103027],
[6216203875, 9.094608306884766],
[6234602791, 11.364452362060547],
[6234604625, 9.886852264404297],
[6234605875, 8.409252166748047],
[6234607041, 6.931652069091797],
[6234608166, 5.454051971435547],
[6234609375, 3.813976287841797],
[6348616125, 5.261004447937012],
[6366779208, 7.036834716796875],
[6366781333, 8.985023498535156],
[6390473000, 11.254837036132812],
[6390474875, 9.777236938476562],
[6390476041, 8.299636840820312],
[6390477041, 6.8220367431640625],
[6390478083, 5.3444366455078125],
[6390479208, 3.7043609619140625],
[6506749583, 5.15134334564209],
[6517145583, 6.927173614501953],
[6527678208, 8.875362396240234],
[6539907833, 11.145206451416016],
[6551332375, 9.667606353759766],
[6551333750, 8.190006256103516],
[6551334708, 6.712406158447266],
[6551335583, 5.234806060791016],
[6551336583, 3.5947303771972656],
[6659821750, 5.041796684265137],
[6670074916, 6.817626953125],
[6680510333, 8.765815734863281],
[6688715083, 11.035659790039062],
[6703736250, 9.558059692382812],
[6703737291, 8.080459594726562],
[6703738250, 6.6028594970703125],
[6703739125, 5.1252593994140625],
[6703740041, 3.4851531982421875],
[6811960416, 4.932135581970215],
[6822391916, 6.707965850830078],
[6832958583, 8.65615463256836],
[6851142875, 10.92599868774414],
[6851144583, 9.44839859008789],
[6851145875, 7.970798492431641],
[6851147041, 6.493198394775391],
[6851148208, 5.015598297119141],
[6851149375, 3.3755226135253906],
[6959931750, 4.822482109069824],
[6981281541, 6.598335266113281],
[6981283541, 8.546524047851562],
[7003760208, 10.816337585449219],
[7003762250, 9.338737487792969],
[7003763541, 7.861137390136719],
[7003764750, 6.383537292480469],
[7003765875, 4.905937194824219],
[7003767041, 3.2658615112304688],
[7124618791, 4.712904930114746],
[7124620708, 6.394492149353027],
[7139070708, 8.436893463134766],
[7151226625, 10.706737518310547],
[7168924875, 9.229137420654297],
[7168926000, 7.751537322998047],
[7168926916, 6.273937225341797],
[7168927833, 4.796337127685547],
[7168928750, 3.156261444091797],
[7271675208, 4.6033735275268555],
[7280306708, 6.379203796386719],
[7286626166, 8.327362060546875],
[7303586708, 10.597206115722656],
[7309867416, 9.119606018066406],
[7309870541, 7.642005920410156],
[7309871375, 6.164405822753906],
[7309872166, 4.686805725097656],
[7309873000, 3.0466995239257812],
[7425296791, 4.493781089782715],
[7432751708, 6.269611358642578],
[7445323166, 8.217769622802734],
[7453590500, 10.487613677978516],
[7466128208, 9.010013580322266],
[7466129333, 7.532413482666016],
[7466130250, 6.054813385009766],
[7466131125, 4.577213287353516],
[7466132083, 2.9371376037597656],
[7585419750, 4.384127616882324],
[7585421583, 6.0656843185424805],
[7600045291, 8.108085632324219],
[7618278500, 10.3779296875],
[7618280291, 8.90032958984375],
[7618281541, 7.4227294921875],
[7618282708, 5.94512939453125],
[7618283833, 4.467529296875],
[7618285000, 2.82745361328125],
[7730206083, 4.274535179138184],
[7739121833, 6.050365447998047],
[7751067958, 7.998554229736328],
[7763611625, 10.268367767333984],
[7773978041, 8.790767669677734],
[7773979083, 7.313167572021484],
[7773980000, 5.835567474365234],
[7773980916, 4.357967376708984],
[7773981875, 2.7178916931152344],
[7890274416, 4.164889335632324],
[7890276458, 5.8464765548706055],
[7899436500, 7.888877868652344],
[7922984291, 10.15869140625],
[7922986000, 8.68109130859375],
[7922987125, 7.2034912109375],
[7922988208, 5.72589111328125],
[7922989333, 4.248291015625],
[7922990458, 2.60821533203125],
[8032392083, 4.055205345153809],
[8052683250, 5.831058502197266],
[8052685166, 7.779247283935547],
[8075218333, 10.049060821533203],
[8075220166, 8.571460723876953],
[8075221458, 7.093860626220703],
[8075222666, 5.616260528564453],
[8075223791, 4.138660430908203],
[8075224958, 2.498584747314453],
[8188880083, 3.9457273483276367],
[8199114875, 5.7215576171875],
[8206809333, 7.669746398925781],
[8221570375, 9.939559936523438],
[8228816583, 8.461959838867188],
[8228817708, 6.9843597412109375],
[8228818750, 5.5067596435546875],
[8228821125, 4.0291595458984375],
[8228822125, 2.3890838623046875],
[8342216583, 3.83615779876709],
[8352695375, 5.611957550048828],
[8363300708, 7.560146331787109],
[8375225958, 9.82999038696289],
[8392941833, 8.35239028930664],
[8392943000, 6.874790191650391],
[8392944166, 5.397190093994141],
[8392945125, 3.9195899963378906],
[8392946125, 2.2795143127441406],
[8495075250, 3.726557731628418],
[8505475458, 5.502388000488281],
[8516066666, 7.4505767822265625],
[8527981166, 9.720420837402344],
[8539415500, 8.242820739746094],
[8539416916, 6.765220642089844],
[8539417916, 5.287620544433594],
[8539418875, 3.8100204467773438],
[8539419833, 2.1699447631835938],
[8649702166, 3.7112159729003906],
[8658581833, 5.392803192138672],
[8669098541, 7.340991973876953],
[8681025250, 9.610836029052734],
[8692400875, 8.133235931396484],
[8692402208, 6.655635833740234],
[8692403208, 5.178035736083984],
[8692404125, 3.7004356384277344],
[8692405291, 2.0603599548339844],
[8800241791, 3.507472038269043],
[8809383500, 5.283302307128906],
[8815657666, 7.2314605712890625],
[8839327000, 9.501304626464844],
[8839328875, 8.023704528808594],
[8839329958, 6.546104431152344],
[8839331000, 5.068504333496094],
[8839332041, 3.5909042358398438],
[8839333125, 1.9508285522460938],
[8950785458, 3.3979177474975586],
[8959493416, 5.173748016357422],
[8973360375, 7.121906280517578],
[8980815625, 9.39175033569336],
[8996633041, 7.914150238037109],
[8996634291, 6.436550140380859],
[8996635333, 4.958950042724609],
[8996636291, 3.4813499450683594],
[8996637333, 1.8412437438964844],
[9104700125, 3.2890424728393555],
[9113232875, 5.065467834472656],
[9119527750, 7.0136260986328125],
[9134379083, 9.283470153808594],
[9144595250, 7.805870056152344],
[9144596541, 6.328269958496094],
[9144597541, 4.850669860839844],
[9144598541, 3.3730697631835938],
[9144599583, 1.7329940795898438],
[9258142833, 3.180159568786621],
[9268505250, 4.955989837646484],
[9276182666, 6.904178619384766],
[9291074458, 9.173992156982422],
[9302424541, 7.696392059326172],
[9302425875, 6.218791961669922],
[9302426833, 4.741191864013672],
[9302427750, 3.263591766357422],
[9302429291, 1.6234855651855469],
[9409353000, 3.070734977722168],
[9416169750, 4.847198486328125],
[9432215166, 6.795356750488281],
[9444124708, 9.065200805664062],
[9455917708, 7.5876007080078125],
[9455918833, 6.1100006103515625],
[9455919791, 4.6324005126953125],
[9455920708, 3.1548004150390625],
[9455921666, 1.5147247314453125],
[9564740958, 2.96176815032959],
[9575088750, 4.737567901611328],
[9585687458, 6.685756683349609],
[9597607791, 8.95560073852539],
[9609052458, 7.478000640869141],
[9609053708, 6.000400543212891],
[9609054833, 4.522800445556641],
[9609055833, 3.0452003479003906],
[9609056833, 1.4051246643066406],
[9717562416, 2.8521909713745117],
[9726166083, 4.628021240234375],
[9732440250, 6.576179504394531],
[9749529833, 8.846023559570312],
[9755954916, 7.3684234619140625],
[9755956166, 5.8908233642578125],
[9755957083, 4.4132232666015625],
[9755957916, 2.9356231689453125],
[9755958833, 1.2955169677734375],
[9877554291, 2.7426061630249023],
[9877556125, 4.424162864685059],
[9898585458, 6.466564178466797],
[9898587625, 8.736408233642578],
[9909523750, 7.258808135986328],
[9909524916, 5.781208038330078],
[9909525791, 4.303607940673828],
[9909526541, 2.826007843017578],
[9909527375, 1.1859016418457031],
[10022011125, 2.6330671310424805],
[10034561666, 4.408866882324219],
[10051395250, 6.3570556640625],
[10051397250, 8.626899719238281],
[10068887916, 7.149299621582031],
[10068889166, 5.671699523925781],
[10068890208, 4.194099426269531],
[10068891166, 2.7164993286132812],
[10068892166, 1.0763931274414062],
[10176176125, 2.523695945739746],
[10187819000, 4.299495697021484],
[10204757041, 6.247684478759766],
[10204759166, 8.517528533935547],
[10228388958, 7.039928436279297],
[10228390458, 5.562328338623047],
[10228391416, 4.084728240966797],
[10228392333, 2.607128143310547],
[10228393333, 0.9670219421386719],
[10343431333, 2.4139585494995117],
[10343433166, 4.095545768737793],
[10351890000, 6.137947082519531],
[10363845958, 8.407791137695312],
[10375247083, 6.9301910400390625],
[10375248166, 5.4525909423828125],
[10375249291, 3.9749908447265625],
[10375250166, 2.4973907470703125],
[10375251208, 0.8573150634765625],
[10483380708, 2.304396629333496],
[10493674791, 4.080226898193359],
[10501163750, 6.028415679931641],
[10516118083, 8.298229217529297],
[10527505583, 6.820629119873047],
[10527506625, 5.343029022216797],
[10527507541, 3.865428924560547],
[10527508416, 2.387828826904297],
[10527510541, 0.7477226257324219],
[10635850375, 2.1946516036987305],
[10646199125, 3.9704818725585938],
[10656751875, 5.918670654296875],
[10663705250, 8.188514709472656],
[10679894000, 6.710914611816406],
[10679895250, 5.233314514160156],
[10679896333, 3.7557144165039062],
[10679897291, 2.2781143188476562],
[10679898291, 0.6380081176757812],
[10788063583, 2.085005760192871],
[10804907041, 3.8608360290527344],
[10804909041, 5.809024810791016],
[10816468125, 8.078838348388672],
[10840273875, 6.601238250732422],
[10840275083, 5.123638153076172],
[10840276041, 3.646038055419922],
[10840276958, 2.168437957763672],
[10840277916, 0.5283622741699219],
[10943152208, 1.9754819869995117],
[10949585416, 3.751312255859375],
[10961035541, 5.699501037597656],
[10976165333, 7.9693145751953125],
[10982958166, 6.4917144775390625],
[10982959416, 5.0141143798828125],
[10982960333, 3.5365142822265625],
[10982961250, 2.0589141845703125],
[10982962166, 0.4188385009765625],
[11096841500, 1.8658361434936523],
[11107369708, 3.6416664123535156],
[11118517000, 5.589855194091797],
[11130516500, 7.859699249267578],
[11142093625, 6.382099151611328],
[11142094750, 4.904499053955078],
[11142095875, 3.426898956298828],
[11142096875, 1.9492988586425781],
[11142097833, 0.3092231750488281],
[11257055291, 1.756342887878418],
[11257057291, 3.437930107116699],
[11266261333, 5.4803314208984375],
[11283573625, 7.750144958496094],
[11290272291, 6.272544860839844],
[11290273625, 4.794944763183594],
[11290274625, 3.3173446655273438],
[11290275541, 1.8397445678710938],
[11290276500, 0.19966888427734375],
[11403672750, 1.7409095764160156],
[11409931750, 3.422496795654297],
[11425560125, 5.370685577392578],
[11438276833, 7.640529632568359],
[11459236583, 6.162929534912109],
[11459240375, 4.685329437255859],
[11459243583, 3.2077293395996094],
[11459246625, 1.7301292419433594],
[11459249958, 0.09005355834960938],
[11591309458, 1.5372495651245117],
[11602022208, 3.313079833984375],
[11608272125, 5.261268615722656],
[11622100375, 7.5311126708984375],
[11637136625, 6.0535125732421875],
[11637137916, 4.5759124755859375],
[11637138875, 3.0983123779296875],
[11637139750, 1.6207122802734375],
[11637140708, -0.0193939208984375],
[11747080875, 1.473306655883789],
[11758417666, 3.3060121536254883],
[11769115541, 5.2542009353637695],
[11781375500, 7.524044990539551],
[11793056791, 6.046444892883301],
[11793058000, 4.568844795227051],
[11793058958, 3.091244697570801],
[11793059875, 1.6136445999145508],
[11793060791, -0.02643108367919922],
[11907871750, 1.473306655883789],
[11907873708, 3.1548938751220703],
[11916298041, 5.2542009353637695],
[11934474833, 7.524044990539551],
[11945984916, 6.046444892883301],
[11945986041, 4.568844795227051],
[11945987000, 3.091244697570801],
[11945990166, 1.6136445999145508],
[11945991125, -0.02643108367919922],
[12054509666, 1.4733905792236328],
[12063261375, 3.3060426712036133],
[12074139125, 5.2542314529418945],
[12084480875, 7.524075508117676],
[12094924791, 6.046475410461426],
[12094925958, 4.568875312805176],
[12094926916, 3.091275215148926],
[12094927791, 1.6136751174926758],
[12094928708, -0.02640056610107422],
[12203334708, 1.473276138305664],
[12217599291, 3.306065559387207],
[12229401583, 5.254254341125488],
[12249113875, 7.5240983963012695],
[12249115833, 6.0464982986450195],
[12249116958, 4.5688982009887695],
[12249117916, 3.0912981033325195],
[12249118833, 1.6136980056762695],
[12249119791, -0.02637767791748047],
[12366387916, 1.4733219146728516],
[12376687958, 3.3060426712036133],
[12383011625, 5.2542009353637695],
[12399670166, 7.524044990539551],
[12412263083, 6.046444892883301],
[12412264250, 4.568844795227051],
[12412265250, 3.091244697570801],
[12412266166, 1.6136445999145508],
[12412267125, -0.02646160125732422],
[12519048833, 1.4732913970947266],
[12531295541, 3.3060121536254883],
[12541782958, 5.2542009353637695],
[12553649041, 7.524044990539551],
[12565102500, 6.046444892883301],
[12565103708, 4.568844795227051],
[12565104750, 3.091244697570801],
[12565105791, 1.6136445999145508],
[12565106833, -0.02643108367919922],
[12669442125, 1.473245620727539],
[12683720416, 3.306065559387207],
[12694433583, 5.254254341125488],
[12712894375, 7.5240983963012695],
[12712897125, 6.0464982986450195],
[12712898291, 4.5688982009887695],
[12712899375, 3.0912981033325195],
[12712900416, 1.6136980056762695],
[12712901541, -0.02637767791748047],
[12826646458, 1.4733829498291016],
[12833011458, 3.3060426712036133],
[12843311041, 5.2542314529418945],
[12859614458, 7.524044990539551],
[12866377916, 6.046444892883301],
[12866379125, 4.568844795227051],
[12866380125, 3.091244697570801],
[12866381125, 1.6136445999145508],
[12866382208, -0.02643108367919922],
[555511875, 9.390792846679688],
[565001708, 11.16716480255127],
[575258416, 13.11535358428955],
[586841333, 15.385197639465332],
[597092625, 17.341931343078613],
[597095916, 15.779431343078613],
[597098041, 18.5227632522583],
[597099375, 16.7727632522583],
[605396958, 19.86289691925049],
[605398791, 17.89414691925049],
[618511291, 21.3744478225708],
[618513333, 19.1556978225708],
[618514583, 17.678105354309082],
[618515833, 16.200505256652832],
[618516958, 14.722905158996582],
[618518083, 13.245305061340332],
[618519250, 11.767704963684082],
[618520750, 7.842289924621582],
[716911291, 9.281749725341797],
[725632333, 11.057496070861816],
[734916625, 13.005684852600098],
[751884791, 15.27541446685791],
[751886958, 17.23214817047119],
[751888625, 15.669648170471191],
[761087791, 18.412949562072754],
[761089500, 16.662949562072754],
[767328041, 19.753045082092285],
[767329375, 17.784295082092285],
[775905583, 21.264504432678223],
[775907250, 19.045754432678223],
[775908375, 17.568161964416504],
[775909333, 16.090561866760254],
[775915375, 14.612961769104004],
[775916750, 13.135361671447754],
[775917708, 11.657761573791504],
[775918666, 7.732377052307129],
[870451875, 9.172538757324219],
[880999041, 10.948307991027832],
[890439291, 12.896496772766113],
[907388625, 15.166340827941895],
[907390625, 17.123074531555176],
[907392791, 15.560574531555176],
[916867125, 18.30387592315674],
[916868541, 16.55387592315674],
[916870375, 19.643986701965332],
[916871500, 17.675236701965332],
[929537916, 21.15550708770752],
[929540000, 18.93675708770752],
[929541083, 17.4591646194458],
[929542083, 15.98156452178955],
[929543041, 14.5039644241333],
[929544000, 13.02636432647705],
[929544916, 11.5487642288208],
[929546125, 7.623379707336426],
[1025440625, 9.062931060791016],
[1031966083, 10.838730812072754],
[1043298000, 12.786919593811035],
[1049550791, 15.056733131408691],
[1064023458, 17.013436317443848],
[1064026791, 15.450936317443848],
[1064028833, 18.19429874420166],
[1064030083, 16.44429874420166],
[1076172333, 19.534432411193848],
[1076173916, 17.565682411193848],
[1083924625, 21.045952796936035],
[1083927666, 18.827202796936035],
[1083928625, 17.349610328674316],
[1083929500, 15.872010231018066],
[1083930416, 14.394410133361816],
[1083931333, 12.916810035705566],
[1083932250, 11.439209938049316],
[1083933166, 7.513794898986816],
[1184557500, 8.953300476074219],
[1184559666, 10.634857177734375],
[1195587500, 12.677258491516113],
[1201858833, 14.94701099395752],
[1217549500, 16.903592109680176],
[1217552375, 15.341092109680176],
[1217554541, 18.08445453643799],
[1217555750, 16.33445453643799],
[1236180458, 19.42455768585205],
[1236182500, 17.45580768585205],
[1236184333, 20.936108589172363],
[1236185500, 18.717358589172363],
[1236186500, 17.239766120910645],
[1236187500, 15.762166023254395],
[1236188583, 14.284565925598145],
[1236189583, 12.806965827941895],
[1236190583, 11.329365730285645],
[1236191541, 7.4039201736450195],
[1338627083, 8.93758487701416],
[1338629291, 10.619111061096191],
[1348636625, 12.567269325256348],
[1361178541, 14.837082862854004],
[1383309833, 16.79378604888916],
[1383312250, 15.23128604888916],
[1383314291, 17.974648475646973],
[1383315458, 16.224648475646973],
[1383317333, 19.31483554840088],
[1383318458, 17.34608554840088],
[1389642333, 20.826355934143066],
[1389644583, 18.607605934143066],
[1389645625, 17.130013465881348],
[1389646583, 15.652413368225098],
[1389647541, 14.174813270568848],
[1389648500, 12.697213172912598],
[1389649416, 11.219613075256348],
[1389650458, 7.294228553771973],
[1485638875, 8.733711242675781],
[1500745250, 10.50951099395752],
[1500747416, 12.4576997756958],
[1509511291, 14.727513313293457],
[1520752041, 16.68424701690674],
[1520754125, 15.121747016906738],
[1529887458, 17.865017890930176],
[1529889000, 16.115017890930176],
[1536118583, 19.20518207550049],
[1536120000, 17.23643207550049],
[1542874458, 20.7167329788208],
[1542876333, 18.4979829788208],
[1542877458, 17.020390510559082],
[1542878458, 15.542790412902832],
[1542879375, 14.065190315246582],
[1542880333, 12.587590217590332],
[1542881250, 11.109990119934082],
[1542882250, 7.184575080871582],
[1634500833, 8.624103546142578],
[1647016583, 10.399903297424316],
[1656918250, 12.348061561584473],
[1667544250, 14.617905616760254],
[1677042708, 16.574639320373535],
[1677044458, 15.012139320373535],
[1677046500, 17.755501747131348],
[1677047708, 16.005501747131348],
[1695595291, 19.09560489654541],
[1695597000, 17.12685489654541],
[1695598708, 20.607155799865723],
[1695599708, 18.388405799865723],
[1695600666, 16.910813331604004],
[1695601583, 15.433213233947754],
[1695602458, 13.955613136291504],
[1695603375, 12.478013038635254],
[1695604291, 11.000412940979004],
[1695605250, 7.074967384338379],
[1791391791, 8.514427185058594],
[1806471458, 10.290196418762207],
[1806473416, 12.238385200500488],
[1815312500, 14.508198738098145],
[1829626958, 16.4649019241333],
[1829629166, 14.9024019241333],
[1829631000, 17.64573383331299],
[1829632208, 15.895733833312988],
[1838273250, 18.985806465148926],
[1838274750, 17.017056465148926],
[1848706625, 20.49729633331299],
[1848708666, 18.27854633331299],
[1848709750, 16.80095386505127],
[1848710666, 15.32335376739502],
[1848711541, 13.84575366973877],
[1848712500, 12.36815357208252],
[1848713416, 10.89055347442627],
[1848714375, 6.9651384353637695],
[1945034541, 8.404621124267578],
[1954097250, 10.180390357971191],
[1963537916, 12.128579139709473],
[1974254208, 14.398423194885254],
[1983813833, 16.355156898498535],
[1983816333, 14.792656898498535],
[1983818375, 17.535988807678223],
[1983819583, 15.785988807678223],
[1992820583, 18.876229286193848],
[1992821875, 16.907479286193848],
[2003450958, 20.387749671936035],
[2003453458, 18.168999671936035],
[2003454708, 16.691407203674316],
[2003455708, 15.213807106018066],
[2003456666, 13.736207008361816],
[2003457583, 12.258606910705566],
[2003458500, 10.781006813049316],
[2003459458, 6.855622291564941],
[2098853583, 8.295028686523438],
[2107703000, 10.070828437805176],
[2117127875, 12.019017219543457],
[2123391375, 14.288861274719238],
[2137372666, 16.245564460754395],
[2137374458, 14.683064460754395],
[2137376375, 17.426396369934082],
[2137377666, 15.676396369934082],
[2144789750, 18.76653003692627],
[2144791208, 16.79778003692627],
[2156970875, 20.278050422668457],
[2156972875, 18.059300422668457],
[2156973958, 16.58170795440674],
[2156974958, 15.104107856750488],
[2156975875, 13.626507759094238],
[2156976791, 12.148907661437988],
[2156977750, 10.671307563781738],
[2156978750, 6.745923042297363],
[2252128250, 8.185497283935547],
[2261111000, 9.96126651763916],
[2270495416, 11.909455299377441],
[2281010250, 14.179299354553223],
[2288727875, 16.136033058166504],
[2288729791, 14.573533058166504],
[2296531666, 17.31686496734619],
[2296533291, 15.566864967346191],
[2296535458, 18.657029151916504],
[2296536625, 16.688279151916504],
[2316518875, 20.16854953765869],
[2316520583, 17.94979953765869],
[2316521625, 16.472207069396973],
[2316522541, 14.994606971740723],
[2316523458, 13.517006874084473],
[2316524375, 12.039406776428223],
[2316525291, 10.561806678771973],
[2316526291, 6.636391639709473],
[2405358041, 8.07586669921875],
[2414186750, 9.851635932922363],
[2423603500, 11.799824714660645],
[2434183083, 14.069668769836426],
[2443616916, 16.026402473449707],
[2443619041, 14.463902473449707],
[2443621208, 17.207234382629395],
[2443622375, 15.457234382629395],
[2451122625, 18.54747486114502],
[2451123916, 16.57872486114502],
[2463408833, 20.058995246887207],
[2463411958, 17.840245246887207],
[2463413041, 16.36265277862549],
[2463414083, 14.885052680969238],
[2463415083, 13.407452583312988],
[2463416083, 11.929852485656738],
[2463417083, 10.452252388000488],
[2463420666, 6.526867866516113],
[2558430208, 7.966442108154297],
[2567834833, 9.742241859436035],
[2581782250, 11.690400123596191],
[2590380458, 13.960183143615723],
[2596683583, 15.916886329650879],
[2596686166, 14.354386329650879],
[2608509958, 17.097771644592285],
[2608511958, 15.347771644592285],
[2608513916, 18.437935829162598],
[2608515083, 16.469185829162598],
[2628441916, 19.949456214904785],
[2628443791, 17.730706214904785],
[2628444875, 16.253113746643066],
[2628445791, 14.775513648986816],
[2628446708, 13.297913551330566],
[2628447625, 11.820313453674316],
[2628448500, 10.342713356018066],
[2628449416, 6.417298316955566],
[2716936291, 7.856758117675781],
[2723704333, 9.63249683380127],
[2729981750, 11.580655097961426],
[2745614583, 13.850468635559082],
[2761433333, 15.807202339172363],
[2761437375, 14.244702339172363],
[2761439458, 16.988064765930176],
[2761440833, 15.238064765930176],
[2761442791, 18.32816791534424],
[2761443958, 16.35941791534424],
[2773086416, 19.83971881866455],
[2773088083, 17.62096881866455],
[2773089208, 16.143376350402832],
[2773090333, 14.665776252746582],
[2773091416, 13.188176155090332],
[2773092583, 11.710576057434082],
[2773093666, 10.232975959777832],
[2773095541, 6.307560920715332],
[2867830583, 7.747097015380859],
[2884560958, 9.522866249084473],
[2884563083, 11.471055030822754],
[2892822375, 13.74086856842041],
[2907884000, 15.698105812072754],
[2907886125, 14.135605812072754],
[2907888000, 16.87893772125244],
[2907889250, 15.128937721252441],
[2915387791, 18.21907138824463],
[2915389375, 16.25032138824463],
[2926667500, 19.73062229156494],
[2926669625, 17.51187229156494],
[2926670625, 16.034279823303223],
[2926671583, 14.556679725646973],
[2926672625, 13.079079627990723],
[2926673625, 11.601479530334473],
[2926674583, 10.123879432678223],
[2926675625, 6.198464393615723],
[3034666125, 7.6379852294921875],
[3034668041, 9.319541931152344],
[3034669750, 11.2677001953125],
[3046989583, 13.631756782531738],
[3060246125, 15.588459968566895],
[3060247916, 14.025959968566895],
[3060249750, 16.769291877746582],
[3060250916, 15.019291877746582],
[3072037500, 18.10942554473877],
[3072039166, 16.14067554473877],
[3086011833, 19.620945930480957],
[3086013958, 17.402195930480957],
[3086015083, 15.924603462219238],
[3086016083, 14.447003364562988],
[3086017166, 12.969403266906738],
[3086018125, 11.491803169250488],
[3086019041, 10.014203071594238],
[3086020000, 6.088788032531738],
[3174625125, 7.528247833251953],
[3183568041, 9.304047584533691],
[3192818916, 11.252236366271973],
[3199073833, 13.522049903869629],
[3219456666, 15.478753089904785],
[3219458958, 13.916253089904785],
[3219460916, 16.659615516662598],
[3219462000, 14.909615516662598],
[3219463708, 17.99971866607666],
[3219464750, 16.03096866607666],
[3232053958, 19.511269569396973],
[3232056041, 17.292519569396973],
[3232057125, 15.814927101135254],
[3232058041, 14.337327003479004],
[3232059000, 12.859726905822754],
[3232059916, 11.382126808166504],
[3232060833, 9.904526710510254],
[3232061791, 5.979111671447754],
[3328167291, 7.418495178222656],
[3337774666, 9.19426441192627],
[3347573000, 11.14245319366455],
[3358798833, 13.412297248840332],
[3375074833, 15.369030952453613],
[3375077125, 13.806530952453613],
[3375079000, 16.549893379211426],
[3375080166, 14.799893379211426],
[3375081916, 17.890103340148926],
[3375083000, 15.921353340148926],
[3382591416, 19.40165424346924],
[3382593625, 17.18290424346924],
[3393229458, 15.70531177520752],
[3393230708, 14.22771167755127],
[3393231500, 12.75011157989502],
[3393232291, 11.27251148223877],
[3393233125, 9.79491138458252],
[3393233916, 5.8694963455200195],
[3483706583, 7.309093475341797],
[3498923166, 9.08486270904541],
[3498925250, 11.033051490783691],
[3507070083, 13.302865028381348],
[3517781541, 15.259598731994629],
[3517784083, 13.697098731994629],
[3534458125, 16.440430641174316],
[3534459625, 14.690430641174316],
[3534461375, 17.78059482574463],
[3534462583, 15.811844825744629],
[3540753750, 19.292115211486816],
[3540760500, 17.073365211486816],
[3540761583, 15.595772743225098],
[3540762500, 14.118172645568848],
[3540763458, 12.640572547912598],
[3540764375, 11.162972450256348],
[3540765291, 9.685372352600098],
[3540766208, 5.759957313537598],
[3636936250, 7.199432373046875],
[3643253833, 8.975232124328613],
[3649555708, 10.92339038848877],
[3665517083, 13.193203926086426],
[3681314625, 15.149937629699707],
[3681316833, 13.587437629699707],
[3681318833, 16.33080005645752],
[3681320000, 14.58080005645752],
[3681321708, 17.670903205871582],
[3681322791, 15.702153205871582],
[3694533125, 19.182454109191895],
[3694535208, 16.963704109191895],
[3694536291, 15.486111640930176],
[3694537250, 14.008511543273926],
[3694538125, 12.530911445617676],
[3694539083, 11.053311347961426],
[3694539958, 9.575711250305176],
[3694540916, 5.650296211242676],
[3790098791, 7.089809417724609],
[3798911541, 8.865555763244629],
[3808257708, 10.81374454498291],
[3815910166, 13.083588600158691],
[3822191208, 15.040291786193848],
[3822193208, 13.477791786193848],
[3828487166, 16.221177101135254],
[3828488500, 14.471177101135254],
[3840441541, 17.561440467834473],
[3840442958, 15.592690467834473],
[3846821041, 19.07296085357666],
[3846822958, 16.85421085357666],
[3846823958, 15.376618385314941],
[3846824875, 13.899018287658691],
[3846825791, 12.421418190002441],
[3846826708, 10.943818092346191],
[3846827583, 9.466217994689941],
[3846828625, 5.540833473205566],
[3943422500, 6.9803619384765625],
[3958368375, 8.756131172180176],
[3958370500, 10.704319953918457],
[3966165833, 12.974133491516113],
[3981619916, 14.93083667755127],
[3981623875, 13.36833667755127],
[3981625791, 16.111668586730957],
[3981626958, 14.361668586730957],
[3989149166, 17.451802253723145],
[3989150791, 15.483052253723145],
[4000965208, 18.963269233703613],
[4000967375, 16.744519233703613],
[4000968458, 15.266926765441895],
[4000969375, 13.789326667785645],
[4000970291, 12.311726570129395],
[4000971208, 10.834126472473145],
[4000972125, 9.356526374816895],
[4000973041, 5.4311418533325195],
[4095860250, 6.870655059814453],
[4105109375, 8.646454811096191],
[4114606291, 10.594643592834473],
[4122073833, 12.864487648010254],
[4134668416, 14.82119083404541],
[4134670708, 13.25869083404541],
[4134672666, 16.002022743225098],
[4134673833, 14.252022743225098],
[4147024291, 17.34212589263916],
[4147025625, 15.37337589263916],
[4153339500, 18.853676795959473],
[4153341291, 16.634926795959473],
[4153342333, 15.157334327697754],
[4153343291, 13.679734230041504],
[4153344250, 12.202134132385254],
[4153345208, 10.724534034729004],
[4153346166, 9.246933937072754],
[4153347125, 5.321518898010254],
[4244786125, 6.760932922363281],
[4257113208, 8.53673267364502],
[4263442208, 10.484890937805176],
[4278888958, 12.754704475402832],
[4294709791, 14.711438179016113],
[4294712000, 13.148938179016113],
[4294713875, 15.892300605773926],
[4294714958, 14.142300605773926],
[4294716666, 17.23240375518799],
[4294717750, 15.263653755187988],
[4306235625, 18.7439546585083],
[4306237708, 16.5252046585083],
[4306238916, 15.047612190246582],
[4306240041, 13.570012092590332],
[4306241166, 12.092411994934082],
[4306242375, 10.614811897277832],
[4306243500, 9.137211799621582],
[4306244625, 5.211796760559082],
[4402735458, 6.651203155517578],
[4411437708, 8.426972389221191],
[4420925333, 10.375161170959473],
[4431466500, 12.645005226135254],
[4438017708, 14.601738929748535],
[4438019375, 13.039238929748535],
[4453015833, 15.782624244689941],
[4453019166, 14.032624244689941],
[4453021166, 17.122788429260254],
[4453022375, 15.154038429260254],
[4459552083, 18.63430881500244],
[4459553666, 16.41555881500244],
[4459554750, 14.937966346740723],
[4459555750, 13.460366249084473],
[4459556708, 11.982766151428223],
[4459557708, 10.505166053771973],
[4459558625, 9.027565956115723],
[4459559625, 5.102150917053223],
[4555238708, 6.541717529296875],
[4563668750, 8.317517280578613],
[4569932541, 10.26567554473877],
[4590304041, 12.535489082336426],
[4590306291, 14.492222785949707],
[4590308416, 12.929722785949707],
[4599289375, 15.67302417755127],
[4599290958, 13.92302417755127],
[4599293041, 17.013188362121582],
[4599294333, 15.044438362121582],
[4611807916, 18.524739265441895],
[4611809708, 16.305989265441895],
[4611810750, 14.828396797180176],
[4611811708, 13.350796699523926],
[4611812708, 11.873196601867676],
[4611813666, 10.395596504211426],
[4611814708, 8.917996406555176],
[4611815791, 4.992581367492676],
[4703001166, 6.431995391845703],
[4717039083, 8.207795143127441],
[4726370083, 10.155983924865723],
[4734432875, 12.425827980041504],
[4740758083, 14.38253116607666],
[4740759958, 12.82003116607666],
[4752320625, 15.563416481018066],
[4752322250, 13.813416481018066],
[4752324041, 16.90358066558838],
[4752325208, 14.934830665588379],
[4765011333, 18.415101051330566],
[4765013416, 16.196351051330566],
[4765014458, 14.718758583068848],
[4765015416, 13.241158485412598],
[4765016375, 11.763558387756348],
[4765017291, 10.285958290100098],
[4765018208, 8.808358192443848],
[4765019166, 4.882973670959473],
[4860951041, 6.322502136230469],
[4869187791, 8.098271369934082],
[4879627916, 10.046460151672363],
[4890477166, 12.316304206848145],
[4897023333, 14.273037910461426],
[4897025583, 12.710537910461426],
[4906051166, 15.453923225402832],
[4906053708, 13.703923225402832],
[4912887500, 16.794087409973145],
[4912889458, 14.825337409973145],
[4919814125, 18.305577278137207],
[4919816208, 16.086827278137207],
[4919817250, 14.609234809875488],
[4919818166, 13.131634712219238],
[4919819125, 11.654034614562988],
[4919820083, 10.176434516906738],
[4919821000, 8.698834419250488],
[4919823833, 4.773419380187988],
[5023320041, 6.213077545166016],
[5023323125, 7.894603729248047],
[5029641916, 9.937005043029785],
[5044781916, 12.206818580627441],
[5050837250, 14.163552284240723],
[5050839333, 12.601052284240723],
[5057138833, 15.34438419342041],
[5057140166, 13.59438419342041],
[5063449041, 16.684517860412598],
[5063450291, 14.715767860412598],
[5069771416, 18.195984840393066],
[5069772708, 15.977234840393066],
[5078160250, 14.499642372131348],
[5078161416, 13.022042274475098],
[5078162333, 11.544442176818848],
[5078163166, 10.066842079162598],
[5078163958, 8.589241981506348],
[5078164916, 4.663826942443848],
[5167815333, 6.1033935546875],
[5177588416, 7.879162788391113],
[5194539583, 9.827351570129395],
[5194541625, 12.097195625305176],
[5202341125, 14.053898811340332],
[5202343416, 12.491398811340332],
[5220412083, 15.23473072052002],
[5220413625, 13.48473072052002],
[5220415500, 16.574894905090332],
[5220416750, 14.606144905090332],
[5226693833, 18.08641529083252],
[5226695916, 15.86766529083252],
[5226696958, 14.3900728225708],
[5226697875, 12.91247272491455],
[5226698833, 11.4348726272583],
[5226699708, 9.95727252960205],
[5226700625, 8.4796724319458],
[5226701625, 4.554257392883301],
[5322822500, 5.993740081787109],
[5331672708, 7.769539833068848],
[5338285250, 9.717728614807129],
[5350854458, 11.987542152404785],
[5359496833, 13.944275856018066],
[5359498666, 12.381775856018066],
[5365814000, 15.125107765197754],
[5365815583, 13.375107765197754],
[5372042791, 16.46524143218994],
[5372044416, 14.496491432189941],
[5380466375, 17.97676181793213],
[5380488791, 15.758011817932129],
[5380490083, 14.28041934967041],
[5380491041, 12.80281925201416],
[5380491958, 11.32521915435791],
[5380492916, 9.84761905670166],
[5380493875, 8.37001895904541],
[5380494875, 4.44460391998291],
[5470324958, 5.884117126464844],
[5478485041, 7.659916877746582],
[5493524500, 9.608075141906738],
[5501088708, 11.87791919708252],
[5507374875, 13.834622383117676],
[5507376791, 12.272122383117676],
[5525673541, 15.015507698059082],
[5525675125, 13.265507698059082],
[5525676916, 16.355671882629395],
[5525678041, 14.386921882629395],
[5532040750, 17.867161750793457],
[5532042333, 15.648411750793457],
[5532043375, 14.170819282531738],
[5532044291, 12.693219184875488],
[5532045208, 11.215619087219238],
[5532046125, 9.738018989562988],
[5532047083, 8.260418891906738],
[5532052375, 4.335034370422363],
[5628032083, 5.774478912353516],
[5636955125, 7.550278663635254],
[5646291708, 9.498467445373535],
[5655363166, 11.768311500549316],
[5661695375, 13.725014686584473],
[5661697125, 12.162514686584473],
[5672175625, 14.905900001525879],
[5672177000, 13.155900001525879],
[5672178875, 16.246033668518066],
[5672180083, 14.277283668518066],
[5684715750, 17.75752353668213],
[5684717625, 15.538773536682129],
[5684718625, 14.06118106842041],
[5684719583, 12.58358097076416],
[5684720500, 11.10598087310791],
[5684721458, 9.62838077545166],
[5684722375, 8.15078067779541],
[5684723333, 4.22536563873291],
[5776186333, 5.664955139160156],
[5788316833, 7.4407548904418945],
[5798866875, 9.38891315460205],
[5809500166, 11.658757209777832],
[5825329666, 13.615490913391113],
[5825332875, 12.052990913391113],
[5825334833, 14.796353340148926],
[5825336000, 13.046353340148926],
[5825337791, 16.13645648956299],
[5825338916, 14.167706489562988],
[5834431250, 17.648655891418457],
[5834432875, 15.429905891418457],
[5843298875, 13.952313423156738],
[5843299958, 12.474713325500488],
[5843300833, 10.997113227844238],
[5843301583, 9.519513130187988],
[5843302416, 8.041913032531738],
[5843303250, 4.116497993469238],
[5932753666, 5.556041717529297],
[5942303625, 7.33181095123291],
[5951736208, 9.279999732971191],
[5968644000, 11.549843788146973],
[5968646000, 13.506577491760254],
[5968647791, 11.944077491760254],
[5983957208, 14.687378883361816],
[5983958916, 12.937378883361816],
[5983961000, 16.02754306793213],
[5983962291, 14.058793067932129],
[5996582875, 17.539063453674316],
[5996584625, 15.320313453674316],
[5996585666, 13.842720985412598],
[5996586625, 12.365120887756348],
[5996587583, 10.887520790100098],
[5996588583, 9.409920692443848],
[5996589541, 7.932320594787598],
[5996590541, 4.006905555725098],
[6082731250, 5.4465179443359375],
[6093244166, 7.222317695617676],
[6099501750, 9.170475959777832],
[6115769500, 11.440289497375488],
[6125370500, 13.39702320098877],
[6125372500, 11.83452320098877],
[6125374500, 14.577885627746582],
[6125375750, 12.827885627746582],
[6137464916, 15.917988777160645],
[6137466583, 13.949238777160645],
[6143755000, 17.429539680480957],
[6143756958, 15.210789680480957],
[6143758041, 13.733197212219238],
[6143759000, 12.255597114562988],
[6143759916, 10.777997016906738],
[6143760833, 9.300396919250488],
[6143761833, 7.822796821594238],
[6143762833, 3.8973817825317383],
[6234613208, 5.336803436279297],
[6243245916, 7.112603187561035],
[6257785875, 9.060761451721191],
[6266030708, 11.330605506896973],
[6272334625, 13.287308692932129],
[6272336875, 11.724808692932129],
[6289988291, 14.468194007873535],
[6289994583, 12.718194007873535],
[6289996458, 15.808358192443848],
[6289997750, 13.839608192443848],
[6302588958, 17.31984806060791],
[6302591208, 15.10109806060791],
[6302592250, 13.623505592346191],
[6302593333, 12.145905494689941],
[6302594291, 10.668305397033691],
[6302595291, 9.190705299377441],
[6302596333, 7.713105201721191],
[6302597333, 3.7877206802368164],
[6390482541, 5.2271881103515625],
[6401091625, 7.002987861633301],
[6412865208, 8.951176643371582],
[6419126333, 11.220990180969238],
[6434483208, 13.177693367004395],
[6434485125, 11.615193367004395],
[6434487250, 14.358555793762207],
[6434488500, 12.608555793762207],
[6446846666, 15.69871997833252],
[6446848666, 13.72996997833252],
[6455603458, 17.210240364074707],
[6455605541, 14.991490364074707],
[6455606666, 13.513897895812988],
[6455607708, 12.036297798156738],
[6455608666, 10.558697700500488],
[6455609625, 9.081097602844238],
[6455610625, 7.603497505187988],
[6455611625, 3.6780824661254883],
[6551340166, 5.117588043212891],
[6566544208, 6.893387794494629],
[6566546333, 8.84157657623291],
[6578061333, 11.111390113830566],
[6602241708, 13.068093299865723],
[6602243916, 11.505593299865723],
[6602245750, 14.248955726623535],
[6602246958, 12.498955726623535],
[6602248666, 15.589142799377441],
[6602249833, 13.620392799377441],
[6608597291, 17.10066318511963],
[6608599250, 14.881913185119629],
[6608600333, 13.40432071685791],
[6608601250, 11.92672061920166],
[6608602208, 10.44912052154541],
[6608603125, 8.97152042388916],
[6608604041, 7.49392032623291],
[6608605041, 3.56850528717041],
[6703743750, 5.0080108642578125],
[6718685916, 6.783780097961426],
[6718688166, 8.731968879699707],
[6726152166, 11.001782417297363],
[6741937000, 12.95848560333252],
[6741946500, 11.39598560333252],
[6741948416, 14.139317512512207],
[6741949708, 12.389317512512207],
[6751076666, 15.479451179504395],
[6751077958, 13.510701179504395],
[6757386000, 16.990971565246582],
[6757387416, 14.772221565246582],
[6763727125, 13.294629096984863],
[6763728416, 11.817028999328613],
[6763729250, 10.339428901672363],
[6763730125, 8.861828804016113],
[6763730958, 7.384228706359863],
[6763731875, 3.4588136672973633],
[6851153291, 4.898349761962891],
[6859499458, 6.674149513244629],
[6874403375, 8.622307777404785],
[6882233666, 10.892151832580566],
[6888538750, 12.848855018615723],
[6888540833, 11.286355018615723],
[6894837291, 14.029740333557129],
[6894838625, 12.279740333557129],
[6906424583, 15.369874000549316],
[6906425833, 13.401124000549316],
[6912790333, 16.881394386291504],
[6912792208, 14.662644386291504],
[6912793375, 13.185051918029785],
[6912794375, 11.707451820373535],
[6912795333, 10.229851722717285],
[6912796250, 8.752251625061035],
[6912797166, 7.274651527404785],
[6912798166, 3.349236488342285],
[7003770375, 4.788688659667969],
[7011609083, 6.564488410949707],
[7027232541, 8.512646675109863],
[7033464583, 10.782490730285645],
[7046696541, 12.739224433898926],
[7046700125, 11.176724433898926],
[7053895583, 13.920056343078613],
[7053897583, 12.170056343078613],
[7053899583, 15.260220527648926],
[7053901000, 13.291470527648926],
[7067522875, 16.771740913391113],
[7067525125, 14.552990913391113],
[7067526250, 13.075398445129395],
[7067527208, 11.597798347473145],
[7067528166, 10.120198249816895],
[7067529125, 8.642598152160645],
[7067530041, 7.1649980545043945],
[7067531041, 3.2395830154418945],
[7168933125, 4.679119110107422],
[7168935083, 6.360675811767578],
[7176566708, 8.403077125549316],
[7191593416, 10.672890663146973],
[7199429333, 12.629624366760254],
[7199431958, 11.067124366760254],
[7206961291, 13.810456275939941],
[7206963041, 12.060456275939941],
[7206965041, 15.150620460510254],
[7206966333, 13.181870460510254],
[7220339958, 16.662171363830566],
[7220342125, 14.443421363830566],
[7220343125, 12.965828895568848],
[7220344083, 11.488228797912598],
[7220345125, 10.010628700256348],
[7220346041, 8.533028602600098],
[7220347000, 7.055428504943848],
[7220348000, 3.1300134658813477],
[7316084791, 4.663830757141113],
[7325138333, 6.3453874588012695],
[7334582041, 8.29357624053955],
[7351638375, 10.563420295715332],
[7351640291, 12.520153999328613],
[7351642375, 10.957653999328613],
[7359897666, 13.7009859085083],
[7359899291, 11.9509859085083],
[7367202916, 15.041119575500488],
[7367204333, 13.072369575500488],
[7373492125, 16.5526704788208],
[7373494375, 14.3339204788208],
[7373495500, 12.856328010559082],
[7373496541, 11.378727912902832],
[7373497541, 9.901127815246582],
[7373498500, 8.423527717590332],
[7373499500, 6.945927619934082],
[7373500541, 3.020512580871582],
[7466136083, 4.459995269775391],
[7476558250, 6.235795021057129],
[7482890041, 8.183953285217285],
[7499235125, 10.453766822814941],
[7508872833, 12.410500526428223],
[7508875125, 10.848000526428223],
[7508877125, 13.591362953186035],
[7508878250, 11.841362953186035],
[7520261125, 14.931496620178223],
[7520262458, 12.962746620178223],
[7528224041, 16.44301700592041],
[7528226333, 14.22426700592041],
[7528227375, 12.746674537658691],
[7528228333, 11.269074440002441],
[7528229250, 9.791474342346191],
[7528230166, 8.313874244689941],
[7528231125, 6.836274147033691],
[7528232125, 2.9108591079711914],
[7618288291, 4.35028076171875],
[7626573083, 6.126080513000488],
[7641592166, 8.074238777160645],
[7649427041, 10.344082832336426],
[7655708291, 12.300786018371582],
[7655710500, 10.738286018371582],
[7667459041, 13.481671333312988],
[7667460708, 11.731671333312988],
[7667462625, 14.8218355178833],
[7667463875, 12.8530855178833],
[7679976541, 16.33335590362549],
[7679978458, 14.114605903625488],
[7679979416, 12.63701343536377],
[7679980375, 11.15941333770752],
[7679981333, 9.68181324005127],
[7679982291, 8.20421314239502],
[7679983208, 6.7266130447387695],
[7679984166, 2.8012285232543945],
[7773985541, 4.240749359130859],
[7784402958, 6.016549110412598],
[7790662125, 7.964707374572754],
[7810971500, 10.23452091217041],
[7810973708, 12.191254615783691],
[7810975291, 10.628754615783691],
[7817748541, 13.372086524963379],
[7817750250, 11.622086524963379],
[7832559291, 14.712220191955566],
[7832561166, 12.743470191955566],
[7832563041, 16.22377109527588],
[7832564083, 14.005021095275879],
[7832565083, 12.52742862701416],
[7832566041, 11.04982852935791],
[7832567000, 9.57222843170166],
[7832570208, 8.09462833404541],
[7832571208, 6.61702823638916],
[7832572333, 2.691582679748535],
[7922994083, 4.13104248046875],
[7932775750, 5.906842231750488],
[7945337000, 7.8550004959106445],
[7953611083, 10.124844551086426],
[7959889083, 12.081547737121582],
[7959891041, 10.519047737121582],
[7966055125, 13.262433052062988],
[7966056500, 11.512433052062988],
[7977993166, 14.602566719055176],
[7977994625, 12.633816719055176],
[7984344791, 16.114087104797363],
[7984346625, 13.895337104797363],
[7984347666, 12.417744636535645],
[7984348583, 10.940144538879395],
[7984349500, 9.462544441223145],
[7984350458, 7.9849443435668945],
[7984351375, 6.5073442459106445],
[7984352333, 2.5819292068481445],
[8075228541, 4.021411895751953],
[8082781916, 5.797211647033691],
[8098281875, 7.745369911193848],
[8108783458, 10.015213966369629],
[8116131166, 11.97194766998291],
[8116133375, 10.40944766998291],
[8124245541, 13.152779579162598],
[8124247208, 11.402779579162598],
[8124249166, 14.49294376373291],
[8124250375, 12.52419376373291],
[8137013625, 16.004494667053223],
[8137015791, 13.785744667053223],
[8137016875, 12.308152198791504],
[8137017791, 10.830552101135254],
[8137018750, 9.352952003479004],
[8137019666, 7.875351905822754],
[8137020583, 6.397751808166504],
[8137021583, 2.472336769104004],
[8228826375, 3.9119415283203125],
[8240680541, 5.687741279602051],
[8251054875, 7.635930061340332],
[8257330708, 9.905743598937988],
[8271154500, 11.862446784973145],
[8271156750, 10.299946784973145],
[8271158666, 13.043309211730957],
[8271159875, 11.293309211730957],
[8282650583, 14.38341236114502],
[8282652833, 12.41466236114502],
[8291123875, 15.894963264465332],
[8291125708, 13.676213264465332],
[8291126750, 12.198620796203613],
[8291127666, 10.721020698547363],
[8291128583, 9.243420600891113],
[8291129541, 7.765820503234863],
[8291130458, 6.288220405578613],
[8291131416, 2.3628053665161133],
[8392950541, 3.8023719787597656],
[8392952708, 5.483928680419922],
[8403638000, 7.52632999420166],
[8409890708, 9.796143531799316],
[8431111916, 11.752846717834473],
[8431113791, 10.190346717834473],
[8431115750, 12.933709144592285],
[8431116958, 11.183709144592285],
[8431118750, 14.273812294006348],
[8431119833, 12.305062294006348],
[8439101375, 15.78536319732666],
[8439102541, 13.56661319732666],
[8449067541, 12.089020729064941],
[8449068750, 10.611420631408691],
[8449069541, 9.133820533752441],
[8449070333, 7.656220436096191],
[8449071166, 6.178620338439941],
[8449072083, 2.2532052993774414],
[8539423791, 3.6928024291992188],
[8548272541, 5.468602180480957],
[8555782416, 7.416790962219238],
[8562089875, 9.686604499816895],
[8583991625, 11.64330768585205],
[8583993625, 10.08080768585205],
[8583995500, 12.824170112609863],
[8583996666, 11.074170112609863],
[8583998375, 14.164273262023926],
[8583999458, 12.195523262023926],
[8597094666, 15.675824165344238],
[8597096583, 13.457074165344238],
[8597097625, 11.97948169708252],
[8597098583, 10.50188159942627],
[8597099541, 9.02428150177002],
[8597100458, 7.5466814041137695],
[8597101416, 6.0690813064575195],
[8597102416, 2.1436662673950195],
[8692409625, 3.5832481384277344],
[8707328333, 5.359017372131348],
[8707330291, 7.307206153869629],
[8717721958, 9.577019691467285],
[8728510041, 11.533753395080566],
[8728512041, 9.971253395080566],
[8742288750, 12.714585304260254],
[8742290625, 10.964585304260254],
[8742292916, 14.054749488830566],
[8742294125, 12.085999488830566],
[8754893791, 15.566239356994629],
[8754895666, 13.347489356994629],
[8754896625, 11.86989688873291],
[8754897541, 10.39229679107666],
[8754898458, 8.91469669342041],
[8754899416, 7.43709659576416],
[8754900333, 5.95949649810791],
[8754901291, 2.034111976623535],
[8839336416, 3.4736557006835938],
[8853248750, 5.249455451965332],
[8862653041, 7.197644233703613],
[8870236500, 9.467488288879395],
[8876539583, 11.42419147491455],
[8876541750, 9.86169147491455],
[8882642625, 12.605076789855957],
[8882643916, 10.855076789855957],
[8894576833, 13.945210456848145],
[8894578125, 11.976460456848145],
[8907180958, 15.456730842590332],
[8907183041, 13.237980842590332],
[8907184083, 11.760388374328613],
[8907185041, 10.282788276672363],
[8907185958, 8.805188179016113],
[8907186875, 7.327588081359863],
[8907187833, 5.849987983703613],
[8907188791, 1.9246034622192383],
[8996641041, 3.3641014099121094],
[9005356000, 5.139870643615723],
[9014702125, 7.088059425354004],
[9025219750, 9.357903480529785],
[9034624208, 11.314637184143066],
[9034626166, 9.752137184143066],
[9034628250, 12.495469093322754],
[9034629458, 10.745469093322754],
[9042829750, 13.835709571838379],
[9042831291, 11.866959571838379],
[9053968125, 15.347229957580566],
[9053969875, 13.128479957580566],
[9053970958, 11.650887489318848],
[9053971916, 10.173287391662598],
[9053972875, 8.695687294006348],
[9053973833, 7.218087196350098],
[9053974791, 5.740487098693848],
[9053975791, 1.8151025772094727],
[9144603041, 3.2558517456054688],
[9157169791, 5.031651496887207],
[9167324958, 6.979809761047363],
[9178110416, 9.249653816223145],
[9194000708, 11.206387519836426],
[9194002458, 9.643887519836426],
[9194004291, 12.387249946594238],
[9194005416, 10.637249946594238],
[9194007125, 13.7273530960083],
[9194008208, 11.7586030960083],
[9201048625, 15.238903999328613],
[9201049833, 13.020153999328613],
[9207340750, 11.542561531066895],
[9207341625, 10.064961433410645],
[9207342375, 8.587361335754395],
[9207343166, 7.1097612380981445],
[9207343958, 5.6321611404418945],
[9207344791, 1.7067461013793945],
[9302433750, 3.146373748779297],
[9311151791, 4.92214298248291],
[9320643791, 6.870331764221191],
[9331272208, 9.140175819396973],
[9338275625, 11.096909523010254],
[9338277291, 9.534409523010254],
[9352660958, 12.27779483795166],
[9352662416, 10.52779483795166],
[9352664291, 13.617959022521973],
[9352665458, 11.649209022521973],
[9360059083, 15.129448890686035],
[9360060875, 12.910698890686035],
[9360061916, 11.433106422424316],
[9360063125, 9.955506324768066],
[9360064083, 8.477906227111816],
[9360065041, 7.000306129455566],
[9360065958, 5.522706031799316],
[9360066916, 1.5973520278930664],
[9455925750, 3.0375823974609375],
[9464776750, 4.813382148742676],
[9472791583, 6.761570930480957],
[9479088208, 9.031384468078613],
[9500772333, 10.98808765411377],
[9500774375, 9.42558765411377],
[9500776333, 12.168950080871582],
[9500777416, 10.418950080871582],
[9500779125, 13.509053230285645],
[9500780208, 11.540303230285645],
[9513728916, 15.020604133605957],
[9513731041, 12.801854133605957],
[9513732125, 11.324261665344238],
[9513733208, 9.846661567687988],
[9513734166, 8.369061470031738],
[9513735083, 6.891461372375488],
[9513736041, 5.413861274719238],
[9513737083, 1.4884462356567383],
[9609060666, 2.9279823303222656],
[9624226000, 4.703782081604004],
[9624228041, 6.651970863342285],
[9634511583, 8.921784400939941],
[9647057208, 10.878487586975098],
[9647059416, 9.315987586975098],
[9647061458, 12.059319496154785],
[9647062708, 10.309319496154785],
[9657363791, 13.399453163146973],
[9657365166, 11.430703163146973],
[9666877791, 14.91097354888916],
[9666879625, 12.69222354888916],
[9666880708, 11.214631080627441],
[9666881666, 9.737030982971191],
[9666882625, 8.259430885314941],
[9666883500, 6.781830787658691],
[9666884416, 5.304230690002441],
[9666885416, 1.3788461685180664],
[9761919625, 2.9126176834106445],
[9770368416, 4.594204902648926],
[9776645458, 6.542363166809082],
[9791089083, 8.812176704406738],
[9806952625, 10.76891040802002],
[9806954875, 9.20641040802002],
[9806956875, 11.949772834777832],
[9806958083, 10.199772834777832],
[9806959875, 13.289875984191895],
[9806961041, 11.321125984191895],
[9816194125, 14.801426887512207],
[9816195458, 12.582676887512207],
[9831393958, 11.105084419250488],
[9831395125, 9.627484321594238],
[9831395958, 8.149884223937988],
[9831396708, 6.672284126281738],
[9831397500, 5.194684028625488],
[9831398333, 1.2692689895629883],
[9916727750, 2.80300235748291],
[9924698208, 4.484589576721191],
[9932873000, 6.432778358459473],
[9939152791, 8.702591896057129],
[9960544500, 10.659295082092285],
[9960546541, 9.096795082092285],
[9960548458, 11.840157508850098],
[9960549666, 10.090157508850098],
[9960551375, 13.18026065826416],
[9960552500, 11.21151065826416],
[9967836458, 14.691811561584473],
[9967837666, 12.473061561584473],
[9974138583, 10.995469093322754],
[9974139666, 9.517868995666504],
[9974140500, 8.040268898010254],
[9974141291, 6.562668800354004],
[9974142041, 5.085068702697754],
[9974142875, 1.159653663635254],
[10068896125, 2.5992507934570312],
[10077671875, 4.3750505447387695],
[10087134041, 6.323239326477051],
[10097715125, 8.593083381652832],
[10107291041, 10.549817085266113],
[10107293375, 8.987317085266113],
[10107295166, 11.7306489944458],
[10107296333, 9.9806489944458],
[10116215208, 13.070889472961426],
[10116216458, 11.102139472961426],
[10126709250, 14.582409858703613],
[10126711791, 12.363659858703613],
[10126712833, 10.886067390441895],
[10126713750, 9.408467292785645],
[10126714750, 7.9308671951293945],
[10126715708, 6.4532670974731445],
[10126716625, 4.9756669998168945],
[10126717625, 1.0502824783325195],
[10228397541, 2.489879608154297],
[10228399541, 4.171436309814453],
[10240194875, 6.213837623596191],
[10247062833, 8.483681678771973],
[10259656541, 10.440384864807129],
[10259658625, 8.877884864807129],
[10272069166, 11.621216773986816],
[10272070916, 9.871216773986816],
[10272072958, 12.961380958557129],
[10272074166, 10.992630958557129],
[10280290916, 14.472870826721191],
[10280293083, 12.254120826721191],
[10280294166, 10.776528358459473],
[10280295125, 9.298928260803223],
[10280296041, 7.821328163146973],
[10280296958, 6.343728065490723],
[10280297875, 4.866127967834473],
[10280298875, 0.9407129287719727],
[10375254875, 2.3801727294921875],
[10383933791, 4.155972480773926],
[10390739291, 6.104161262512207],
[10403268541, 8.373974800109863],
[10413509375, 10.33067798614502],
[10413511125, 8.76817798614502],
[10413513208, 11.511540412902832],
[10413514416, 9.761540412902832],
[10425547875, 12.851696968078613],
[10425549375, 10.882946968078613],
[10431817458, 14.363247871398926],
[10431819250, 12.144497871398926],
[10431820208, 10.666905403137207],
[10431821125, 9.189305305480957],
[10431822041, 7.711705207824707],
[10431822958, 6.234105110168457],
[10431823875, 4.756505012512207],
[10431824833, 0.831089973449707],
[10527514375, 2.270610809326172],
[10542503250, 4.046380043029785],
[10542505083, 5.994568824768066],
[10551167791, 8.264382362365723],
[10565694458, 10.221085548400879],
[10565696666, 8.658585548400879],
[10565698583, 11.401917457580566],
[10565699875, 9.651917457580566],
[10576167333, 12.742051124572754],
[10576169000, 10.773301124572754],
[10585158208, 14.253571510314941],
[10585160333, 12.034821510314941],
[10585161375, 10.557229042053223],
[10585162291, 9.079628944396973],
[10585163208, 7.602028846740723],
[10585164083, 6.124428749084473],
[10585165000, 4.646828651428223],
[10585165916, 0.7214136123657227],
[10679902333, 2.1608657836914062],
[10694787208, 3.9366350173950195],
[10694789208, 5.884823799133301],
[10707466291, 8.154637336730957],
[10718130458, 10.111371040344238],
[10718132125, 8.548871040344238],
[10718133958, 11.292202949523926],
[10718135125, 9.542202949523926],
[10736509375, 12.632336616516113],
[10736511500, 10.663586616516113],
[10736513500, 14.143887519836426],
[10736514541, 11.925137519836426],
[10736515666, 10.447545051574707],
[10736516666, 8.969944953918457],
[10736517708, 7.492344856262207],
[10736518666, 6.014744758605957],
[10736519625, 4.537144660949707],
[10736520625, 0.611699104309082],
[10840282375, 2.051219940185547],
[10840284458, 3.732776641845703],
[10849612583, 5.775177955627441],
[10860022125, 8.045022010803223],
[10872596250, 10.001725196838379],
[10872598458, 8.439225196838379],
[10872600333, 11.182557106018066],
[10872601541, 9.432557106018066],
[10882916125, 12.522690773010254],
[10882917333, 10.553940773010254],
[10905076250, 14.034211158752441],
[10905078166, 11.815461158752441],
[10905079208, 10.337868690490723],
[10905080208, 8.860268592834473],
[10905081250, 7.382668495178223],
[10905082166, 5.905068397521973],
[10905083125, 4.427468299865723],
[10905084125, 0.5020837783813477],
[10982966416, 1.9416961669921875],
[10993338083, 3.717495918273926],
[11003769375, 5.665684700012207],
[11016296041, 7.935528755187988],
[11026691291, 9.892231941223145],
[11026693333, 8.329731941223145],
[11026695250, 11.073094367980957],
[11026696416, 9.323094367980957],
[11037193791, 12.413228034973145],
[11037195125, 10.444478034973145],
[11046151666, 13.924748420715332],
[11046154625, 11.705998420715332],
[11046155666, 10.228405952453613],
[11046156583, 8.750805854797363],
[11046157500, 7.273205757141113],
[11046158416, 5.795605659484863],
[11046159375, 4.318005561828613],
[11046160375, 0.3925905227661133],
[11142101958, 1.8320808410644531],
[11157123166, 3.6078805923461914],
[11157125416, 5.556069374084473],
[11166258041, 7.825882911682129],
[11176659583, 9.78261661529541],
[11176662166, 8.22011661529541],
[11192579791, 10.963448524475098],
[11192581791, 9.213448524475098],
[11192583791, 12.30361270904541],
[11192585083, 10.33486270904541],
[11199880333, 13.815102577209473],
[11199882166, 11.596352577209473],
[11199883250, 10.118760108947754],
[11199884208, 8.641160011291504],
[11199885125, 7.163559913635254],
[11199886041, 5.685959815979004],
[11199886958, 4.208359718322754],
[11199887916, 0.2829751968383789],
[11290280500, 1.7225265502929688],
[11301166458, 3.498326301574707],
[11307445291, 5.446484565734863],
[11323843791, 7.7162981033325195],
[11339677500, 9.6730318069458],
[11339679375, 8.1105318069458],
[11339681416, 10.853894233703613],
[11339682666, 9.103894233703613],
[11339684583, 12.193997383117676],
[11339685750, 10.225247383117676],
[11351282291, 13.705548286437988],
[11351284291, 11.486798286437988],
[11351285416, 10.00920581817627],
[11351286500, 8.53160572052002],
[11351287708, 7.0540056228637695],
[11351288791, 5.5764055252075195],
[11351289875, 4.0988054275512695],
[11351291125, 0.17339038848876953],
[11459265375, 1.6129112243652344],
[11459271833, 3.2944679260253906],
[11479420041, 5.336899757385254],
[11497722458, 7.60671329498291],
[11514445583, 9.563446998596191],
[11514448333, 8.000946998596191],
[11525430250, 10.744309425354004],
[11525432083, 8.994309425354004],
[11531662291, 12.084473609924316],
[11531664625, 10.115723609924316],
[11545973750, 13.595993995666504],
[11545976125, 11.377243995666504],
[11545977125, 9.899651527404785],
[11545978041, 8.422051429748535],
[11545978958, 6.944451332092285],
[11545979875, 5.466851234436035],
[11545980833, 3.989251136779785],
[11545981833, 0.06386661529541016],
[11637145541, 1.5034637451171875],
[11646080291, 3.2986268997192383],
[11655690333, 5.2468156814575195],
[11666421916, 7.516659736633301],
[11676161250, 9.474095344543457],
[11676163416, 7.911595344543457],
[11676165416, 10.654927253723145],
[11676166750, 8.904927253723145],
[11684479916, 11.99516773223877],
[11684481708, 10.02641773223877],
[11694955791, 13.506688117980957],
[11694958083, 11.287938117980957],
[11694959291, 9.810345649719238],
[11694960416, 8.332745552062988],
[11694961500, 6.855145454406738],
[11694962625, 5.377545356750488],
[11694963750, 3.8999452590942383],
[11694964916, -0.02543926239013672],
[11793064583, 1.4964265823364258],
[11801811458, 3.2986574172973633],
[11809493291, 5.2468461990356445],
[11815791500, 7.516659736633301],
[11837618083, 9.473362922668457],
[11837620291, 7.910862922668457],
[11837622083, 10.65422534942627],
[11837623208, 8.90422534942627],
[11837624875, 11.994328498840332],
[11837625916, 10.025578498840332],
[11849392958, 13.505879402160645],
[11849395000, 11.287129402160645],
[11849396166, 9.809536933898926],
[11849397291, 8.331936836242676],
[11849398333, 6.854336738586426],
[11849399375, 5.376736640930176],
[11849400458, 3.899136543273926],
[11849401500, -0.02627849578857422],
[11945996375, 1.4964265823364258],
[11954879916, 3.2986574172973633],
[11964169833, 5.2468461990356445],
[11971820291, 7.516690254211426],
[11984360375, 9.473393440246582],
[11984362416, 7.910893440246582],
[11984364666, 10.65422534942627],
[11984365875, 8.90422534942627],
[11993308500, 11.994359016418457],
[11993309791, 10.025609016418457],
[11999589625, 13.505879402160645],
[11999590958, 11.287129402160645],
[12005909375, 9.809536933898926],
[12005910416, 8.331936836242676],
[12005911166, 6.854336738586426],
[12005911916, 5.376736640930176],
[12005912708, 3.899136543273926],
[12005913541, -0.02627849578857422],
[12094932958, 1.4964570999145508],
[12107397875, 3.2986268997192383],
[12123030833, 5.2468156814575195],
[12123032791, 7.516659736633301],
[12142997375, 9.473362922668457],
[12142999750, 7.910862922668457],
[12143001625, 10.65422534942627],
[12143002833, 8.90422534942627],
[12143004583, 11.994328498840332],
[12143005666, 10.025578498840332],
[12156182250, 13.505879402160645],
[12156184208, 11.287129402160645],
[12156185375, 9.809536933898926],
[12156186333, 8.331936836242676],
[12156187250, 6.854336738586426],
[12156188166, 5.376736640930176],
[12156189083, 3.899136543273926],
[12156190125, -0.02627849578857422],
[12255301583, 1.617100715637207],
[12263787541, 3.2986574172973633],
[12273490541, 5.247906684875488],
[12284254541, 7.517926216125488],
[12294010708, 9.47465991973877],
[12294013166, 7.9121599197387695],
[12294015166, 10.655491828918457],
[12294016375, 8.905491828918457],
[12306510041, 11.995732307434082],
[12306512166, 10.026982307434082],
[12312797208, 13.507283210754395],
[12312800041, 11.288533210754395],
[12312801083, 9.810940742492676],
[12312802000, 8.333340644836426],
[12312802916, 6.855740547180176],
[12312803833, 5.378140449523926],
[12312804750, 3.900540351867676],
[12312805750, -0.02487468719482422],
[12412272458, 1.4963960647583008],
[12420502333, 3.2986574172973633],
[12430569500, 5.2468156814575195],
[12441200041, 7.516659736633301],
[12456973208, 9.473393440246582],
[12456975541, 7.910893440246582],
[12456977458, 10.654255867004395],
[12456978666, 8.904255867004395],
[12456980458, 11.994412422180176],
[12456981583, 10.025662422180176],
[12468596125, 13.505963325500488],
[12468597708, 11.287213325500488],
[12468598875, 9.80962085723877],
[12468600000, 8.33202075958252],
[12468601041, 6.8544206619262695],
[12468602125, 5.3768205642700195],
[12468603416, 3.8992204666137695],
[12468604541, -0.02619457244873047],
[12565110458, 1.4964265823364258],
[12573889833, 3.2986574172973633],
[12583136625, 5.2468461990356445],
[12589988083, 7.516690254211426],
[12602705666, 9.473393440246582],
[12602707625, 7.910893440246582],
[12602709541, 10.65422534942627],
[12602710791, 8.90422534942627],
[12615077666, 11.994389533996582],
[12615079041, 10.025639533996582],
[12622640541, 13.50590991973877],
[12622642583, 11.28715991973877],
[12622643666, 9.80956745147705],
[12622644625, 8.3319673538208],
[12622645541, 6.854367256164551],
[12622646458, 5.376767158508301],
[12622647375, 3.899167060852051],
[12622648375, -0.02624797821044922],
[12712905333, 1.4964799880981445],
[12726887083, 3.2986268997192383],
[12736326000, 5.2468156814575195],
[12742815458, 7.516659736633301],
[12755360666, 9.473362922668457],
[12755362750, 7.910862922668457],
[12761633791, 10.654194831848145],
[12761635208, 8.904194831848145],
[12767878583, 11.994359016418457],
[12767879833, 10.025609016418457],
[12788602125, 13.505879402160645],
[12788604041, 11.287129402160645],
[12788605000, 9.809536933898926],
[12788605916, 8.331936836242676],
[12788606833, 6.854336738586426],
[12788607750, 5.376736640930176],
[12788608708, 3.899136543273926],
[12788609708, -0.02624797821044922],
[12866386083, 1.4964265823364258],
[12877738166, 3.2986574172973633],
[12884012291, 5.2468156814575195],
[12899734875, 7.516629219055176],
[12915539666, 9.473362922668457],
[12915541833, 7.910862922668457],
[12915543916, 10.65422534942627],
[12915545166, 8.90422534942627],
[12915546958, 11.994328498840332],
[12915548083, 10.025578498840332],
[12924181166, 13.505879402160645],
[12924182375, 11.287129402160645],
[12939781208, 9.809536933898926],
[12939782416, 8.331936836242676],
[12939783375, 6.854336738586426],
[12939784208, 5.376736640930176],
[12939785000, 3.899136543273926],
[12939785833, -0.02627849578857422],
],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 15.85280501325518,
n_cpu_percent_python: 58.95372800766973,
n_gpu_percent: 0,
n_growth_mb: 13.413040161132812,
n_malloc_mb: 2366.0141983032227,
n_mallocs: 243,
n_peak_mb: 13.413040161132812,
n_python_fraction: 0.37192399803769643,
n_sys_percent: 1.7721340966865076,
n_usage_fraction: 0.9809516071621144,
},
{
line: "doit2",
lineno: 19,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 2.566693282322446,
n_cpu_percent_python: 12.965426382708367,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.42433226093041604,
n_usage_fraction: 0.0,
},
{
line: "stuff",
lineno: 45,
memory_samples: [
[376561916, 46.03816890716553],
[419515541, 7.945382118225098],
],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 2.1150691718295715,
n_cpu_percent_python: 0.06865792500233953,
n_gpu_percent: 0,
n_growth_mb: 38.45994186401367,
n_malloc_mb: 38.45994186401367,
n_mallocs: 1,
n_peak_mb: 38.45994186401367,
n_python_fraction: 0.0003818475199016959,
n_sys_percent: 0.0,
n_usage_fraction: 0.015945526366630304,
},
],
lines: [
{
line: "import numpy as np\n",
lineno: 1,
memory_samples: [
[255127500, 1.4791831970214844],
[292883416, 3.0510921478271484],
[319242208, 4.622952461242676],
[334186250, 6.100545883178711],
[364484250, 7.5782270431518555],
],
n_avg_mb: 1.4791831970214844,
n_copy_mb_s: 0.17320883014245084,
n_cpu_percent_c: 4.010810602239169,
n_cpu_percent_python: 0.5492634000187162,
n_gpu_percent: 0,
n_growth_mb: 6.004800796508789,
n_malloc_mb: 7.483983993530273,
n_mallocs: 1,
n_peak_mb: 6.004800796508789,
n_python_fraction: 0.0017520807864979666,
n_sys_percent: 0.0,
n_usage_fraction: 0.003102866471255301,
},
{
line: "from numpy import linalg as LA\n",
lineno: 4,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.0,
n_cpu_percent_python: 0.0,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 1,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.0,
n_usage_fraction: 0.0,
},
{
line: " x = [i*i for i in range(0,100000)][99999]\n",
lineno: 12,
memory_samples: [
[428532500, 9.570051193237305],
[445064208, 11.226824760437012],
[467929458, 9.749224662780762],
[467933333, 7.894305229187012],
[651147208, 9.467050552368164],
[661861583, 11.117934226989746],
[668149041, 9.640334129333496],
[668150333, 7.785323143005371],
[810188791, 9.357297897338867],
[819091291, 11.008158683776855],
[827225333, 9.530558586120605],
[827227250, 7.6755781173706055],
[964097833, 9.248224258422852],
[973085041, 10.89908504486084],
[981253250, 9.42148494720459],
[981254500, 7.56650447845459],
[1113670791, 9.138654708862305],
[1126232208, 10.789484977722168],
[1140849791, 9.311884880065918],
[1140851041, 7.456873893737793],
[1267816125, 9.028757095336914],
[1278337458, 10.679617881774902],
[1294287916, 9.202017784118652],
[1294289166, 7.347006797790527],
[1424228291, 8.919004440307617],
[1433313750, 10.569865226745605],
[1441482708, 9.092265129089355],
[1441483875, 7.2372541427612305],
[1576166708, 8.809465408325195],
[1586517375, 10.460295677185059],
[1594678416, 8.982695579528809],
[1594679583, 7.127715110778809],
[1730114333, 8.699773788452148],
[1739212375, 10.350634574890137],
[1747344291, 8.873034477233887],
[1747345666, 7.018054008483887],
[1883137000, 8.589975357055664],
[1898345333, 10.240836143493652],
[1898347625, 8.763236045837402],
[1898349000, 6.908255577087402],
[2042904500, 8.480405807495117],
[2042907958, 10.037023544311523],
[2053159625, 8.653666496276855],
[2053160916, 6.7986555099487305],
[2196880416, 8.370790481567383],
[2196883625, 9.927408218383789],
[2204029583, 8.544051170349121],
[2204030875, 6.689040184020996],
[2338301750, 8.261251449584961],
[2352917083, 9.912020683288574],
[2359497791, 8.434420585632324],
[2359499000, 6.579440116882324],
[2501090625, 8.151735305786133],
[2510295291, 9.802596092224121],
[2519173666, 8.324995994567871],
[2519174875, 6.470015525817871],
[2651119791, 8.042112350463867],
[2663691041, 9.69294261932373],
[2672632583, 8.21534252166748],
[2672633833, 6.3603315353393555],
[2808274125, 7.932390213012695],
[2817241083, 9.583250999450684],
[2825362500, 8.105650901794434],
[2825363708, 6.250670433044434],
[2967276500, 7.823369979858398],
[2967280416, 9.379987716674805],
[2976146916, 7.996630668640137],
[2976148208, 6.141619682312012],
[3109490458, 7.713602066040039],
[3122068833, 9.364432334899902],
[3130361916, 7.886832237243652],
[3130363083, 6.031821250915527],
[3265027166, 7.603918075561523],
[3271320291, 9.254679679870605],
[3282568291, 7.7770795822143555],
[3282569458, 5.9220991134643555],
[3422217791, 7.494386672973633],
[3437609416, 9.145247459411621],
[3437611583, 7.667647361755371],
[3437613041, 5.812666893005371],
[3575513458, 7.384756088256836],
[3584540708, 9.035616874694824],
[3592703166, 7.558016777038574],
[3592704333, 5.703036308288574],
[3723742875, 7.275102615356445],
[3734449208, 8.925963401794434],
[3745659166, 7.448363304138184],
[3745660250, 5.593352317810059],
[3881893166, 7.165685653686523],
[3897173333, 8.816546440124512],
[3897175416, 7.338946342468262],
[3897176666, 5.483965873718262],
[4034441041, 7.056039810180664],
[4050005958, 8.706870079040527],
[4050007583, 7.229269981384277],
[4050008958, 5.374289512634277],
[4184483375, 6.946355819702148],
[4197052708, 8.59711742401123],
[4205576916, 7.1195173263549805],
[4205578166, 5.2645063400268555],
[4347725000, 6.836626052856445],
[4347728041, 8.393243789672852],
[4358553500, 7.009886741638184],
[4358554583, 5.154875755310059],
[4492837750, 6.727071762084961],
[4502908041, 8.377902030944824],
[4511011375, 6.900301933288574],
[4511012541, 5.045321464538574],
[4646531000, 6.617380142211914],
[4661992208, 8.268240928649902],
[4661994166, 6.790640830993652],
[4661995500, 4.935660362243652],
[4805872333, 6.50782585144043],
[4805875458, 8.064443588256836],
[4816663458, 6.681086540222168],
[4816664916, 4.826075553894043],
[4954285750, 6.398340225219727],
[4963335000, 8.049201011657715],
[4971800083, 6.571600914001465],
[4971801291, 4.716620445251465],
[5108196500, 6.288686752319336],
[5123296458, 7.939547538757324],
[5123298416, 6.461947441101074],
[5123299708, 4.606966972351074],
[5261455875, 6.179033279418945],
[5270583000, 7.829894065856934],
[5278670500, 6.352293968200684],
[5278671833, 4.497313499450684],
[5413466541, 6.069440841674805],
[5423099541, 7.720301628112793],
[5430323333, 6.242701530456543],
[5430324625, 4.387721061706543],
[5565807583, 5.959833145141602],
[5575698250, 7.61063289642334],
[5582189041, 6.13303279876709],
[5582190291, 4.27805233001709],
[5713625000, 5.850225448608398],
[5726142000, 7.501086235046387],
[5732466750, 6.023486137390137],
[5732468041, 4.168475151062012],
[5872050708, 5.741365432739258],
[5881280666, 7.392195701599121],
[5889371000, 5.914595603942871],
[5889372208, 4.059615135192871],
[6023858541, 5.631811141967773],
[6033953416, 7.282641410827637],
[6042215291, 5.805041313171387],
[6042216500, 3.9500608444213867],
[6176588416, 5.522188186645508],
[6182908666, 7.173018455505371],
[6201797875, 5.695418357849121],
[6201799041, 3.840407371520996],
[6331915791, 5.412542343139648],
[6348609666, 7.063403129577637],
[6348611833, 5.585803031921387],
[6348613125, 3.7308225631713867],
[6484444250, 5.302881240844727],
[6496964458, 6.953742027282715],
[6506744041, 5.476141929626465],
[6506745250, 3.62113094329834],
[6638721125, 5.193334579467773],
[6651084000, 6.844195365905762],
[6659817208, 5.366595268249512],
[6659818375, 3.5115842819213867],
[6788692208, 5.083703994750977],
[6803875291, 6.73453426361084],
[6811955708, 5.25693416595459],
[6811956916, 3.401923179626465],
[6942827708, 4.974020004272461],
[6953656666, 6.624880790710449],
[6959926041, 5.147280693054199],
[6959927375, 3.292269706726074],
[7096960208, 4.864442825317383],
[7109526708, 6.515303611755371],
[7124614083, 5.037703514099121],
[7124615250, 3.182692527770996],
[7254360708, 4.754880905151367],
[7263431791, 6.4057416915893555],
[7271670041, 4.9281415939331055],
[7271671208, 3.0731611251831055],
[7408255583, 4.645288467407227],
[7417207291, 6.296149253845215],
[7425292250, 4.818549156188965],
[7425293541, 2.963568687438965],
[7557260708, 4.535665512084961],
[7569857958, 6.186495780944824],
[7585415291, 4.708895683288574],
[7585416416, 2.853884696960449],
[7714997916, 4.42607307434082],
[7730199916, 6.076933860778809],
[7730201708, 4.599333763122559],
[7730202916, 2.7443532943725586],
[7866120000, 4.316427230834961],
[7875908250, 5.967257499694824],
[7890269833, 4.489657402038574],
[7890271041, 2.634676933288574],
[8013597291, 4.206743240356445],
[8026055708, 5.857604026794434],
[8032387416, 4.380003929138184],
[8032388666, 2.5249929428100586],
[8170270500, 4.097265243530273],
[8180642250, 5.748095512390137],
[8188875500, 4.270495414733887],
[8188876625, 2.4155149459838867],
[8320641916, 3.9876651763916016],
[8332800958, 5.63852596282959],
[8342211291, 4.16092586517334],
[8342212500, 2.305914878845215],
[8473975291, 3.8780956268310547],
[8484424833, 5.528956413269043],
[8495070500, 4.051356315612793],
[8495071750, 2.196345329284668],
[8626539708, 3.7685108184814453],
[8636981708, 5.419371604919434],
[8643245333, 3.9417715072631836],
[8643246500, 2.0867605209350586],
[8783219791, 3.6589794158935547],
[8792149541, 5.309840202331543],
[8800236916, 3.832240104675293],
[8800238125, 1.977259635925293],
[8935519958, 3.5494556427001953],
[8950778666, 5.200316429138184],
[8950780791, 3.7227163314819336],
[8950782333, 1.8677358627319336],
[9087624208, 3.439970016479492],
[9096657916, 5.0908308029174805],
[9104695375, 3.6132307052612305],
[9104696583, 1.7588300704956055],
[9238711333, 3.331697463989258],
[9249853541, 4.982527732849121],
[9258138375, 3.504927635192871],
[9258139541, 1.649947166442871],
[9393347833, 3.2223033905029297],
[9409346291, 4.873133659362793],
[9409348208, 3.395533561706543],
[9409349583, 1.540553092956543],
[9542842958, 3.1133060455322266],
[9556594875, 4.76413631439209],
[9564736583, 3.28653621673584],
[9564737708, 1.4315252304077148],
[9700385875, 3.0036983489990234],
[9709378000, 4.654559135437012],
[9717558041, 3.1769590377807617],
[9717559333, 1.3219785690307617],
[9849538500, 2.894113540649414],
[9860017000, 4.544974327087402],
[9877549916, 3.0673742294311523],
[9877551125, 1.2123632431030273],
[10003729750, 2.784605026245117],
[10015718125, 4.4354658126831055],
[10022006791, 2.9578657150268555],
[10022007916, 1.1028547286987305],
[10166653041, 2.675233840942383],
[10166656458, 4.231851577758789],
[10176171416, 2.848494529724121],
[10176172583, 0.9934835433959961],
[10309492333, 2.5655269622802734],
[10322073083, 4.216357231140137],
[10343426708, 2.7387571334838867],
[10343427916, 0.8837461471557617],
[10463716625, 2.455934524536133],
[10475263291, 4.106764793395996],
[10483376500, 2.629164695739746],
[10483377708, 0.7741842269897461],
[10613975750, 2.346220016479492],
[10627739125, 3.9970502853393555],
[10635846250, 2.5194501876831055],
[10635847375, 0.6644392013549805],
[10767835750, 2.236543655395508],
[10779923500, 3.887373924255371],
[10788059083, 2.409773826599121],
[10788060250, 0.5547933578491211],
[10926140750, 2.1269893646240234],
[10935088083, 3.7778501510620117],
[10943147250, 2.3002500534057617],
[10943148708, 0.4452695846557617],
[11075597208, 2.017404556274414],
[11088158916, 3.6682348251342773],
[11096836916, 2.1906347274780273],
[11096838208, 0.33562374114990234],
[11232944875, 1.9078807830810547],
[11242620916, 3.558711051940918],
[11257050708, 2.081110954284668],
[11257052000, 0.22613048553466797],
[11384783666, 1.7982349395751953],
[11391132458, 3.4490652084350586],
[11397366583, 1.9714651107788086],
[11397367833, 0.1164541244506836],
[11573774375, 1.6887569427490234],
[11582847833, 3.3396177291870117],
[11591304416, 1.8620176315307617],
[11591305625, 0.007037162780761719],
[11737134291, 1.6248445510864258],
[11737137708, 3.181462287902832],
[11747075916, 1.798105239868164],
[11747077208, -0.05690574645996094],
[11882963625, 1.6248445510864258],
[11893308541, 3.275705337524414],
[11907866833, 1.798105239868164],
[11907868125, -0.05690574645996094],
[12037364666, 1.6248979568481445],
[12046407333, 3.275758743286133],
[12054504875, 1.7981586456298828],
[12054505958, -0.05682182312011719],
[12184473750, 1.6248140335083008],
[12196997083, 3.275674819946289],
[12203330375, 1.798074722290039],
[12203331625, -0.05693626403808594],
[12343375875, 1.6248292922973633],
[12353697041, 3.2756900787353516],
[12366382375, 1.7980899810791016],
[12366383625, -0.05689048767089844],
[12501165625, 1.6248598098754883],
[12519042541, 3.2756900787353516],
[12519044416, 1.7980899810791016],
[12519045666, -0.05689048767089844],
[12651156250, 1.6247835159301758],
[12663171666, 3.275644302368164],
[12669437708, 1.798044204711914],
[12669438958, -0.05696678161621094],
[12815936958, 1.6249208450317383],
[12815939958, 3.1815385818481445],
[12826641666, 1.7981815338134766],
[12826643083, -0.05682945251464844],
],
n_avg_mb: 1.5563542872299383,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 3.2513205077474945,
n_cpu_percent_python: 10.134091287434035,
n_gpu_percent: 0,
n_growth_mb: 1.562530517578125,
n_malloc_mb: 250.06993865966797,
n_mallocs: 81,
n_peak_mb: 1.562530517578125,
n_python_fraction: 0.0704750565601485,
n_sys_percent: 0.21740526694453302,
n_usage_fraction: 0.10367922069404875,
},
{
line: " y1 = [i*i for i in range(0,200000)][199999]\n",
lineno: 13,
memory_samples: [
[467950083, 9.424517631530762],
[480011041, 11.200347900390625],
[501608208, 13.148506164550781],
[534547000, 15.418411254882812],
[555500041, 13.940811157226562],
[555501500, 12.463211059570312],
[555502500, 10.985610961914062],
[555503458, 9.508010864257812],
[555504583, 7.8679351806640625],
[668153375, 9.315535545349121],
[682672875, 11.09133529663086],
[693283000, 13.03952407836914],
[705307875, 15.309368133544922],
[716903083, 13.831768035888672],
[716904500, 12.354167938232422],
[716905416, 10.876567840576172],
[716906291, 9.398967742919922],
[716907375, 7.758892059326172],
[827231583, 9.205790519714355],
[834454208, 10.982154846191406],
[846991333, 12.930343627929688],
[859534666, 15.200157165527344],
[870443625, 13.722557067871094],
[870444791, 12.244956970214844],
[870445708, 10.767356872558594],
[870446708, 9.289756774902344],
[870447666, 7.649681091308594],
[981257666, 9.09671688079834],
[988426000, 10.872547149658203],
[998615708, 12.820735931396484],
[1013968958, 15.09054946899414],
[1025432666, 13.61294937133789],
[1025433833, 12.13534927368164],
[1025434833, 10.65774917602539],
[1025435791, 9.18014907836914],
[1025436791, 7.540073394775391],
[1140854333, 8.987086296081543],
[1140856500, 10.668673515319824],
[1154928250, 12.711074829101562],
[1167686333, 14.980918884277344],
[1184549000, 13.503318786621094],
[1184550416, 12.025718688964844],
[1184551458, 10.548118591308594],
[1184552458, 9.070518493652344],
[1184553458, 7.430442810058594],
[1294292791, 8.877219200134277],
[1294294875, 10.558806419372559],
[1315191416, 12.601146697998047],
[1315193375, 14.870990753173828],
[1326181208, 13.393390655517578],
[1326182500, 11.915790557861328],
[1326183625, 10.438190460205078],
[1326184458, 8.960590362548828],
[1326185583, 7.320484161376953],
[1441486833, 8.76746654510498],
[1451792333, 10.543296813964844],
[1462320958, 12.491485595703125],
[1474265541, 14.761329650878906],
[1485631291, 13.283729553222656],
[1485632291, 11.806129455566406],
[1485633291, 10.328529357910156],
[1485634291, 8.850929260253906],
[1485635291, 7.210853576660156],
[1594682500, 8.657927513122559],
[1604963750, 10.433757781982422],
[1615432250, 12.381877899169922],
[1621695125, 14.651721954345703],
[1634493000, 13.174121856689453],
[1634494125, 11.696521759033203],
[1634495083, 10.218921661376953],
[1634496041, 8.741321563720703],
[1634497041, 7.101245880126953],
[1747348541, 8.548266410827637],
[1755371166, 10.324043273925781],
[1767914291, 12.272201538085938],
[1780037375, 14.542015075683594],
[1791382833, 13.064414978027344],
[1791385000, 11.586814880371094],
[1791385958, 10.109214782714844],
[1791386875, 8.631614685058594],
[1791387875, 6.991539001464844],
[1898352000, 8.438437461853027],
[1906989791, 10.21426773071289],
[1921336458, 12.162425994873047],
[1930364750, 14.432270050048828],
[1945026333, 12.954669952392578],
[1945027666, 11.477069854736328],
[1945028583, 9.999469757080078],
[1945029458, 8.521869659423828],
[1945030375, 6.881763458251953],
[2053164416, 8.32886791229248],
[2064736083, 10.104667663574219],
[2074923416, 12.0528564453125],
[2081200625, 14.322647094726562],
[2098845208, 12.845046997070312],
[2098846416, 11.367446899414062],
[2098847500, 9.889846801757812],
[2098848500, 8.412246704101562],
[2098849500, 6.7721710205078125],
[2204033833, 8.219252586364746],
[2215335958, 9.99508285522461],
[2226162458, 11.94327163696289],
[2238716250, 14.213115692138672],
[2252120250, 12.735515594482422],
[2252121333, 11.257915496826172],
[2252122291, 9.780315399169922],
[2252123208, 8.302715301513672],
[2252124166, 6.662609100341797],
[2359502083, 8.109652519226074],
[2370129750, 9.885482788085938],
[2376411791, 11.833641052246094],
[2392833625, 14.103485107421875],
[2405350166, 12.625885009765625],
[2405351250, 11.148284912109375],
[2405352208, 9.670684814453125],
[2405353125, 8.193084716796875],
[2405354125, 6.552978515625],
[2519178875, 8.000227928161621],
[2529543875, 9.776058197021484],
[2540148041, 11.724246978759766],
[2558420583, 13.994091033935547],
[2558422291, 12.516490936279297],
[2558423416, 11.038890838623047],
[2558424500, 9.561290740966797],
[2558425541, 8.083690643310547],
[2558426625, 6.443614959716797],
[2672636833, 7.8905439376831055],
[2682918583, 9.666374206542969],
[2693627750, 11.61456298828125],
[2701119666, 13.884407043457031],
[2716928416, 12.406806945800781],
[2716929583, 10.929206848144531],
[2716930500, 9.451606750488281],
[2716931375, 7.974006652832031],
[2716932291, 6.333900451660156],
[2825367125, 7.780882835388184],
[2832063750, 9.556713104248047],
[2843282958, 11.504901885986328],
[2858265166, 13.774715423583984],
[2867822500, 12.297115325927734],
[2867823750, 10.819515228271484],
[2867824666, 9.341915130615234],
[2867825583, 7.864315032958984],
[2867826500, 6.224239349365234],
[2976151416, 7.671832084655762],
[2982453250, 9.4476318359375],
[3005093375, 11.395790100097656],
[3005095291, 13.665634155273438],
[3034657708, 12.188034057617188],
[3034659416, 10.710433959960938],
[3034660333, 9.232833862304688],
[3034661208, 7.7552337646484375],
[3034662125, 6.1151275634765625],
[3130366000, 7.562033653259277],
[3147039333, 9.33786392211914],
[3147041500, 11.286052703857422],
[3157046125, 13.555866241455078],
[3174617541, 12.078266143798828],
[3174618583, 10.600666046142578],
[3174619583, 9.123065948486328],
[3174620458, 7.645465850830078],
[3174621416, 6.005390167236328],
[3282572791, 7.4523115158081055],
[3293275416, 9.228141784667969],
[3299548708, 11.176300048828125],
[3315505500, 13.446144104003906],
[3328157916, 11.968544006347656],
[3328159291, 10.490943908691406],
[3328160333, 9.013343811035156],
[3328161333, 7.535743713378906],
[3328162333, 5.895637512207031],
[3437616291, 7.342848777770996],
[3449239000, 9.11867904663086],
[3459936166, 11.06686782836914],
[3471865958, 13.336711883544922],
[3483698333, 11.859111785888672],
[3483699416, 10.381511688232422],
[3483700375, 8.903911590576172],
[3483701250, 7.426311492919922],
[3483702208, 5.786205291748047],
[3592707750, 7.233248710632324],
[3599236458, 9.009078979492188],
[3613642500, 10.957237243652344],
[3620071666, 13.227081298828125],
[3636928458, 11.749481201171875],
[3636929625, 10.271881103515625],
[3636930541, 8.794281005859375],
[3636931416, 7.316680908203125],
[3636932333, 5.67657470703125],
[3745664583, 7.123595237731934],
[3756017250, 8.899394989013672],
[3766550750, 10.847583770751953],
[3778435291, 13.117427825927734],
[3790088583, 11.639827728271484],
[3790089625, 10.162227630615234],
[3790090583, 8.684627532958984],
[3790091541, 7.207027435302734],
[3790092458, 5.566951751708984],
[3897179625, 7.014147758483887],
[3915726791, 8.789947509765625],
[3915728708, 10.738136291503906],
[3931954708, 13.007949829101562],
[3943414666, 11.530349731445312],
[3943415833, 10.052749633789062],
[3943416833, 8.575149536132812],
[3943417791, 7.0975494384765625],
[3943418750, 5.4574737548828125],
[4050012166, 6.904471397399902],
[4059490750, 8.680301666259766],
[4072037458, 10.628459930419922],
[4084401375, 12.898273468017578],
[4095851958, 11.420673370361328],
[4095853166, 9.943073272705078],
[4095854125, 8.465473175048828],
[4095855041, 6.987873077392578],
[4095856000, 5.347797393798828],
[4205582125, 6.7947187423706055],
[4222331833, 8.570549011230469],
[4222333833, 10.51873779296875],
[4234443333, 12.788551330566406],
[4244777291, 11.310951232910156],
[4244778500, 9.833351135253906],
[4244779416, 8.355751037597656],
[4244780375, 6.878150939941406],
[4244781333, 5.238075256347656],
[4358557708, 6.685088157653809],
[4365447958, 8.460918426513672],
[4379415666, 10.409076690673828],
[4388705500, 12.678852081298828],
[4402726291, 11.201251983642578],
[4402727541, 9.723651885986328],
[4402728583, 8.246051788330078],
[4402729500, 6.768451690673828],
[4402731458, 5.128345489501953],
[4511016083, 6.575533866882324],
[4517762000, 8.351364135742188],
[4531949708, 10.299522399902344],
[4540447250, 12.569366455078125],
[4555231333, 11.091766357421875],
[4555232375, 9.614166259765625],
[4555233291, 8.136566162109375],
[4555234166, 6.658966064453125],
[4555235083, 5.01885986328125],
[4661999000, 6.465842247009277],
[4672057916, 8.24167251586914],
[4684632291, 10.189830780029297],
[4702990625, 12.459644317626953],
[4702992583, 10.982044219970703],
[4702994083, 9.504444122314453],
[4702995291, 8.026844024658203],
[4702996500, 6.549243927001953],
[4702997708, 4.909168243408203],
[4816668083, 6.356287956237793],
[4823797375, 8.132118225097656],
[4836394625, 10.080276489257812],
[4846976125, 12.350120544433594],
[4860942375, 10.872520446777344],
[4860943625, 9.394920349121094],
[4860944625, 7.917320251464844],
[4860945625, 6.439720153808594],
[4860946625, 4.799613952636719],
[4971805333, 6.246832847595215],
[4980344583, 8.022663116455078],
[4992514291, 9.97085189819336],
[5005164791, 12.24069595336914],
[5023308708, 10.76309585571289],
[5023310750, 9.28549575805664],
[5023312208, 7.807895660400391],
[5023313541, 6.330295562744141],
[5023314875, 4.690189361572266],
[5123303583, 6.137148857116699],
[5134428958, 7.9129791259765625],
[5146181666, 9.861167907714844],
[5157165708, 12.131011962890625],
[5167807208, 10.653411865234375],
[5167808375, 9.175811767578125],
[5167809291, 7.698211669921875],
[5167810166, 6.220611572265625],
[5167811083, 4.580535888671875],
[5278674916, 6.027525901794434],
[5288734833, 7.803356170654297],
[5299486333, 9.751514434814453],
[5311409083, 12.021358489990234],
[5322814041, 10.543758392333984],
[5322815333, 9.066158294677734],
[5322816250, 7.588558197021484],
[5322817208, 6.110958099365234],
[5322818250, 4.470882415771484],
[5430328083, 5.917933464050293],
[5441573958, 7.693733215332031],
[5452078208, 9.641921997070312],
[5470314583, 11.911766052246094],
[5470316416, 10.434165954589844],
[5470317708, 8.956565856933594],
[5470318833, 7.478965759277344],
[5470319958, 6.001365661621094],
[5470321125, 4.361289978027344],
[5582194000, 5.80826473236084],
[5592824666, 7.584095001220703],
[5604736458, 9.53225326538086],
[5616646666, 11.80209732055664],
[5628024000, 10.32449722290039],
[5628025125, 8.84689712524414],
[5628026208, 7.369297027587891],
[5628027291, 5.891696929931641],
[5628028375, 4.251621246337891],
[5732471291, 5.698687553405762],
[5746847625, 7.474540710449219],
[5757285625, 9.4227294921875],
[5763546125, 11.692573547363281],
[5776178166, 10.214973449707031],
[5776179291, 8.737373352050781],
[5776180291, 7.259773254394531],
[5776181208, 5.782173156738281],
[5776182166, 4.142097473144531],
[5889375500, 5.589827537536621],
[5896965125, 7.365657806396484],
[5909528000, 9.31381607055664],
[5920176500, 11.583660125732422],
[5932745458, 10.106060028076172],
[5932746541, 8.628459930419922],
[5932747583, 7.150859832763672],
[5932748541, 5.673259735107422],
[5932749541, 4.033153533935547],
[6042220375, 5.480273246765137],
[6052706708, 7.256103515625],
[6059516583, 9.204292297363281],
[6070229500, 11.474136352539062],
[6082723750, 9.996536254882812],
[6082724916, 8.518936157226562],
[6082725916, 7.0413360595703125],
[6082726791, 5.5637359619140625],
[6082727708, 3.9236602783203125],
[6201802458, 5.370619773864746],
[6201804333, 7.052206993103027],
[6216203875, 9.094608306884766],
[6234602791, 11.364452362060547],
[6234604625, 9.886852264404297],
[6234605875, 8.409252166748047],
[6234607041, 6.931652069091797],
[6234608166, 5.454051971435547],
[6234609375, 3.813976287841797],
[6348616125, 5.261004447937012],
[6366779208, 7.036834716796875],
[6366781333, 8.985023498535156],
[6390473000, 11.254837036132812],
[6390474875, 9.777236938476562],
[6390476041, 8.299636840820312],
[6390477041, 6.8220367431640625],
[6390478083, 5.3444366455078125],
[6390479208, 3.7043609619140625],
[6506749583, 5.15134334564209],
[6517145583, 6.927173614501953],
[6527678208, 8.875362396240234],
[6539907833, 11.145206451416016],
[6551332375, 9.667606353759766],
[6551333750, 8.190006256103516],
[6551334708, 6.712406158447266],
[6551335583, 5.234806060791016],
[6551336583, 3.5947303771972656],
[6659821750, 5.041796684265137],
[6670074916, 6.817626953125],
[6680510333, 8.765815734863281],
[6688715083, 11.035659790039062],
[6703736250, 9.558059692382812],
[6703737291, 8.080459594726562],
[6703738250, 6.6028594970703125],
[6703739125, 5.1252593994140625],
[6703740041, 3.4851531982421875],
[6811960416, 4.932135581970215],
[6822391916, 6.707965850830078],
[6832958583, 8.65615463256836],
[6851142875, 10.92599868774414],
[6851144583, 9.44839859008789],
[6851145875, 7.970798492431641],
[6851147041, 6.493198394775391],
[6851148208, 5.015598297119141],
[6851149375, 3.3755226135253906],
[6959931750, 4.822482109069824],
[6981281541, 6.598335266113281],
[6981283541, 8.546524047851562],
[7003760208, 10.816337585449219],
[7003762250, 9.338737487792969],
[7003763541, 7.861137390136719],
[7003764750, 6.383537292480469],
[7003765875, 4.905937194824219],
[7003767041, 3.2658615112304688],
[7124618791, 4.712904930114746],
[7124620708, 6.394492149353027],
[7139070708, 8.436893463134766],
[7151226625, 10.706737518310547],
[7168924875, 9.229137420654297],
[7168926000, 7.751537322998047],
[7168926916, 6.273937225341797],
[7168927833, 4.796337127685547],
[7168928750, 3.156261444091797],
[7271675208, 4.6033735275268555],
[7280306708, 6.379203796386719],
[7286626166, 8.327362060546875],
[7303586708, 10.597206115722656],
[7309867416, 9.119606018066406],
[7309870541, 7.642005920410156],
[7309871375, 6.164405822753906],
[7309872166, 4.686805725097656],
[7309873000, 3.0466995239257812],
[7425296791, 4.493781089782715],
[7432751708, 6.269611358642578],
[7445323166, 8.217769622802734],
[7453590500, 10.487613677978516],
[7466128208, 9.010013580322266],
[7466129333, 7.532413482666016],
[7466130250, 6.054813385009766],
[7466131125, 4.577213287353516],
[7466132083, 2.9371376037597656],
[7585419750, 4.384127616882324],
[7585421583, 6.0656843185424805],
[7600045291, 8.108085632324219],
[7618278500, 10.3779296875],
[7618280291, 8.90032958984375],
[7618281541, 7.4227294921875],
[7618282708, 5.94512939453125],
[7618283833, 4.467529296875],
[7618285000, 2.82745361328125],
[7730206083, 4.274535179138184],
[7739121833, 6.050365447998047],
[7751067958, 7.998554229736328],
[7763611625, 10.268367767333984],
[7773978041, 8.790767669677734],
[7773979083, 7.313167572021484],
[7773980000, 5.835567474365234],
[7773980916, 4.357967376708984],
[7773981875, 2.7178916931152344],
[7890274416, 4.164889335632324],
[7890276458, 5.8464765548706055],
[7899436500, 7.888877868652344],
[7922984291, 10.15869140625],
[7922986000, 8.68109130859375],
[7922987125, 7.2034912109375],
[7922988208, 5.72589111328125],
[7922989333, 4.248291015625],
[7922990458, 2.60821533203125],
[8032392083, 4.055205345153809],
[8052683250, 5.831058502197266],
[8052685166, 7.779247283935547],
[8075218333, 10.049060821533203],
[8075220166, 8.571460723876953],
[8075221458, 7.093860626220703],
[8075222666, 5.616260528564453],
[8075223791, 4.138660430908203],
[8075224958, 2.498584747314453],
[8188880083, 3.9457273483276367],
[8199114875, 5.7215576171875],
[8206809333, 7.669746398925781],
[8221570375, 9.939559936523438],
[8228816583, 8.461959838867188],
[8228817708, 6.9843597412109375],
[8228818750, 5.5067596435546875],
[8228821125, 4.0291595458984375],
[8228822125, 2.3890838623046875],
[8342216583, 3.83615779876709],
[8352695375, 5.611957550048828],
[8363300708, 7.560146331787109],
[8375225958, 9.82999038696289],
[8392941833, 8.35239028930664],
[8392943000, 6.874790191650391],
[8392944166, 5.397190093994141],
[8392945125, 3.9195899963378906],
[8392946125, 2.2795143127441406],
[8495075250, 3.726557731628418],
[8505475458, 5.502388000488281],
[8516066666, 7.4505767822265625],
[8527981166, 9.720420837402344],
[8539415500, 8.242820739746094],
[8539416916, 6.765220642089844],
[8539417916, 5.287620544433594],
[8539418875, 3.8100204467773438],
[8539419833, 2.1699447631835938],
[8649702166, 3.7112159729003906],
[8658581833, 5.392803192138672],
[8669098541, 7.340991973876953],
[8681025250, 9.610836029052734],
[8692400875, 8.133235931396484],
[8692402208, 6.655635833740234],
[8692403208, 5.178035736083984],
[8692404125, 3.7004356384277344],
[8692405291, 2.0603599548339844],
[8800241791, 3.507472038269043],
[8809383500, 5.283302307128906],
[8815657666, 7.2314605712890625],
[8839327000, 9.501304626464844],
[8839328875, 8.023704528808594],
[8839329958, 6.546104431152344],
[8839331000, 5.068504333496094],
[8839332041, 3.5909042358398438],
[8839333125, 1.9508285522460938],
[8950785458, 3.3979177474975586],
[8959493416, 5.173748016357422],
[8973360375, 7.121906280517578],
[8980815625, 9.39175033569336],
[8996633041, 7.914150238037109],
[8996634291, 6.436550140380859],
[8996635333, 4.958950042724609],
[8996636291, 3.4813499450683594],
[8996637333, 1.8412437438964844],
[9104700125, 3.2890424728393555],
[9113232875, 5.065467834472656],
[9119527750, 7.0136260986328125],
[9134379083, 9.283470153808594],
[9144595250, 7.805870056152344],
[9144596541, 6.328269958496094],
[9144597541, 4.850669860839844],
[9144598541, 3.3730697631835938],
[9144599583, 1.7329940795898438],
[9258142833, 3.180159568786621],
[9268505250, 4.955989837646484],
[9276182666, 6.904178619384766],
[9291074458, 9.173992156982422],
[9302424541, 7.696392059326172],
[9302425875, 6.218791961669922],
[9302426833, 4.741191864013672],
[9302427750, 3.263591766357422],
[9302429291, 1.6234855651855469],
[9409353000, 3.070734977722168],
[9416169750, 4.847198486328125],
[9432215166, 6.795356750488281],
[9444124708, 9.065200805664062],
[9455917708, 7.5876007080078125],
[9455918833, 6.1100006103515625],
[9455919791, 4.6324005126953125],
[9455920708, 3.1548004150390625],
[9455921666, 1.5147247314453125],
[9564740958, 2.96176815032959],
[9575088750, 4.737567901611328],
[9585687458, 6.685756683349609],
[9597607791, 8.95560073852539],
[9609052458, 7.478000640869141],
[9609053708, 6.000400543212891],
[9609054833, 4.522800445556641],
[9609055833, 3.0452003479003906],
[9609056833, 1.4051246643066406],
[9717562416, 2.8521909713745117],
[9726166083, 4.628021240234375],
[9732440250, 6.576179504394531],
[9749529833, 8.846023559570312],
[9755954916, 7.3684234619140625],
[9755956166, 5.8908233642578125],
[9755957083, 4.4132232666015625],
[9755957916, 2.9356231689453125],
[9755958833, 1.2955169677734375],
[9877554291, 2.7426061630249023],
[9877556125, 4.424162864685059],
[9898585458, 6.466564178466797],
[9898587625, 8.736408233642578],
[9909523750, 7.258808135986328],
[9909524916, 5.781208038330078],
[9909525791, 4.303607940673828],
[9909526541, 2.826007843017578],
[9909527375, 1.1859016418457031],
[10022011125, 2.6330671310424805],
[10034561666, 4.408866882324219],
[10051395250, 6.3570556640625],
[10051397250, 8.626899719238281],
[10068887916, 7.149299621582031],
[10068889166, 5.671699523925781],
[10068890208, 4.194099426269531],
[10068891166, 2.7164993286132812],
[10068892166, 1.0763931274414062],
[10176176125, 2.523695945739746],
[10187819000, 4.299495697021484],
[10204757041, 6.247684478759766],
[10204759166, 8.517528533935547],
[10228388958, 7.039928436279297],
[10228390458, 5.562328338623047],
[10228391416, 4.084728240966797],
[10228392333, 2.607128143310547],
[10228393333, 0.9670219421386719],
[10343431333, 2.4139585494995117],
[10343433166, 4.095545768737793],
[10351890000, 6.137947082519531],
[10363845958, 8.407791137695312],
[10375247083, 6.9301910400390625],
[10375248166, 5.4525909423828125],
[10375249291, 3.9749908447265625],
[10375250166, 2.4973907470703125],
[10375251208, 0.8573150634765625],
[10483380708, 2.304396629333496],
[10493674791, 4.080226898193359],
[10501163750, 6.028415679931641],
[10516118083, 8.298229217529297],
[10527505583, 6.820629119873047],
[10527506625, 5.343029022216797],
[10527507541, 3.865428924560547],
[10527508416, 2.387828826904297],
[10527510541, 0.7477226257324219],
[10635850375, 2.1946516036987305],
[10646199125, 3.9704818725585938],
[10656751875, 5.918670654296875],
[10663705250, 8.188514709472656],
[10679894000, 6.710914611816406],
[10679895250, 5.233314514160156],
[10679896333, 3.7557144165039062],
[10679897291, 2.2781143188476562],
[10679898291, 0.6380081176757812],
[10788063583, 2.085005760192871],
[10804907041, 3.8608360290527344],
[10804909041, 5.809024810791016],
[10816468125, 8.078838348388672],
[10840273875, 6.601238250732422],
[10840275083, 5.123638153076172],
[10840276041, 3.646038055419922],
[10840276958, 2.168437957763672],
[10840277916, 0.5283622741699219],
[10943152208, 1.9754819869995117],
[10949585416, 3.751312255859375],
[10961035541, 5.699501037597656],
[10976165333, 7.9693145751953125],
[10982958166, 6.4917144775390625],
[10982959416, 5.0141143798828125],
[10982960333, 3.5365142822265625],
[10982961250, 2.0589141845703125],
[10982962166, 0.4188385009765625],
[11096841500, 1.8658361434936523],
[11107369708, 3.6416664123535156],
[11118517000, 5.589855194091797],
[11130516500, 7.859699249267578],
[11142093625, 6.382099151611328],
[11142094750, 4.904499053955078],
[11142095875, 3.426898956298828],
[11142096875, 1.9492988586425781],
[11142097833, 0.3092231750488281],
[11257055291, 1.756342887878418],
[11257057291, 3.437930107116699],
[11266261333, 5.4803314208984375],
[11283573625, 7.750144958496094],
[11290272291, 6.272544860839844],
[11290273625, 4.794944763183594],
[11290274625, 3.3173446655273438],
[11290275541, 1.8397445678710938],
[11290276500, 0.19966888427734375],
[11403672750, 1.7409095764160156],
[11409931750, 3.422496795654297],
[11425560125, 5.370685577392578],
[11438276833, 7.640529632568359],
[11459236583, 6.162929534912109],
[11459240375, 4.685329437255859],
[11459243583, 3.2077293395996094],
[11459246625, 1.7301292419433594],
[11459249958, 0.09005355834960938],
[11591309458, 1.5372495651245117],
[11602022208, 3.313079833984375],
[11608272125, 5.261268615722656],
[11622100375, 7.5311126708984375],
[11637136625, 6.0535125732421875],
[11637137916, 4.5759124755859375],
[11637138875, 3.0983123779296875],
[11637139750, 1.6207122802734375],
[11637140708, -0.0193939208984375],
[11747080875, 1.473306655883789],
[11758417666, 3.3060121536254883],
[11769115541, 5.2542009353637695],
[11781375500, 7.524044990539551],
[11793056791, 6.046444892883301],
[11793058000, 4.568844795227051],
[11793058958, 3.091244697570801],
[11793059875, 1.6136445999145508],
[11793060791, -0.02643108367919922],
[11907871750, 1.473306655883789],
[11907873708, 3.1548938751220703],
[11916298041, 5.2542009353637695],
[11934474833, 7.524044990539551],
[11945984916, 6.046444892883301],
[11945986041, 4.568844795227051],
[11945987000, 3.091244697570801],
[11945990166, 1.6136445999145508],
[11945991125, -0.02643108367919922],
[12054509666, 1.4733905792236328],
[12063261375, 3.3060426712036133],
[12074139125, 5.2542314529418945],
[12084480875, 7.524075508117676],
[12094924791, 6.046475410461426],
[12094925958, 4.568875312805176],
[12094926916, 3.091275215148926],
[12094927791, 1.6136751174926758],
[12094928708, -0.02640056610107422],
[12203334708, 1.473276138305664],
[12217599291, 3.306065559387207],
[12229401583, 5.254254341125488],
[12249113875, 7.5240983963012695],
[12249115833, 6.0464982986450195],
[12249116958, 4.5688982009887695],
[12249117916, 3.0912981033325195],
[12249118833, 1.6136980056762695],
[12249119791, -0.02637767791748047],
[12366387916, 1.4733219146728516],
[12376687958, 3.3060426712036133],
[12383011625, 5.2542009353637695],
[12399670166, 7.524044990539551],
[12412263083, 6.046444892883301],
[12412264250, 4.568844795227051],
[12412265250, 3.091244697570801],
[12412266166, 1.6136445999145508],
[12412267125, -0.02646160125732422],
[12519048833, 1.4732913970947266],
[12531295541, 3.3060121536254883],
[12541782958, 5.2542009353637695],
[12553649041, 7.524044990539551],
[12565102500, 6.046444892883301],
[12565103708, 4.568844795227051],
[12565104750, 3.091244697570801],
[12565105791, 1.6136445999145508],
[12565106833, -0.02643108367919922],
[12669442125, 1.473245620727539],
[12683720416, 3.306065559387207],
[12694433583, 5.254254341125488],
[12712894375, 7.5240983963012695],
[12712897125, 6.0464982986450195],
[12712898291, 4.5688982009887695],
[12712899375, 3.0912981033325195],
[12712900416, 1.6136980056762695],
[12712901541, -0.02637767791748047],
[12826646458, 1.4733829498291016],
[12833011458, 3.3060426712036133],
[12843311041, 5.2542314529418945],
[12859614458, 7.524044990539551],
[12866377916, 6.046444892883301],
[12866379125, 4.568844795227051],
[12866380125, 3.091244697570801],
[12866381125, 1.6136445999145508],
[12866382208, -0.02643108367919922],
],
n_avg_mb: 7.3380991617838545,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 7.174404078555208,
n_cpu_percent_python: 20.677884165844787,
n_gpu_percent: 0,
n_growth_mb: 7.4304046630859375,
n_malloc_mb: 601.8158340454102,
n_mallocs: 81,
n_peak_mb: 7.4304046630859375,
n_python_fraction: 0.11390462197583993,
n_sys_percent: 0.5389171972072154,
n_usage_fraction: 0.24951338417403499,
},
{
line: " z1 = [i for i in range(0,300000)][299999]\n",
lineno: 14,
memory_samples: [
[555511875, 9.390792846679688],
[565001708, 11.16716480255127],
[575258416, 13.11535358428955],
[586841333, 15.385197639465332],
[597092625, 17.341931343078613],
[597095916, 15.779431343078613],
[597098041, 18.5227632522583],
[597099375, 16.7727632522583],
[605396958, 19.86289691925049],
[605398791, 17.89414691925049],
[618511291, 21.3744478225708],
[618513333, 19.1556978225708],
[618514583, 17.678105354309082],
[618515833, 16.200505256652832],
[618516958, 14.722905158996582],
[618518083, 13.245305061340332],
[618519250, 11.767704963684082],
[618520750, 7.842289924621582],
[716911291, 9.281749725341797],
[725632333, 11.057496070861816],
[734916625, 13.005684852600098],
[751884791, 15.27541446685791],
[751886958, 17.23214817047119],
[751888625, 15.669648170471191],
[761087791, 18.412949562072754],
[761089500, 16.662949562072754],
[767328041, 19.753045082092285],
[767329375, 17.784295082092285],
[775905583, 21.264504432678223],
[775907250, 19.045754432678223],
[775908375, 17.568161964416504],
[775909333, 16.090561866760254],
[775915375, 14.612961769104004],
[775916750, 13.135361671447754],
[775917708, 11.657761573791504],
[775918666, 7.732377052307129],
[870451875, 9.172538757324219],
[880999041, 10.948307991027832],
[890439291, 12.896496772766113],
[907388625, 15.166340827941895],
[907390625, 17.123074531555176],
[907392791, 15.560574531555176],
[916867125, 18.30387592315674],
[916868541, 16.55387592315674],
[916870375, 19.643986701965332],
[916871500, 17.675236701965332],
[929537916, 21.15550708770752],
[929540000, 18.93675708770752],
[929541083, 17.4591646194458],
[929542083, 15.98156452178955],
[929543041, 14.5039644241333],
[929544000, 13.02636432647705],
[929544916, 11.5487642288208],
[929546125, 7.623379707336426],
[1025440625, 9.062931060791016],
[1031966083, 10.838730812072754],
[1043298000, 12.786919593811035],
[1049550791, 15.056733131408691],
[1064023458, 17.013436317443848],
[1064026791, 15.450936317443848],
[1064028833, 18.19429874420166],
[1064030083, 16.44429874420166],
[1076172333, 19.534432411193848],
[1076173916, 17.565682411193848],
[1083924625, 21.045952796936035],
[1083927666, 18.827202796936035],
[1083928625, 17.349610328674316],
[1083929500, 15.872010231018066],
[1083930416, 14.394410133361816],
[1083931333, 12.916810035705566],
[1083932250, 11.439209938049316],
[1083933166, 7.513794898986816],
[1184557500, 8.953300476074219],
[1184559666, 10.634857177734375],
[1195587500, 12.677258491516113],
[1201858833, 14.94701099395752],
[1217549500, 16.903592109680176],
[1217552375, 15.341092109680176],
[1217554541, 18.08445453643799],
[1217555750, 16.33445453643799],
[1236180458, 19.42455768585205],
[1236182500, 17.45580768585205],
[1236184333, 20.936108589172363],
[1236185500, 18.717358589172363],
[1236186500, 17.239766120910645],
[1236187500, 15.762166023254395],
[1236188583, 14.284565925598145],
[1236189583, 12.806965827941895],
[1236190583, 11.329365730285645],
[1236191541, 7.4039201736450195],
[1338627083, 8.93758487701416],
[1338629291, 10.619111061096191],
[1348636625, 12.567269325256348],
[1361178541, 14.837082862854004],
[1383309833, 16.79378604888916],
[1383312250, 15.23128604888916],
[1383314291, 17.974648475646973],
[1383315458, 16.224648475646973],
[1383317333, 19.31483554840088],
[1383318458, 17.34608554840088],
[1389642333, 20.826355934143066],
[1389644583, 18.607605934143066],
[1389645625, 17.130013465881348],
[1389646583, 15.652413368225098],
[1389647541, 14.174813270568848],
[1389648500, 12.697213172912598],
[1389649416, 11.219613075256348],
[1389650458, 7.294228553771973],
[1485638875, 8.733711242675781],
[1500745250, 10.50951099395752],
[1500747416, 12.4576997756958],
[1509511291, 14.727513313293457],
[1520752041, 16.68424701690674],
[1520754125, 15.121747016906738],
[1529887458, 17.865017890930176],
[1529889000, 16.115017890930176],
[1536118583, 19.20518207550049],
[1536120000, 17.23643207550049],
[1542874458, 20.7167329788208],
[1542876333, 18.4979829788208],
[1542877458, 17.020390510559082],
[1542878458, 15.542790412902832],
[1542879375, 14.065190315246582],
[1542880333, 12.587590217590332],
[1542881250, 11.109990119934082],
[1542882250, 7.184575080871582],
[1634500833, 8.624103546142578],
[1647016583, 10.399903297424316],
[1656918250, 12.348061561584473],
[1667544250, 14.617905616760254],
[1677042708, 16.574639320373535],
[1677044458, 15.012139320373535],
[1677046500, 17.755501747131348],
[1677047708, 16.005501747131348],
[1695595291, 19.09560489654541],
[1695597000, 17.12685489654541],
[1695598708, 20.607155799865723],
[1695599708, 18.388405799865723],
[1695600666, 16.910813331604004],
[1695601583, 15.433213233947754],
[1695602458, 13.955613136291504],
[1695603375, 12.478013038635254],
[1695604291, 11.000412940979004],
[1695605250, 7.074967384338379],
[1791391791, 8.514427185058594],
[1806471458, 10.290196418762207],
[1806473416, 12.238385200500488],
[1815312500, 14.508198738098145],
[1829626958, 16.4649019241333],
[1829629166, 14.9024019241333],
[1829631000, 17.64573383331299],
[1829632208, 15.895733833312988],
[1838273250, 18.985806465148926],
[1838274750, 17.017056465148926],
[1848706625, 20.49729633331299],
[1848708666, 18.27854633331299],
[1848709750, 16.80095386505127],
[1848710666, 15.32335376739502],
[1848711541, 13.84575366973877],
[1848712500, 12.36815357208252],
[1848713416, 10.89055347442627],
[1848714375, 6.9651384353637695],
[1945034541, 8.404621124267578],
[1954097250, 10.180390357971191],
[1963537916, 12.128579139709473],
[1974254208, 14.398423194885254],
[1983813833, 16.355156898498535],
[1983816333, 14.792656898498535],
[1983818375, 17.535988807678223],
[1983819583, 15.785988807678223],
[1992820583, 18.876229286193848],
[1992821875, 16.907479286193848],
[2003450958, 20.387749671936035],
[2003453458, 18.168999671936035],
[2003454708, 16.691407203674316],
[2003455708, 15.213807106018066],
[2003456666, 13.736207008361816],
[2003457583, 12.258606910705566],
[2003458500, 10.781006813049316],
[2003459458, 6.855622291564941],
[2098853583, 8.295028686523438],
[2107703000, 10.070828437805176],
[2117127875, 12.019017219543457],
[2123391375, 14.288861274719238],
[2137372666, 16.245564460754395],
[2137374458, 14.683064460754395],
[2137376375, 17.426396369934082],
[2137377666, 15.676396369934082],
[2144789750, 18.76653003692627],
[2144791208, 16.79778003692627],
[2156970875, 20.278050422668457],
[2156972875, 18.059300422668457],
[2156973958, 16.58170795440674],
[2156974958, 15.104107856750488],
[2156975875, 13.626507759094238],
[2156976791, 12.148907661437988],
[2156977750, 10.671307563781738],
[2156978750, 6.745923042297363],
[2252128250, 8.185497283935547],
[2261111000, 9.96126651763916],
[2270495416, 11.909455299377441],
[2281010250, 14.179299354553223],
[2288727875, 16.136033058166504],
[2288729791, 14.573533058166504],
[2296531666, 17.31686496734619],
[2296533291, 15.566864967346191],
[2296535458, 18.657029151916504],
[2296536625, 16.688279151916504],
[2316518875, 20.16854953765869],
[2316520583, 17.94979953765869],
[2316521625, 16.472207069396973],
[2316522541, 14.994606971740723],
[2316523458, 13.517006874084473],
[2316524375, 12.039406776428223],
[2316525291, 10.561806678771973],
[2316526291, 6.636391639709473],
[2405358041, 8.07586669921875],
[2414186750, 9.851635932922363],
[2423603500, 11.799824714660645],
[2434183083, 14.069668769836426],
[2443616916, 16.026402473449707],
[2443619041, 14.463902473449707],
[2443621208, 17.207234382629395],
[2443622375, 15.457234382629395],
[2451122625, 18.54747486114502],
[2451123916, 16.57872486114502],
[2463408833, 20.058995246887207],
[2463411958, 17.840245246887207],
[2463413041, 16.36265277862549],
[2463414083, 14.885052680969238],
[2463415083, 13.407452583312988],
[2463416083, 11.929852485656738],
[2463417083, 10.452252388000488],
[2463420666, 6.526867866516113],
[2558430208, 7.966442108154297],
[2567834833, 9.742241859436035],
[2581782250, 11.690400123596191],
[2590380458, 13.960183143615723],
[2596683583, 15.916886329650879],
[2596686166, 14.354386329650879],
[2608509958, 17.097771644592285],
[2608511958, 15.347771644592285],
[2608513916, 18.437935829162598],
[2608515083, 16.469185829162598],
[2628441916, 19.949456214904785],
[2628443791, 17.730706214904785],
[2628444875, 16.253113746643066],
[2628445791, 14.775513648986816],
[2628446708, 13.297913551330566],
[2628447625, 11.820313453674316],
[2628448500, 10.342713356018066],
[2628449416, 6.417298316955566],
[2716936291, 7.856758117675781],
[2723704333, 9.63249683380127],
[2729981750, 11.580655097961426],
[2745614583, 13.850468635559082],
[2761433333, 15.807202339172363],
[2761437375, 14.244702339172363],
[2761439458, 16.988064765930176],
[2761440833, 15.238064765930176],
[2761442791, 18.32816791534424],
[2761443958, 16.35941791534424],
[2773086416, 19.83971881866455],
[2773088083, 17.62096881866455],
[2773089208, 16.143376350402832],
[2773090333, 14.665776252746582],
[2773091416, 13.188176155090332],
[2773092583, 11.710576057434082],
[2773093666, 10.232975959777832],
[2773095541, 6.307560920715332],
[2867830583, 7.747097015380859],
[2884560958, 9.522866249084473],
[2884563083, 11.471055030822754],
[2892822375, 13.74086856842041],
[2907884000, 15.698105812072754],
[2907886125, 14.135605812072754],
[2907888000, 16.87893772125244],
[2907889250, 15.128937721252441],
[2915387791, 18.21907138824463],
[2915389375, 16.25032138824463],
[2926667500, 19.73062229156494],
[2926669625, 17.51187229156494],
[2926670625, 16.034279823303223],
[2926671583, 14.556679725646973],
[2926672625, 13.079079627990723],
[2926673625, 11.601479530334473],
[2926674583, 10.123879432678223],
[2926675625, 6.198464393615723],
[3034666125, 7.6379852294921875],
[3034668041, 9.319541931152344],
[3034669750, 11.2677001953125],
[3046989583, 13.631756782531738],
[3060246125, 15.588459968566895],
[3060247916, 14.025959968566895],
[3060249750, 16.769291877746582],
[3060250916, 15.019291877746582],
[3072037500, 18.10942554473877],
[3072039166, 16.14067554473877],
[3086011833, 19.620945930480957],
[3086013958, 17.402195930480957],
[3086015083, 15.924603462219238],
[3086016083, 14.447003364562988],
[3086017166, 12.969403266906738],
[3086018125, 11.491803169250488],
[3086019041, 10.014203071594238],
[3086020000, 6.088788032531738],
[3174625125, 7.528247833251953],
[3183568041, 9.304047584533691],
[3192818916, 11.252236366271973],
[3199073833, 13.522049903869629],
[3219456666, 15.478753089904785],
[3219458958, 13.916253089904785],
[3219460916, 16.659615516662598],
[3219462000, 14.909615516662598],
[3219463708, 17.99971866607666],
[3219464750, 16.03096866607666],
[3232053958, 19.511269569396973],
[3232056041, 17.292519569396973],
[3232057125, 15.814927101135254],
[3232058041, 14.337327003479004],
[3232059000, 12.859726905822754],
[3232059916, 11.382126808166504],
[3232060833, 9.904526710510254],
[3232061791, 5.979111671447754],
[3328167291, 7.418495178222656],
[3337774666, 9.19426441192627],
[3347573000, 11.14245319366455],
[3358798833, 13.412297248840332],
[3375074833, 15.369030952453613],
[3375077125, 13.806530952453613],
[3375079000, 16.549893379211426],
[3375080166, 14.799893379211426],
[3375081916, 17.890103340148926],
[3375083000, 15.921353340148926],
[3382591416, 19.40165424346924],
[3382593625, 17.18290424346924],
[3393229458, 15.70531177520752],
[3393230708, 14.22771167755127],
[3393231500, 12.75011157989502],
[3393232291, 11.27251148223877],
[3393233125, 9.79491138458252],
[3393233916, 5.8694963455200195],
[3483706583, 7.309093475341797],
[3498923166, 9.08486270904541],
[3498925250, 11.033051490783691],
[3507070083, 13.302865028381348],
[3517781541, 15.259598731994629],
[3517784083, 13.697098731994629],
[3534458125, 16.440430641174316],
[3534459625, 14.690430641174316],
[3534461375, 17.78059482574463],
[3534462583, 15.811844825744629],
[3540753750, 19.292115211486816],
[3540760500, 17.073365211486816],
[3540761583, 15.595772743225098],
[3540762500, 14.118172645568848],
[3540763458, 12.640572547912598],
[3540764375, 11.162972450256348],
[3540765291, 9.685372352600098],
[3540766208, 5.759957313537598],
[3636936250, 7.199432373046875],
[3643253833, 8.975232124328613],
[3649555708, 10.92339038848877],
[3665517083, 13.193203926086426],
[3681314625, 15.149937629699707],
[3681316833, 13.587437629699707],
[3681318833, 16.33080005645752],
[3681320000, 14.58080005645752],
[3681321708, 17.670903205871582],
[3681322791, 15.702153205871582],
[3694533125, 19.182454109191895],
[3694535208, 16.963704109191895],
[3694536291, 15.486111640930176],
[3694537250, 14.008511543273926],
[3694538125, 12.530911445617676],
[3694539083, 11.053311347961426],
[3694539958, 9.575711250305176],
[3694540916, 5.650296211242676],
[3790098791, 7.089809417724609],
[3798911541, 8.865555763244629],
[3808257708, 10.81374454498291],
[3815910166, 13.083588600158691],
[3822191208, 15.040291786193848],
[3822193208, 13.477791786193848],
[3828487166, 16.221177101135254],
[3828488500, 14.471177101135254],
[3840441541, 17.561440467834473],
[3840442958, 15.592690467834473],
[3846821041, 19.07296085357666],
[3846822958, 16.85421085357666],
[3846823958, 15.376618385314941],
[3846824875, 13.899018287658691],
[3846825791, 12.421418190002441],
[3846826708, 10.943818092346191],
[3846827583, 9.466217994689941],
[3846828625, 5.540833473205566],
[3943422500, 6.9803619384765625],
[3958368375, 8.756131172180176],
[3958370500, 10.704319953918457],
[3966165833, 12.974133491516113],
[3981619916, 14.93083667755127],
[3981623875, 13.36833667755127],
[3981625791, 16.111668586730957],
[3981626958, 14.361668586730957],
[3989149166, 17.451802253723145],
[3989150791, 15.483052253723145],
[4000965208, 18.963269233703613],
[4000967375, 16.744519233703613],
[4000968458, 15.266926765441895],
[4000969375, 13.789326667785645],
[4000970291, 12.311726570129395],
[4000971208, 10.834126472473145],
[4000972125, 9.356526374816895],
[4000973041, 5.4311418533325195],
[4095860250, 6.870655059814453],
[4105109375, 8.646454811096191],
[4114606291, 10.594643592834473],
[4122073833, 12.864487648010254],
[4134668416, 14.82119083404541],
[4134670708, 13.25869083404541],
[4134672666, 16.002022743225098],
[4134673833, 14.252022743225098],
[4147024291, 17.34212589263916],
[4147025625, 15.37337589263916],
[4153339500, 18.853676795959473],
[4153341291, 16.634926795959473],
[4153342333, 15.157334327697754],
[4153343291, 13.679734230041504],
[4153344250, 12.202134132385254],
[4153345208, 10.724534034729004],
[4153346166, 9.246933937072754],
[4153347125, 5.321518898010254],
[4244786125, 6.760932922363281],
[4257113208, 8.53673267364502],
[4263442208, 10.484890937805176],
[4278888958, 12.754704475402832],
[4294709791, 14.711438179016113],
[4294712000, 13.148938179016113],
[4294713875, 15.892300605773926],
[4294714958, 14.142300605773926],
[4294716666, 17.23240375518799],
[4294717750, 15.263653755187988],
[4306235625, 18.7439546585083],
[4306237708, 16.5252046585083],
[4306238916, 15.047612190246582],
[4306240041, 13.570012092590332],
[4306241166, 12.092411994934082],
[4306242375, 10.614811897277832],
[4306243500, 9.137211799621582],
[4306244625, 5.211796760559082],
[4402735458, 6.651203155517578],
[4411437708, 8.426972389221191],
[4420925333, 10.375161170959473],
[4431466500, 12.645005226135254],
[4438017708, 14.601738929748535],
[4438019375, 13.039238929748535],
[4453015833, 15.782624244689941],
[4453019166, 14.032624244689941],
[4453021166, 17.122788429260254],
[4453022375, 15.154038429260254],
[4459552083, 18.63430881500244],
[4459553666, 16.41555881500244],
[4459554750, 14.937966346740723],
[4459555750, 13.460366249084473],
[4459556708, 11.982766151428223],
[4459557708, 10.505166053771973],
[4459558625, 9.027565956115723],
[4459559625, 5.102150917053223],
[4555238708, 6.541717529296875],
[4563668750, 8.317517280578613],
[4569932541, 10.26567554473877],
[4590304041, 12.535489082336426],
[4590306291, 14.492222785949707],
[4590308416, 12.929722785949707],
[4599289375, 15.67302417755127],
[4599290958, 13.92302417755127],
[4599293041, 17.013188362121582],
[4599294333, 15.044438362121582],
[4611807916, 18.524739265441895],
[4611809708, 16.305989265441895],
[4611810750, 14.828396797180176],
[4611811708, 13.350796699523926],
[4611812708, 11.873196601867676],
[4611813666, 10.395596504211426],
[4611814708, 8.917996406555176],
[4611815791, 4.992581367492676],
[4703001166, 6.431995391845703],
[4717039083, 8.207795143127441],
[4726370083, 10.155983924865723],
[4734432875, 12.425827980041504],
[4740758083, 14.38253116607666],
[4740759958, 12.82003116607666],
[4752320625, 15.563416481018066],
[4752322250, 13.813416481018066],
[4752324041, 16.90358066558838],
[4752325208, 14.934830665588379],
[4765011333, 18.415101051330566],
[4765013416, 16.196351051330566],
[4765014458, 14.718758583068848],
[4765015416, 13.241158485412598],
[4765016375, 11.763558387756348],
[4765017291, 10.285958290100098],
[4765018208, 8.808358192443848],
[4765019166, 4.882973670959473],
[4860951041, 6.322502136230469],
[4869187791, 8.098271369934082],
[4879627916, 10.046460151672363],
[4890477166, 12.316304206848145],
[4897023333, 14.273037910461426],
[4897025583, 12.710537910461426],
[4906051166, 15.453923225402832],
[4906053708, 13.703923225402832],
[4912887500, 16.794087409973145],
[4912889458, 14.825337409973145],
[4919814125, 18.305577278137207],
[4919816208, 16.086827278137207],
[4919817250, 14.609234809875488],
[4919818166, 13.131634712219238],
[4919819125, 11.654034614562988],
[4919820083, 10.176434516906738],
[4919821000, 8.698834419250488],
[4919823833, 4.773419380187988],
[5023320041, 6.213077545166016],
[5023323125, 7.894603729248047],
[5029641916, 9.937005043029785],
[5044781916, 12.206818580627441],
[5050837250, 14.163552284240723],
[5050839333, 12.601052284240723],
[5057138833, 15.34438419342041],
[5057140166, 13.59438419342041],
[5063449041, 16.684517860412598],
[5063450291, 14.715767860412598],
[5069771416, 18.195984840393066],
[5069772708, 15.977234840393066],
[5078160250, 14.499642372131348],
[5078161416, 13.022042274475098],
[5078162333, 11.544442176818848],
[5078163166, 10.066842079162598],
[5078163958, 8.589241981506348],
[5078164916, 4.663826942443848],
[5167815333, 6.1033935546875],
[5177588416, 7.879162788391113],
[5194539583, 9.827351570129395],
[5194541625, 12.097195625305176],
[5202341125, 14.053898811340332],
[5202343416, 12.491398811340332],
[5220412083, 15.23473072052002],
[5220413625, 13.48473072052002],
[5220415500, 16.574894905090332],
[5220416750, 14.606144905090332],
[5226693833, 18.08641529083252],
[5226695916, 15.86766529083252],
[5226696958, 14.3900728225708],
[5226697875, 12.91247272491455],
[5226698833, 11.4348726272583],
[5226699708, 9.95727252960205],
[5226700625, 8.4796724319458],
[5226701625, 4.554257392883301],
[5322822500, 5.993740081787109],
[5331672708, 7.769539833068848],
[5338285250, 9.717728614807129],
[5350854458, 11.987542152404785],
[5359496833, 13.944275856018066],
[5359498666, 12.381775856018066],
[5365814000, 15.125107765197754],
[5365815583, 13.375107765197754],
[5372042791, 16.46524143218994],
[5372044416, 14.496491432189941],
[5380466375, 17.97676181793213],
[5380488791, 15.758011817932129],
[5380490083, 14.28041934967041],
[5380491041, 12.80281925201416],
[5380491958, 11.32521915435791],
[5380492916, 9.84761905670166],
[5380493875, 8.37001895904541],
[5380494875, 4.44460391998291],
[5470324958, 5.884117126464844],
[5478485041, 7.659916877746582],
[5493524500, 9.608075141906738],
[5501088708, 11.87791919708252],
[5507374875, 13.834622383117676],
[5507376791, 12.272122383117676],
[5525673541, 15.015507698059082],
[5525675125, 13.265507698059082],
[5525676916, 16.355671882629395],
[5525678041, 14.386921882629395],
[5532040750, 17.867161750793457],
[5532042333, 15.648411750793457],
[5532043375, 14.170819282531738],
[5532044291, 12.693219184875488],
[5532045208, 11.215619087219238],
[5532046125, 9.738018989562988],
[5532047083, 8.260418891906738],
[5532052375, 4.335034370422363],
[5628032083, 5.774478912353516],
[5636955125, 7.550278663635254],
[5646291708, 9.498467445373535],
[5655363166, 11.768311500549316],
[5661695375, 13.725014686584473],
[5661697125, 12.162514686584473],
[5672175625, 14.905900001525879],
[5672177000, 13.155900001525879],
[5672178875, 16.246033668518066],
[5672180083, 14.277283668518066],
[5684715750, 17.75752353668213],
[5684717625, 15.538773536682129],
[5684718625, 14.06118106842041],
[5684719583, 12.58358097076416],
[5684720500, 11.10598087310791],
[5684721458, 9.62838077545166],
[5684722375, 8.15078067779541],
[5684723333, 4.22536563873291],
[5776186333, 5.664955139160156],
[5788316833, 7.4407548904418945],
[5798866875, 9.38891315460205],
[5809500166, 11.658757209777832],
[5825329666, 13.615490913391113],
[5825332875, 12.052990913391113],
[5825334833, 14.796353340148926],
[5825336000, 13.046353340148926],
[5825337791, 16.13645648956299],
[5825338916, 14.167706489562988],
[5834431250, 17.648655891418457],
[5834432875, 15.429905891418457],
[5843298875, 13.952313423156738],
[5843299958, 12.474713325500488],
[5843300833, 10.997113227844238],
[5843301583, 9.519513130187988],
[5843302416, 8.041913032531738],
[5843303250, 4.116497993469238],
[5932753666, 5.556041717529297],
[5942303625, 7.33181095123291],
[5951736208, 9.279999732971191],
[5968644000, 11.549843788146973],
[5968646000, 13.506577491760254],
[5968647791, 11.944077491760254],
[5983957208, 14.687378883361816],
[5983958916, 12.937378883361816],
[5983961000, 16.02754306793213],
[5983962291, 14.058793067932129],
[5996582875, 17.539063453674316],
[5996584625, 15.320313453674316],
[5996585666, 13.842720985412598],
[5996586625, 12.365120887756348],
[5996587583, 10.887520790100098],
[5996588583, 9.409920692443848],
[5996589541, 7.932320594787598],
[5996590541, 4.006905555725098],
[6082731250, 5.4465179443359375],
[6093244166, 7.222317695617676],
[6099501750, 9.170475959777832],
[6115769500, 11.440289497375488],
[6125370500, 13.39702320098877],
[6125372500, 11.83452320098877],
[6125374500, 14.577885627746582],
[6125375750, 12.827885627746582],
[6137464916, 15.917988777160645],
[6137466583, 13.949238777160645],
[6143755000, 17.429539680480957],
[6143756958, 15.210789680480957],
[6143758041, 13.733197212219238],
[6143759000, 12.255597114562988],
[6143759916, 10.777997016906738],
[6143760833, 9.300396919250488],
[6143761833, 7.822796821594238],
[6143762833, 3.8973817825317383],
[6234613208, 5.336803436279297],
[6243245916, 7.112603187561035],
[6257785875, 9.060761451721191],
[6266030708, 11.330605506896973],
[6272334625, 13.287308692932129],
[6272336875, 11.724808692932129],
[6289988291, 14.468194007873535],
[6289994583, 12.718194007873535],
[6289996458, 15.808358192443848],
[6289997750, 13.839608192443848],
[6302588958, 17.31984806060791],
[6302591208, 15.10109806060791],
[6302592250, 13.623505592346191],
[6302593333, 12.145905494689941],
[6302594291, 10.668305397033691],
[6302595291, 9.190705299377441],
[6302596333, 7.713105201721191],
[6302597333, 3.7877206802368164],
[6390482541, 5.2271881103515625],
[6401091625, 7.002987861633301],
[6412865208, 8.951176643371582],
[6419126333, 11.220990180969238],
[6434483208, 13.177693367004395],
[6434485125, 11.615193367004395],
[6434487250, 14.358555793762207],
[6434488500, 12.608555793762207],
[6446846666, 15.69871997833252],
[6446848666, 13.72996997833252],
[6455603458, 17.210240364074707],
[6455605541, 14.991490364074707],
[6455606666, 13.513897895812988],
[6455607708, 12.036297798156738],
[6455608666, 10.558697700500488],
[6455609625, 9.081097602844238],
[6455610625, 7.603497505187988],
[6455611625, 3.6780824661254883],
[6551340166, 5.117588043212891],
[6566544208, 6.893387794494629],
[6566546333, 8.84157657623291],
[6578061333, 11.111390113830566],
[6602241708, 13.068093299865723],
[6602243916, 11.505593299865723],
[6602245750, 14.248955726623535],
[6602246958, 12.498955726623535],
[6602248666, 15.589142799377441],
[6602249833, 13.620392799377441],
[6608597291, 17.10066318511963],
[6608599250, 14.881913185119629],
[6608600333, 13.40432071685791],
[6608601250, 11.92672061920166],
[6608602208, 10.44912052154541],
[6608603125, 8.97152042388916],
[6608604041, 7.49392032623291],
[6608605041, 3.56850528717041],
[6703743750, 5.0080108642578125],
[6718685916, 6.783780097961426],
[6718688166, 8.731968879699707],
[6726152166, 11.001782417297363],
[6741937000, 12.95848560333252],
[6741946500, 11.39598560333252],
[6741948416, 14.139317512512207],
[6741949708, 12.389317512512207],
[6751076666, 15.479451179504395],
[6751077958, 13.510701179504395],
[6757386000, 16.990971565246582],
[6757387416, 14.772221565246582],
[6763727125, 13.294629096984863],
[6763728416, 11.817028999328613],
[6763729250, 10.339428901672363],
[6763730125, 8.861828804016113],
[6763730958, 7.384228706359863],
[6763731875, 3.4588136672973633],
[6851153291, 4.898349761962891],
[6859499458, 6.674149513244629],
[6874403375, 8.622307777404785],
[6882233666, 10.892151832580566],
[6888538750, 12.848855018615723],
[6888540833, 11.286355018615723],
[6894837291, 14.029740333557129],
[6894838625, 12.279740333557129],
[6906424583, 15.369874000549316],
[6906425833, 13.401124000549316],
[6912790333, 16.881394386291504],
[6912792208, 14.662644386291504],
[6912793375, 13.185051918029785],
[6912794375, 11.707451820373535],
[6912795333, 10.229851722717285],
[6912796250, 8.752251625061035],
[6912797166, 7.274651527404785],
[6912798166, 3.349236488342285],
[7003770375, 4.788688659667969],
[7011609083, 6.564488410949707],
[7027232541, 8.512646675109863],
[7033464583, 10.782490730285645],
[7046696541, 12.739224433898926],
[7046700125, 11.176724433898926],
[7053895583, 13.920056343078613],
[7053897583, 12.170056343078613],
[7053899583, 15.260220527648926],
[7053901000, 13.291470527648926],
[7067522875, 16.771740913391113],
[7067525125, 14.552990913391113],
[7067526250, 13.075398445129395],
[7067527208, 11.597798347473145],
[7067528166, 10.120198249816895],
[7067529125, 8.642598152160645],
[7067530041, 7.1649980545043945],
[7067531041, 3.2395830154418945],
[7168933125, 4.679119110107422],
[7168935083, 6.360675811767578],
[7176566708, 8.403077125549316],
[7191593416, 10.672890663146973],
[7199429333, 12.629624366760254],
[7199431958, 11.067124366760254],
[7206961291, 13.810456275939941],
[7206963041, 12.060456275939941],
[7206965041, 15.150620460510254],
[7206966333, 13.181870460510254],
[7220339958, 16.662171363830566],
[7220342125, 14.443421363830566],
[7220343125, 12.965828895568848],
[7220344083, 11.488228797912598],
[7220345125, 10.010628700256348],
[7220346041, 8.533028602600098],
[7220347000, 7.055428504943848],
[7220348000, 3.1300134658813477],
[7316084791, 4.663830757141113],
[7325138333, 6.3453874588012695],
[7334582041, 8.29357624053955],
[7351638375, 10.563420295715332],
[7351640291, 12.520153999328613],
[7351642375, 10.957653999328613],
[7359897666, 13.7009859085083],
[7359899291, 11.9509859085083],
[7367202916, 15.041119575500488],
[7367204333, 13.072369575500488],
[7373492125, 16.5526704788208],
[7373494375, 14.3339204788208],
[7373495500, 12.856328010559082],
[7373496541, 11.378727912902832],
[7373497541, 9.901127815246582],
[7373498500, 8.423527717590332],
[7373499500, 6.945927619934082],
[7373500541, 3.020512580871582],
[7466136083, 4.459995269775391],
[7476558250, 6.235795021057129],
[7482890041, 8.183953285217285],
[7499235125, 10.453766822814941],
[7508872833, 12.410500526428223],
[7508875125, 10.848000526428223],
[7508877125, 13.591362953186035],
[7508878250, 11.841362953186035],
[7520261125, 14.931496620178223],
[7520262458, 12.962746620178223],
[7528224041, 16.44301700592041],
[7528226333, 14.22426700592041],
[7528227375, 12.746674537658691],
[7528228333, 11.269074440002441],
[7528229250, 9.791474342346191],
[7528230166, 8.313874244689941],
[7528231125, 6.836274147033691],
[7528232125, 2.9108591079711914],
[7618288291, 4.35028076171875],
[7626573083, 6.126080513000488],
[7641592166, 8.074238777160645],
[7649427041, 10.344082832336426],
[7655708291, 12.300786018371582],
[7655710500, 10.738286018371582],
[7667459041, 13.481671333312988],
[7667460708, 11.731671333312988],
[7667462625, 14.8218355178833],
[7667463875, 12.8530855178833],
[7679976541, 16.33335590362549],
[7679978458, 14.114605903625488],
[7679979416, 12.63701343536377],
[7679980375, 11.15941333770752],
[7679981333, 9.68181324005127],
[7679982291, 8.20421314239502],
[7679983208, 6.7266130447387695],
[7679984166, 2.8012285232543945],
[7773985541, 4.240749359130859],
[7784402958, 6.016549110412598],
[7790662125, 7.964707374572754],
[7810971500, 10.23452091217041],
[7810973708, 12.191254615783691],
[7810975291, 10.628754615783691],
[7817748541, 13.372086524963379],
[7817750250, 11.622086524963379],
[7832559291, 14.712220191955566],
[7832561166, 12.743470191955566],
[7832563041, 16.22377109527588],
[7832564083, 14.005021095275879],
[7832565083, 12.52742862701416],
[7832566041, 11.04982852935791],
[7832567000, 9.57222843170166],
[7832570208, 8.09462833404541],
[7832571208, 6.61702823638916],
[7832572333, 2.691582679748535],
[7922994083, 4.13104248046875],
[7932775750, 5.906842231750488],
[7945337000, 7.8550004959106445],
[7953611083, 10.124844551086426],
[7959889083, 12.081547737121582],
[7959891041, 10.519047737121582],
[7966055125, 13.262433052062988],
[7966056500, 11.512433052062988],
[7977993166, 14.602566719055176],
[7977994625, 12.633816719055176],
[7984344791, 16.114087104797363],
[7984346625, 13.895337104797363],
[7984347666, 12.417744636535645],
[7984348583, 10.940144538879395],
[7984349500, 9.462544441223145],
[7984350458, 7.9849443435668945],
[7984351375, 6.5073442459106445],
[7984352333, 2.5819292068481445],
[8075228541, 4.021411895751953],
[8082781916, 5.797211647033691],
[8098281875, 7.745369911193848],
[8108783458, 10.015213966369629],
[8116131166, 11.97194766998291],
[8116133375, 10.40944766998291],
[8124245541, 13.152779579162598],
[8124247208, 11.402779579162598],
[8124249166, 14.49294376373291],
[8124250375, 12.52419376373291],
[8137013625, 16.004494667053223],
[8137015791, 13.785744667053223],
[8137016875, 12.308152198791504],
[8137017791, 10.830552101135254],
[8137018750, 9.352952003479004],
[8137019666, 7.875351905822754],
[8137020583, 6.397751808166504],
[8137021583, 2.472336769104004],
[8228826375, 3.9119415283203125],
[8240680541, 5.687741279602051],
[8251054875, 7.635930061340332],
[8257330708, 9.905743598937988],
[8271154500, 11.862446784973145],
[8271156750, 10.299946784973145],
[8271158666, 13.043309211730957],
[8271159875, 11.293309211730957],
[8282650583, 14.38341236114502],
[8282652833, 12.41466236114502],
[8291123875, 15.894963264465332],
[8291125708, 13.676213264465332],
[8291126750, 12.198620796203613],
[8291127666, 10.721020698547363],
[8291128583, 9.243420600891113],
[8291129541, 7.765820503234863],
[8291130458, 6.288220405578613],
[8291131416, 2.3628053665161133],
[8392950541, 3.8023719787597656],
[8392952708, 5.483928680419922],
[8403638000, 7.52632999420166],
[8409890708, 9.796143531799316],
[8431111916, 11.752846717834473],
[8431113791, 10.190346717834473],
[8431115750, 12.933709144592285],
[8431116958, 11.183709144592285],
[8431118750, 14.273812294006348],
[8431119833, 12.305062294006348],
[8439101375, 15.78536319732666],
[8439102541, 13.56661319732666],
[8449067541, 12.089020729064941],
[8449068750, 10.611420631408691],
[8449069541, 9.133820533752441],
[8449070333, 7.656220436096191],
[8449071166, 6.178620338439941],
[8449072083, 2.2532052993774414],
[8539423791, 3.6928024291992188],
[8548272541, 5.468602180480957],
[8555782416, 7.416790962219238],
[8562089875, 9.686604499816895],
[8583991625, 11.64330768585205],
[8583993625, 10.08080768585205],
[8583995500, 12.824170112609863],
[8583996666, 11.074170112609863],
[8583998375, 14.164273262023926],
[8583999458, 12.195523262023926],
[8597094666, 15.675824165344238],
[8597096583, 13.457074165344238],
[8597097625, 11.97948169708252],
[8597098583, 10.50188159942627],
[8597099541, 9.02428150177002],
[8597100458, 7.5466814041137695],
[8597101416, 6.0690813064575195],
[8597102416, 2.1436662673950195],
[8692409625, 3.5832481384277344],
[8707328333, 5.359017372131348],
[8707330291, 7.307206153869629],
[8717721958, 9.577019691467285],
[8728510041, 11.533753395080566],
[8728512041, 9.971253395080566],
[8742288750, 12.714585304260254],
[8742290625, 10.964585304260254],
[8742292916, 14.054749488830566],
[8742294125, 12.085999488830566],
[8754893791, 15.566239356994629],
[8754895666, 13.347489356994629],
[8754896625, 11.86989688873291],
[8754897541, 10.39229679107666],
[8754898458, 8.91469669342041],
[8754899416, 7.43709659576416],
[8754900333, 5.95949649810791],
[8754901291, 2.034111976623535],
[8839336416, 3.4736557006835938],
[8853248750, 5.249455451965332],
[8862653041, 7.197644233703613],
[8870236500, 9.467488288879395],
[8876539583, 11.42419147491455],
[8876541750, 9.86169147491455],
[8882642625, 12.605076789855957],
[8882643916, 10.855076789855957],
[8894576833, 13.945210456848145],
[8894578125, 11.976460456848145],
[8907180958, 15.456730842590332],
[8907183041, 13.237980842590332],
[8907184083, 11.760388374328613],
[8907185041, 10.282788276672363],
[8907185958, 8.805188179016113],
[8907186875, 7.327588081359863],
[8907187833, 5.849987983703613],
[8907188791, 1.9246034622192383],
[8996641041, 3.3641014099121094],
[9005356000, 5.139870643615723],
[9014702125, 7.088059425354004],
[9025219750, 9.357903480529785],
[9034624208, 11.314637184143066],
[9034626166, 9.752137184143066],
[9034628250, 12.495469093322754],
[9034629458, 10.745469093322754],
[9042829750, 13.835709571838379],
[9042831291, 11.866959571838379],
[9053968125, 15.347229957580566],
[9053969875, 13.128479957580566],
[9053970958, 11.650887489318848],
[9053971916, 10.173287391662598],
[9053972875, 8.695687294006348],
[9053973833, 7.218087196350098],
[9053974791, 5.740487098693848],
[9053975791, 1.8151025772094727],
[9144603041, 3.2558517456054688],
[9157169791, 5.031651496887207],
[9167324958, 6.979809761047363],
[9178110416, 9.249653816223145],
[9194000708, 11.206387519836426],
[9194002458, 9.643887519836426],
[9194004291, 12.387249946594238],
[9194005416, 10.637249946594238],
[9194007125, 13.7273530960083],
[9194008208, 11.7586030960083],
[9201048625, 15.238903999328613],
[9201049833, 13.020153999328613],
[9207340750, 11.542561531066895],
[9207341625, 10.064961433410645],
[9207342375, 8.587361335754395],
[9207343166, 7.1097612380981445],
[9207343958, 5.6321611404418945],
[9207344791, 1.7067461013793945],
[9302433750, 3.146373748779297],
[9311151791, 4.92214298248291],
[9320643791, 6.870331764221191],
[9331272208, 9.140175819396973],
[9338275625, 11.096909523010254],
[9338277291, 9.534409523010254],
[9352660958, 12.27779483795166],
[9352662416, 10.52779483795166],
[9352664291, 13.617959022521973],
[9352665458, 11.649209022521973],
[9360059083, 15.129448890686035],
[9360060875, 12.910698890686035],
[9360061916, 11.433106422424316],
[9360063125, 9.955506324768066],
[9360064083, 8.477906227111816],
[9360065041, 7.000306129455566],
[9360065958, 5.522706031799316],
[9360066916, 1.5973520278930664],
[9455925750, 3.0375823974609375],
[9464776750, 4.813382148742676],
[9472791583, 6.761570930480957],
[9479088208, 9.031384468078613],
[9500772333, 10.98808765411377],
[9500774375, 9.42558765411377],
[9500776333, 12.168950080871582],
[9500777416, 10.418950080871582],
[9500779125, 13.509053230285645],
[9500780208, 11.540303230285645],
[9513728916, 15.020604133605957],
[9513731041, 12.801854133605957],
[9513732125, 11.324261665344238],
[9513733208, 9.846661567687988],
[9513734166, 8.369061470031738],
[9513735083, 6.891461372375488],
[9513736041, 5.413861274719238],
[9513737083, 1.4884462356567383],
[9609060666, 2.9279823303222656],
[9624226000, 4.703782081604004],
[9624228041, 6.651970863342285],
[9634511583, 8.921784400939941],
[9647057208, 10.878487586975098],
[9647059416, 9.315987586975098],
[9647061458, 12.059319496154785],
[9647062708, 10.309319496154785],
[9657363791, 13.399453163146973],
[9657365166, 11.430703163146973],
[9666877791, 14.91097354888916],
[9666879625, 12.69222354888916],
[9666880708, 11.214631080627441],
[9666881666, 9.737030982971191],
[9666882625, 8.259430885314941],
[9666883500, 6.781830787658691],
[9666884416, 5.304230690002441],
[9666885416, 1.3788461685180664],
[9761919625, 2.9126176834106445],
[9770368416, 4.594204902648926],
[9776645458, 6.542363166809082],
[9791089083, 8.812176704406738],
[9806952625, 10.76891040802002],
[9806954875, 9.20641040802002],
[9806956875, 11.949772834777832],
[9806958083, 10.199772834777832],
[9806959875, 13.289875984191895],
[9806961041, 11.321125984191895],
[9816194125, 14.801426887512207],
[9816195458, 12.582676887512207],
[9831393958, 11.105084419250488],
[9831395125, 9.627484321594238],
[9831395958, 8.149884223937988],
[9831396708, 6.672284126281738],
[9831397500, 5.194684028625488],
[9831398333, 1.2692689895629883],
[9916727750, 2.80300235748291],
[9924698208, 4.484589576721191],
[9932873000, 6.432778358459473],
[9939152791, 8.702591896057129],
[9960544500, 10.659295082092285],
[9960546541, 9.096795082092285],
[9960548458, 11.840157508850098],
[9960549666, 10.090157508850098],
[9960551375, 13.18026065826416],
[9960552500, 11.21151065826416],
[9967836458, 14.691811561584473],
[9967837666, 12.473061561584473],
[9974138583, 10.995469093322754],
[9974139666, 9.517868995666504],
[9974140500, 8.040268898010254],
[9974141291, 6.562668800354004],
[9974142041, 5.085068702697754],
[9974142875, 1.159653663635254],
[10068896125, 2.5992507934570312],
[10077671875, 4.3750505447387695],
[10087134041, 6.323239326477051],
[10097715125, 8.593083381652832],
[10107291041, 10.549817085266113],
[10107293375, 8.987317085266113],
[10107295166, 11.7306489944458],
[10107296333, 9.9806489944458],
[10116215208, 13.070889472961426],
[10116216458, 11.102139472961426],
[10126709250, 14.582409858703613],
[10126711791, 12.363659858703613],
[10126712833, 10.886067390441895],
[10126713750, 9.408467292785645],
[10126714750, 7.9308671951293945],
[10126715708, 6.4532670974731445],
[10126716625, 4.9756669998168945],
[10126717625, 1.0502824783325195],
[10228397541, 2.489879608154297],
[10228399541, 4.171436309814453],
[10240194875, 6.213837623596191],
[10247062833, 8.483681678771973],
[10259656541, 10.440384864807129],
[10259658625, 8.877884864807129],
[10272069166, 11.621216773986816],
[10272070916, 9.871216773986816],
[10272072958, 12.961380958557129],
[10272074166, 10.992630958557129],
[10280290916, 14.472870826721191],
[10280293083, 12.254120826721191],
[10280294166, 10.776528358459473],
[10280295125, 9.298928260803223],
[10280296041, 7.821328163146973],
[10280296958, 6.343728065490723],
[10280297875, 4.866127967834473],
[10280298875, 0.9407129287719727],
[10375254875, 2.3801727294921875],
[10383933791, 4.155972480773926],
[10390739291, 6.104161262512207],
[10403268541, 8.373974800109863],
[10413509375, 10.33067798614502],
[10413511125, 8.76817798614502],
[10413513208, 11.511540412902832],
[10413514416, 9.761540412902832],
[10425547875, 12.851696968078613],
[10425549375, 10.882946968078613],
[10431817458, 14.363247871398926],
[10431819250, 12.144497871398926],
[10431820208, 10.666905403137207],
[10431821125, 9.189305305480957],
[10431822041, 7.711705207824707],
[10431822958, 6.234105110168457],
[10431823875, 4.756505012512207],
[10431824833, 0.831089973449707],
[10527514375, 2.270610809326172],
[10542503250, 4.046380043029785],
[10542505083, 5.994568824768066],
[10551167791, 8.264382362365723],
[10565694458, 10.221085548400879],
[10565696666, 8.658585548400879],
[10565698583, 11.401917457580566],
[10565699875, 9.651917457580566],
[10576167333, 12.742051124572754],
[10576169000, 10.773301124572754],
[10585158208, 14.253571510314941],
[10585160333, 12.034821510314941],
[10585161375, 10.557229042053223],
[10585162291, 9.079628944396973],
[10585163208, 7.602028846740723],
[10585164083, 6.124428749084473],
[10585165000, 4.646828651428223],
[10585165916, 0.7214136123657227],
[10679902333, 2.1608657836914062],
[10694787208, 3.9366350173950195],
[10694789208, 5.884823799133301],
[10707466291, 8.154637336730957],
[10718130458, 10.111371040344238],
[10718132125, 8.548871040344238],
[10718133958, 11.292202949523926],
[10718135125, 9.542202949523926],
[10736509375, 12.632336616516113],
[10736511500, 10.663586616516113],
[10736513500, 14.143887519836426],
[10736514541, 11.925137519836426],
[10736515666, 10.447545051574707],
[10736516666, 8.969944953918457],
[10736517708, 7.492344856262207],
[10736518666, 6.014744758605957],
[10736519625, 4.537144660949707],
[10736520625, 0.611699104309082],
[10840282375, 2.051219940185547],
[10840284458, 3.732776641845703],
[10849612583, 5.775177955627441],
[10860022125, 8.045022010803223],
[10872596250, 10.001725196838379],
[10872598458, 8.439225196838379],
[10872600333, 11.182557106018066],
[10872601541, 9.432557106018066],
[10882916125, 12.522690773010254],
[10882917333, 10.553940773010254],
[10905076250, 14.034211158752441],
[10905078166, 11.815461158752441],
[10905079208, 10.337868690490723],
[10905080208, 8.860268592834473],
[10905081250, 7.382668495178223],
[10905082166, 5.905068397521973],
[10905083125, 4.427468299865723],
[10905084125, 0.5020837783813477],
[10982966416, 1.9416961669921875],
[10993338083, 3.717495918273926],
[11003769375, 5.665684700012207],
[11016296041, 7.935528755187988],
[11026691291, 9.892231941223145],
[11026693333, 8.329731941223145],
[11026695250, 11.073094367980957],
[11026696416, 9.323094367980957],
[11037193791, 12.413228034973145],
[11037195125, 10.444478034973145],
[11046151666, 13.924748420715332],
[11046154625, 11.705998420715332],
[11046155666, 10.228405952453613],
[11046156583, 8.750805854797363],
[11046157500, 7.273205757141113],
[11046158416, 5.795605659484863],
[11046159375, 4.318005561828613],
[11046160375, 0.3925905227661133],
[11142101958, 1.8320808410644531],
[11157123166, 3.6078805923461914],
[11157125416, 5.556069374084473],
[11166258041, 7.825882911682129],
[11176659583, 9.78261661529541],
[11176662166, 8.22011661529541],
[11192579791, 10.963448524475098],
[11192581791, 9.213448524475098],
[11192583791, 12.30361270904541],
[11192585083, 10.33486270904541],
[11199880333, 13.815102577209473],
[11199882166, 11.596352577209473],
[11199883250, 10.118760108947754],
[11199884208, 8.641160011291504],
[11199885125, 7.163559913635254],
[11199886041, 5.685959815979004],
[11199886958, 4.208359718322754],
[11199887916, 0.2829751968383789],
[11290280500, 1.7225265502929688],
[11301166458, 3.498326301574707],
[11307445291, 5.446484565734863],
[11323843791, 7.7162981033325195],
[11339677500, 9.6730318069458],
[11339679375, 8.1105318069458],
[11339681416, 10.853894233703613],
[11339682666, 9.103894233703613],
[11339684583, 12.193997383117676],
[11339685750, 10.225247383117676],
[11351282291, 13.705548286437988],
[11351284291, 11.486798286437988],
[11351285416, 10.00920581817627],
[11351286500, 8.53160572052002],
[11351287708, 7.0540056228637695],
[11351288791, 5.5764055252075195],
[11351289875, 4.0988054275512695],
[11351291125, 0.17339038848876953],
[11459265375, 1.6129112243652344],
[11459271833, 3.2944679260253906],
[11479420041, 5.336899757385254],
[11497722458, 7.60671329498291],
[11514445583, 9.563446998596191],
[11514448333, 8.000946998596191],
[11525430250, 10.744309425354004],
[11525432083, 8.994309425354004],
[11531662291, 12.084473609924316],
[11531664625, 10.115723609924316],
[11545973750, 13.595993995666504],
[11545976125, 11.377243995666504],
[11545977125, 9.899651527404785],
[11545978041, 8.422051429748535],
[11545978958, 6.944451332092285],
[11545979875, 5.466851234436035],
[11545980833, 3.989251136779785],
[11545981833, 0.06386661529541016],
[11637145541, 1.5034637451171875],
[11646080291, 3.2986268997192383],
[11655690333, 5.2468156814575195],
[11666421916, 7.516659736633301],
[11676161250, 9.474095344543457],
[11676163416, 7.911595344543457],
[11676165416, 10.654927253723145],
[11676166750, 8.904927253723145],
[11684479916, 11.99516773223877],
[11684481708, 10.02641773223877],
[11694955791, 13.506688117980957],
[11694958083, 11.287938117980957],
[11694959291, 9.810345649719238],
[11694960416, 8.332745552062988],
[11694961500, 6.855145454406738],
[11694962625, 5.377545356750488],
[11694963750, 3.8999452590942383],
[11694964916, -0.02543926239013672],
[11793064583, 1.4964265823364258],
[11801811458, 3.2986574172973633],
[11809493291, 5.2468461990356445],
[11815791500, 7.516659736633301],
[11837618083, 9.473362922668457],
[11837620291, 7.910862922668457],
[11837622083, 10.65422534942627],
[11837623208, 8.90422534942627],
[11837624875, 11.994328498840332],
[11837625916, 10.025578498840332],
[11849392958, 13.505879402160645],
[11849395000, 11.287129402160645],
[11849396166, 9.809536933898926],
[11849397291, 8.331936836242676],
[11849398333, 6.854336738586426],
[11849399375, 5.376736640930176],
[11849400458, 3.899136543273926],
[11849401500, -0.02627849578857422],
[11945996375, 1.4964265823364258],
[11954879916, 3.2986574172973633],
[11964169833, 5.2468461990356445],
[11971820291, 7.516690254211426],
[11984360375, 9.473393440246582],
[11984362416, 7.910893440246582],
[11984364666, 10.65422534942627],
[11984365875, 8.90422534942627],
[11993308500, 11.994359016418457],
[11993309791, 10.025609016418457],
[11999589625, 13.505879402160645],
[11999590958, 11.287129402160645],
[12005909375, 9.809536933898926],
[12005910416, 8.331936836242676],
[12005911166, 6.854336738586426],
[12005911916, 5.376736640930176],
[12005912708, 3.899136543273926],
[12005913541, -0.02627849578857422],
[12094932958, 1.4964570999145508],
[12107397875, 3.2986268997192383],
[12123030833, 5.2468156814575195],
[12123032791, 7.516659736633301],
[12142997375, 9.473362922668457],
[12142999750, 7.910862922668457],
[12143001625, 10.65422534942627],
[12143002833, 8.90422534942627],
[12143004583, 11.994328498840332],
[12143005666, 10.025578498840332],
[12156182250, 13.505879402160645],
[12156184208, 11.287129402160645],
[12156185375, 9.809536933898926],
[12156186333, 8.331936836242676],
[12156187250, 6.854336738586426],
[12156188166, 5.376736640930176],
[12156189083, 3.899136543273926],
[12156190125, -0.02627849578857422],
[12255301583, 1.617100715637207],
[12263787541, 3.2986574172973633],
[12273490541, 5.247906684875488],
[12284254541, 7.517926216125488],
[12294010708, 9.47465991973877],
[12294013166, 7.9121599197387695],
[12294015166, 10.655491828918457],
[12294016375, 8.905491828918457],
[12306510041, 11.995732307434082],
[12306512166, 10.026982307434082],
[12312797208, 13.507283210754395],
[12312800041, 11.288533210754395],
[12312801083, 9.810940742492676],
[12312802000, 8.333340644836426],
[12312802916, 6.855740547180176],
[12312803833, 5.378140449523926],
[12312804750, 3.900540351867676],
[12312805750, -0.02487468719482422],
[12412272458, 1.4963960647583008],
[12420502333, 3.2986574172973633],
[12430569500, 5.2468156814575195],
[12441200041, 7.516659736633301],
[12456973208, 9.473393440246582],
[12456975541, 7.910893440246582],
[12456977458, 10.654255867004395],
[12456978666, 8.904255867004395],
[12456980458, 11.994412422180176],
[12456981583, 10.025662422180176],
[12468596125, 13.505963325500488],
[12468597708, 11.287213325500488],
[12468598875, 9.80962085723877],
[12468600000, 8.33202075958252],
[12468601041, 6.8544206619262695],
[12468602125, 5.3768205642700195],
[12468603416, 3.8992204666137695],
[12468604541, -0.02619457244873047],
[12565110458, 1.4964265823364258],
[12573889833, 3.2986574172973633],
[12583136625, 5.2468461990356445],
[12589988083, 7.516690254211426],
[12602705666, 9.473393440246582],
[12602707625, 7.910893440246582],
[12602709541, 10.65422534942627],
[12602710791, 8.90422534942627],
[12615077666, 11.994389533996582],
[12615079041, 10.025639533996582],
[12622640541, 13.50590991973877],
[12622642583, 11.28715991973877],
[12622643666, 9.80956745147705],
[12622644625, 8.3319673538208],
[12622645541, 6.854367256164551],
[12622646458, 5.376767158508301],
[12622647375, 3.899167060852051],
[12622648375, -0.02624797821044922],
[12712905333, 1.4964799880981445],
[12726887083, 3.2986268997192383],
[12736326000, 5.2468156814575195],
[12742815458, 7.516659736633301],
[12755360666, 9.473362922668457],
[12755362750, 7.910862922668457],
[12761633791, 10.654194831848145],
[12761635208, 8.904194831848145],
[12767878583, 11.994359016418457],
[12767879833, 10.025609016418457],
[12788602125, 13.505879402160645],
[12788604041, 11.287129402160645],
[12788605000, 9.809536933898926],
[12788605916, 8.331936836242676],
[12788606833, 6.854336738586426],
[12788607750, 5.376736640930176],
[12788608708, 3.899136543273926],
[12788609708, -0.02624797821044922],
[12866386083, 1.4964265823364258],
[12877738166, 3.2986574172973633],
[12884012291, 5.2468156814575195],
[12899734875, 7.516629219055176],
[12915539666, 9.473362922668457],
[12915541833, 7.910862922668457],
[12915543916, 10.65422534942627],
[12915545166, 8.90422534942627],
[12915546958, 11.994328498840332],
[12915548083, 10.025578498840332],
[12924181166, 13.505879402160645],
[12924182375, 11.287129402160645],
[12939781208, 9.809536933898926],
[12939782416, 8.331936836242676],
[12939783375, 6.854336738586426],
[12939784208, 5.376736640930176],
[12939785000, 3.899136543273926],
[12939785833, -0.02627849578857422],
],
n_avg_mb: 13.246117768464265,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 5.449897122642313,
n_cpu_percent_python: 28.1417525543909,
n_gpu_percent: 0,
n_growth_mb: 13.413040161132812,
n_malloc_mb: 1514.1284255981445,
n_mallocs: 81,
n_peak_mb: 13.413040161132812,
n_python_fraction: 0.18754431950170797,
n_sys_percent: 0.9929949368449258,
n_usage_fraction: 0.6277590022940307,
},
{
line: "def doit2(x):\n",
lineno: 19,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.0,
n_cpu_percent_python: 0.0,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 81,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.0,
n_usage_fraction: 0.0,
},
{
line: " while i < 100000:\n",
lineno: 24,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.20224910523405576,
n_cpu_percent_python: 0.40196582576581585,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.015004028803713564,
n_usage_fraction: 0.0,
},
{
line: " z = z * z\n",
lineno: 29,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.6919713187718092,
n_cpu_percent_python: 4.130177787133885,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.14782644020114388,
n_usage_fraction: 0.0,
},
{
line: " z = x * x\n",
lineno: 30,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.3736870036889326,
n_cpu_percent_python: 2.0118100119639823,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.05683015570030471,
n_usage_fraction: 0.0,
},
{
line: " z = z * z\n",
lineno: 31,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.5930309068593924,
n_cpu_percent_python: 2.332668210842781,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.08824647405051865,
n_usage_fraction: 0.0,
},
{
line: " z = z * z\n",
lineno: 32,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.41799293599671067,
n_cpu_percent_python: 2.214194405491557,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.061242458976033795,
n_usage_fraction: 0.0,
},
{
line: " i += 1\n",
lineno: 33,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.2877928269391876,
n_cpu_percent_python: 1.87461014151035,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.055151888031057916,
n_usage_fraction: 0.0,
},
{
line: " y = np.random.randint(1, 100, size=5000000)[4999999]\n",
lineno: 46,
memory_samples: [
[376561916, 46.03816890716553],
[419515541, 7.945382118225098],
],
n_avg_mb: 38.45994186401367,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.0,
n_cpu_percent_python: 0.0,
n_gpu_percent: 0,
n_growth_mb: 38.45994186401367,
n_malloc_mb: 38.45994186401367,
n_mallocs: 1,
n_peak_mb: 38.45994186401367,
n_python_fraction: 0.0003818475199016959,
n_sys_percent: 0.0,
n_usage_fraction: 0.015945526366630304,
},
{
line: " x = 1.01\n",
lineno: 47,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.0,
n_cpu_percent_python: 0.0,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 1,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.0,
n_usage_fraction: 0.0,
},
{
line: " print(i)\n",
lineno: 49,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 2.1150691718295715,
n_cpu_percent_python: 0.06865792500233953,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.0,
n_usage_fraction: 0.0,
},
{
line: 'print("TESTME")\n',
lineno: 58,
memory_samples: [],
n_avg_mb: 0.0,
n_copy_mb_s: 0.0,
n_cpu_percent_c: 0.56700460783932,
n_cpu_percent_python: 0.06865792500233953,
n_gpu_percent: 0,
n_growth_mb: 0.0,
n_malloc_mb: 0.0,
n_mallocs: 0,
n_peak_mb: 0.0,
n_python_fraction: 0,
n_sys_percent: 0.0,
n_usage_fraction: 0.0,
},
],
percent_cpu_time: 99.91458267550459,
},
},
gpu: false,
growth_rate: 0.003907325283865515,
max_footprint_mb: 46.22665500640869,
samples: [
[255111708, 1.4791831970214844],
[255112958, 1.5734262466430664],
[292870041, 3.0510921478271484],
[319227875, 4.622952461242676],
[334173583, 6.100545883178711],
[364468750, 7.5782270431518555],
[376535708, 7.6724700927734375],
[376537750, 46.13241195678711],
[376539291, 46.22665500640869],
[419496125, 7.945382118225098],
[419498000, 8.03962516784668],
[428523041, 9.570051193237305],
[428523916, 9.664294242858887],
[445050833, 11.226824760437012],
[467909583, 9.749224662780762],
[467911958, 7.894305229187012],
[467914208, 7.988548278808594],
[467916458, 9.518760681152344],
[479993166, 11.200347900390625],
[501593000, 13.148506164550781],
[534540791, 15.418411254882812],
[555492541, 13.940811157226562],
[555493375, 12.463211059570312],
[555493875, 10.985610961914062],
[555494375, 9.508010864257812],
[555495000, 7.8679351806640625],
[555495583, 7.9621782302856445],
[555496041, 9.48503589630127],
[564997333, 11.16716480255127],
[575255208, 13.11535358428955],
[586837916, 15.385197639465332],
[597083708, 17.341931343078613],
[597084708, 15.779431343078613],
[597085458, 18.5227632522583],
[597086125, 16.7727632522583],
[605392791, 19.86289691925049],
[605393875, 17.89414691925049],
[618500208, 21.3744478225708],
[618501833, 19.1556978225708],
[618502458, 17.678105354309082],
[618503041, 16.200505256652832],
[618504166, 14.722905158996582],
[618504666, 13.245305061340332],
[618505208, 11.767704963684082],
[618505875, 7.842289924621582],
[629845625, 7.936532974243164],
[651142333, 9.467050552368164],
[651143041, 9.561293601989746],
[661857958, 11.117934226989746],
[668143500, 9.640334129333496],
[668144250, 7.785323143005371],
[668144916, 7.879566192626953],
[668145458, 9.409778594970703],
[682669583, 11.09133529663086],
[693279916, 13.03952407836914],
[705305375, 15.309368133544922],
[716897250, 13.831768035888672],
[716897916, 12.354167938232422],
[716898458, 10.876567840576172],
[716898875, 9.398967742919922],
[716899375, 7.758892059326172],
[716899916, 7.853135108947754],
[716900458, 9.375992774963379],
[725629333, 11.057496070861816],
[734912916, 13.005684852600098],
[751879625, 15.27541446685791],
[751880208, 17.23214817047119],
[751881708, 15.669648170471191],
[761084833, 18.412949562072754],
[761085500, 16.662949562072754],
[767325000, 19.753045082092285],
[767325541, 17.784295082092285],
[775891666, 21.264504432678223],
[775893000, 19.045754432678223],
[775893583, 17.568161964416504],
[775894041, 16.090561866760254],
[775894541, 14.612961769104004],
[775898708, 13.135361671447754],
[775899166, 11.657761573791504],
[775899875, 7.732377052307129],
[775900416, 7.826620101928711],
[810184791, 9.357297897338867],
[810185416, 9.45154094696045],
[819088458, 11.008158683776855],
[827216458, 9.530558586120605],
[827217208, 7.6755781173706055],
[827218000, 7.7698211669921875],
[827218458, 9.300033569335938],
[834450750, 10.982154846191406],
[846987041, 12.930343627929688],
[859531333, 15.200157165527344],
[870435083, 13.722557067871094],
[870435875, 12.244956970214844],
[870437583, 10.767356872558594],
[870438125, 9.289756774902344],
[870438625, 7.649681091308594],
[870439333, 7.743924140930176],
[870439791, 9.2667818069458],
[880995750, 10.948307991027832],
[890436375, 12.896496772766113],
[907383666, 15.166340827941895],
[907384250, 17.123074531555176],
[907385166, 15.560574531555176],
[916862583, 18.30387592315674],
[916863250, 16.55387592315674],
[916863750, 19.643986701965332],
[916864250, 17.675236701965332],
[929525166, 21.15550708770752],
[929526291, 18.93675708770752],
[929530458, 17.4591646194458],
[929530875, 15.98156452178955],
[929531333, 14.5039644241333],
[929531750, 13.02636432647705],
[929532166, 11.5487642288208],
[929532833, 7.623379707336426],
[929533333, 7.717622756958008],
[964094250, 9.248224258422852],
[964094833, 9.342467308044434],
[973082125, 10.89908504486084],
[981249500, 9.42148494720459],
[981250166, 7.56650447845459],
[981250666, 7.660747528076172],
[981251125, 9.190959930419922],
[988422541, 10.872547149658203],
[998613000, 12.820735931396484],
[1013966083, 15.09054946899414],
[1025426416, 13.61294937133789],
[1025427041, 12.13534927368164],
[1025427541, 10.65774917602539],
[1025428333, 9.18014907836914],
[1025428791, 7.540073394775391],
[1025429333, 7.634316444396973],
[1025429750, 9.157174110412598],
[1031962916, 10.838730812072754],
[1043294666, 12.786919593811035],
[1049547916, 15.056733131408691],
[1064018666, 17.013436317443848],
[1064019583, 15.450936317443848],
[1064020083, 18.19429874420166],
[1064020583, 16.44429874420166],
[1076168208, 19.534432411193848],
[1076169166, 17.565682411193848],
[1083915041, 21.045952796936035],
[1083916000, 18.827202796936035],
[1083916458, 17.349610328674316],
[1083916875, 15.872010231018066],
[1083917291, 14.394410133361816],
[1083917708, 12.916810035705566],
[1083918125, 11.439209938049316],
[1083919291, 7.513794898986816],
[1083919791, 7.608037948608398],
[1113666458, 9.138654708862305],
[1113667125, 9.232897758483887],
[1126228375, 10.789484977722168],
[1140844916, 9.311884880065918],
[1140845666, 7.456873893737793],
[1140846250, 7.551116943359375],
[1140846708, 9.081329345703125],
[1140847166, 10.762916564941406],
[1154924791, 12.711074829101562],
[1167683458, 14.980918884277344],
[1184540791, 13.503318786621094],
[1184541541, 12.025718688964844],
[1184542083, 10.548118591308594],
[1184542583, 9.070518493652344],
[1184543125, 7.430442810058594],
[1184543750, 7.524685859680176],
[1184544208, 9.0475435256958],
[1184544750, 10.729100227355957],
[1195584708, 12.677258491516113],
[1201856541, 14.94701099395752],
[1217542958, 16.903592109680176],
[1217543791, 15.341092109680176],
[1217545666, 18.08445453643799],
[1217546166, 16.33445453643799],
[1236168958, 19.42455768585205],
[1236170000, 17.45580768585205],
[1236170541, 20.936108589172363],
[1236171083, 18.717358589172363],
[1236171583, 17.239766120910645],
[1236172083, 15.762166023254395],
[1236172666, 14.284565925598145],
[1236173125, 12.806965827941895],
[1236173583, 11.329365730285645],
[1236174458, 7.4039201736450195],
[1236174875, 7.498163223266602],
[1267811916, 9.028757095336914],
[1267812541, 9.123000144958496],
[1278334625, 10.679617881774902],
[1294282916, 9.202017784118652],
[1294283666, 7.347006797790527],
[1294284208, 7.441249847412109],
[1294284666, 8.97146224975586],
[1294285083, 10.65304946899414],
[1315187041, 12.601146697998047],
[1315187625, 14.870990753173828],
[1326173958, 13.393390655517578],
[1326174958, 11.915790557861328],
[1326175583, 10.438190460205078],
[1326176083, 8.960590362548828],
[1326176500, 7.320484161376953],
[1326177416, 7.414727210998535],
[1338623000, 8.93758487701416],
[1338623583, 10.619111061096191],
[1348634125, 12.567269325256348],
[1361175166, 14.837082862854004],
[1383303375, 16.79378604888916],
[1383304250, 15.23128604888916],
[1383304750, 17.974648475646973],
[1383305291, 16.224648475646973],
[1383305833, 19.31483554840088],
[1383306375, 17.34608554840088],
[1389632416, 20.826355934143066],
[1389633458, 18.607605934143066],
[1389634000, 17.130013465881348],
[1389634458, 15.652413368225098],
[1389634875, 14.174813270568848],
[1389635333, 12.697213172912598],
[1389635833, 11.219613075256348],
[1389636583, 7.294228553771973],
[1389637041, 7.388471603393555],
[1424223625, 8.919004440307617],
[1424224250, 9.0132474899292],
[1433310041, 10.569865226745605],
[1441478583, 9.092265129089355],
[1441479416, 7.2372541427612305],
[1441479958, 7.3314971923828125],
[1441480333, 8.861709594726562],
[1451789791, 10.543296813964844],
[1462318083, 12.491485595703125],
[1474262916, 14.761329650878906],
[1485623958, 13.283729553222656],
[1485624666, 11.806129455566406],
[1485625875, 10.328529357910156],
[1485626375, 8.850929260253906],
[1485626958, 7.210853576660156],
[1485627541, 7.305096626281738],
[1485628000, 8.827954292297363],
[1500741375, 10.50951099395752],
[1500741958, 12.4576997756958],
[1509507666, 14.727513313293457],
[1520748625, 16.68424701690674],
[1520749416, 15.121747016906738],
[1529883750, 17.865017890930176],
[1529884583, 16.115017890930176],
[1536115583, 19.20518207550049],
[1536116208, 17.23643207550049],
[1542864250, 20.7167329788208],
[1542865583, 18.4979829788208],
[1542866125, 17.020390510559082],
[1542866541, 15.542790412902832],
[1542867000, 14.065190315246582],
[1542867458, 12.587590217590332],
[1542867875, 11.109990119934082],
[1542868625, 7.184575080871582],
[1542869125, 7.278818130493164],
[1576162250, 8.809465408325195],
[1576162833, 8.903708457946777],
[1586513833, 10.460295677185059],
[1594674500, 8.982695579528809],
[1594675208, 7.127715110778809],
[1594675750, 7.221958160400391],
[1594676166, 8.75217056274414],
[1604961083, 10.433757781982422],
[1615429833, 12.381877899169922],
[1621692833, 14.651721954345703],
[1634485791, 13.174121856689453],
[1634486625, 11.696521759033203],
[1634487333, 10.218921661376953],
[1634488041, 8.741321563720703],
[1634488625, 7.101245880126953],
[1634489250, 7.195488929748535],
[1634489750, 8.71834659576416],
[1647013666, 10.399903297424316],
[1656915416, 12.348061561584473],
[1667541541, 14.617905616760254],
[1677038291, 16.574639320373535],
[1677039125, 15.012139320373535],
[1677039583, 17.755501747131348],
[1677040166, 16.005501747131348],
[1695585750, 19.09560489654541],
[1695586708, 17.12685489654541],
[1695587208, 20.607155799865723],
[1695587708, 18.388405799865723],
[1695588125, 16.910813331604004],
[1695588583, 15.433213233947754],
[1695589041, 13.955613136291504],
[1695589458, 12.478013038635254],
[1695589875, 11.000412940979004],
[1695590458, 7.074967384338379],
[1695590916, 7.169210433959961],
[1730109875, 8.699773788452148],
[1730110458, 8.79401683807373],
[1739209333, 10.350634574890137],
[1747339916, 8.873034477233887],
[1747340625, 7.018054008483887],
[1747341208, 7.112297058105469],
[1747341750, 8.642509460449219],
[1755368333, 10.324043273925781],
[1767911458, 12.272201538085938],
[1780034666, 14.542015075683594],
[1791376541, 13.064414978027344],
[1791377250, 11.586814880371094],
[1791377750, 10.109214782714844],
[1791378208, 8.631614685058594],
[1791378750, 6.991539001464844],
[1791379250, 7.085782051086426],
[1791379708, 8.608670234680176],
[1806466750, 10.290196418762207],
[1806468583, 12.238385200500488],
[1815309083, 14.508198738098145],
[1829621916, 16.4649019241333],
[1829622791, 14.9024019241333],
[1829623333, 17.64573383331299],
[1829623916, 15.895733833312988],
[1838269916, 18.985806465148926],
[1838270500, 17.017056465148926],
[1848696583, 20.49729633331299],
[1848697875, 18.27854633331299],
[1848698375, 16.80095386505127],
[1848698833, 15.32335376739502],
[1848699250, 13.84575366973877],
[1848699666, 12.36815357208252],
[1848700083, 10.89055347442627],
[1848700833, 6.9651384353637695],
[1848701291, 7.059381484985352],
[1883132041, 8.589975357055664],
[1883132708, 8.684218406677246],
[1898338791, 10.240836143493652],
[1898340125, 8.763236045837402],
[1898340750, 6.908255577087402],
[1898341208, 7.002498626708984],
[1898341625, 8.53268051147461],
[1906986166, 10.21426773071289],
[1921332083, 12.162425994873047],
[1930356541, 14.432270050048828],
[1945018250, 12.954669952392578],
[1945018958, 11.477069854736328],
[1945019458, 9.999469757080078],
[1945019875, 8.521869659423828],
[1945020416, 6.881763458251953],
[1945021041, 6.976006507873535],
[1945021458, 8.49886417388916],
[1954093791, 10.180390357971191],
[1963534833, 12.128579139709473],
[1974251458, 14.398423194885254],
[1983809208, 16.355156898498535],
[1983810041, 14.792656898498535],
[1983810541, 17.535988807678223],
[1983811041, 15.785988807678223],
[1992817333, 18.876229286193848],
[1992817958, 16.907479286193848],
[2003438666, 20.387749671936035],
[2003442416, 18.168999671936035],
[2003442958, 16.691407203674316],
[2003443416, 15.213807106018066],
[2003443875, 13.736207008361816],
[2003444333, 12.258606910705566],
[2003444791, 10.781006813049316],
[2003445375, 6.855622291564941],
[2003445916, 6.949865341186523],
[2042892708, 8.480405807495117],
[2042893333, 8.5746488571167],
[2042893791, 10.131266593933105],
[2053155250, 8.653666496276855],
[2053156083, 6.7986555099487305],
[2053156625, 6.8928985595703125],
[2053157083, 8.423110961914062],
[2064732625, 10.104667663574219],
[2074920541, 12.0528564453125],
[2081198125, 14.322647094726562],
[2098838916, 12.845046997070312],
[2098839625, 11.367446899414062],
[2098840250, 9.889846801757812],
[2098840750, 8.412246704101562],
[2098841250, 6.7721710205078125],
[2098841791, 6.8664140701293945],
[2098842250, 8.38927173614502],
[2107699791, 10.070828437805176],
[2117125208, 12.019017219543457],
[2123386291, 14.288861274719238],
[2137367458, 16.245564460754395],
[2137368291, 14.683064460754395],
[2137368833, 17.426396369934082],
[2137369375, 15.676396369934082],
[2144786625, 18.76653003692627],
[2144787208, 16.79778003692627],
[2156960416, 20.278050422668457],
[2156961708, 18.059300422668457],
[2156962333, 16.58170795440674],
[2156962833, 15.104107856750488],
[2156963250, 13.626507759094238],
[2156963708, 12.148907661437988],
[2156964166, 10.671307563781738],
[2156964916, 6.745923042297363],
[2156965500, 6.840166091918945],
[2196875708, 8.370790481567383],
[2196876291, 8.465033531188965],
[2196876708, 10.021651268005371],
[2204024500, 8.544051170349121],
[2204025208, 6.689040184020996],
[2204026625, 6.783283233642578],
[2204027125, 8.313495635986328],
[2215333041, 9.99508285522461],
[2226158750, 11.94327163696289],
[2238712791, 14.213115692138672],
[2252113916, 12.735515594482422],
[2252114541, 11.257915496826172],
[2252115041, 9.780315399169922],
[2252115541, 8.302715301513672],
[2252116041, 6.662609100341797],
[2252116541, 6.756852149963379],
[2252117000, 8.279740333557129],
[2261108125, 9.96126651763916],
[2270492166, 11.909455299377441],
[2281007625, 14.179299354553223],
[2288724250, 16.136033058166504],
[2288725125, 14.573533058166504],
[2296526291, 17.31686496734619],
[2296527250, 15.566864967346191],
[2296527791, 18.657029151916504],
[2296528416, 16.688279151916504],
[2316508916, 20.16854953765869],
[2316510000, 17.94979953765869],
[2316510500, 16.472207069396973],
[2316510958, 14.994606971740723],
[2316511375, 13.517006874084473],
[2316511875, 12.039406776428223],
[2316512375, 10.561806678771973],
[2316513041, 6.636391639709473],
[2316513500, 6.730634689331055],
[2338297750, 8.261251449584961],
[2338298333, 8.355494499206543],
[2352914000, 9.912020683288574],
[2359494083, 8.434420585632324],
[2359494750, 6.579440116882324],
[2359495291, 6.673683166503906],
[2359495750, 8.203895568847656],
[2370126416, 9.885482788085938],
[2376408666, 11.833641052246094],
[2392830208, 14.103485107421875],
[2405343958, 12.625885009765625],
[2405344666, 11.148284912109375],
[2405345166, 9.670684814453125],
[2405345666, 8.193084716796875],
[2405346125, 6.552978515625],
[2405346666, 6.647221565246582],
[2405347125, 8.170109748840332],
[2414183791, 9.851635932922363],
[2423600625, 11.799824714660645],
[2434180166, 14.069668769836426],
[2443612208, 16.026402473449707],
[2443613041, 14.463902473449707],
[2443613625, 17.207234382629395],
[2443614125, 15.457234382629395],
[2451117208, 18.54747486114502],
[2451117875, 16.57872486114502],
[2463395416, 20.058995246887207],
[2463396666, 17.840245246887207],
[2463397208, 16.36265277862549],
[2463397666, 14.885052680969238],
[2463398166, 13.407452583312988],
[2463398666, 11.929852485656738],
[2463399125, 10.452252388000488],
[2463399916, 6.526867866516113],
[2463400416, 6.621110916137695],
[2501084375, 8.151735305786133],
[2501085166, 8.245978355407715],
[2510289458, 9.802596092224121],
[2519167958, 8.324995994567871],
[2519168916, 6.470015525817871],
[2519169541, 6.564258575439453],
[2519169958, 8.094470977783203],
[2529540916, 9.776058197021484],
[2540144458, 11.724246978759766],
[2558413000, 13.994091033935547],
[2558413875, 12.516490936279297],
[2558414416, 11.038890838623047],
[2558414875, 9.561290740966797],
[2558415333, 8.083690643310547],
[2558415791, 6.443614959716797],
[2558416250, 6.537858009338379],
[2558416666, 8.060685157775879],
[2567831041, 9.742241859436035],
[2581776333, 11.690400123596191],
[2590376958, 13.960183143615723],
[2596678750, 15.916886329650879],
[2596679875, 14.354386329650879],
[2608502916, 17.097771644592285],
[2608504083, 15.347771644592285],
[2608504583, 18.437935829162598],
[2608505125, 16.469185829162598],
[2628432625, 19.949456214904785],
[2628433750, 17.730706214904785],
[2628434250, 16.253113746643066],
[2628434666, 14.775513648986816],
[2628435125, 13.297913551330566],
[2628435500, 11.820313453674316],
[2628435916, 10.342713356018066],
[2628436500, 6.417298316955566],
[2628437000, 6.511541366577148],
[2651115750, 8.042112350463867],
[2651116416, 8.13635540008545],
[2663687958, 9.69294261932373],
[2672628958, 8.21534252166748],
[2672629666, 6.3603315353393555],
[2672630250, 6.4545745849609375],
[2672630666, 7.9847869873046875],
[2682914458, 9.666374206542969],
[2693624916, 11.61456298828125],
[2701116750, 13.884407043457031],
[2716921916, 12.406806945800781],
[2716922583, 10.929206848144531],
[2716923166, 9.451606750488281],
[2716923666, 7.974006652832031],
[2716924166, 6.333900451660156],
[2716924750, 6.428143501281738],
[2716925250, 7.951001167297363],
[2723700625, 9.63249683380127],
[2729979166, 11.580655097961426],
[2745605125, 13.850468635559082],
[2761422500, 15.807202339172363],
[2761423458, 14.244702339172363],
[2761424000, 16.988064765930176],
[2761424541, 15.238064765930176],
[2761425041, 18.32816791534424],
[2761425666, 16.35941791534424],
[2773077916, 19.83971881866455],
[2773078666, 17.62096881866455],
[2773079250, 16.143376350402832],
[2773079833, 14.665776252746582],
[2773080375, 13.188176155090332],
[2773080916, 11.710576057434082],
[2773081458, 10.232975959777832],
[2773082250, 6.307560920715332],
[2785779083, 6.401803970336914],
[2808270541, 7.932390213012695],
[2808271083, 8.026633262634277],
[2817238083, 9.583250999450684],
[2825357708, 8.105650901794434],
[2825358416, 6.250670433044434],
[2825359000, 6.344913482666016],
[2825359416, 7.875125885009766],
[2832060208, 9.556713104248047],
[2843280041, 11.504901885986328],
[2858262166, 13.774715423583984],
[2867815125, 12.297115325927734],
[2867815958, 10.819515228271484],
[2867816500, 9.341915130615234],
[2867816958, 7.864315032958984],
[2867817458, 6.224239349365234],
[2867818208, 6.318482398986816],
[2867818708, 7.841340065002441],
[2884557000, 9.522866249084473],
[2884557708, 11.471055030822754],
[2892819166, 13.74086856842041],
[2907878791, 15.698105812072754],
[2907879500, 14.135605812072754],
[2907880166, 16.87893772125244],
[2907880708, 15.128937721252441],
[2915383916, 18.21907138824463],
[2915384708, 16.25032138824463],
[2926657333, 19.73062229156494],
[2926658583, 17.51187229156494],
[2926659083, 16.034279823303223],
[2926659500, 14.556679725646973],
[2926659958, 13.079079627990723],
[2926660375, 11.601479530334473],
[2926660791, 10.123879432678223],
[2926661583, 6.198464393615723],
[2926662041, 6.292707443237305],
[2967271708, 7.823369979858398],
[2967272291, 7.9176130294799805],
[2967272708, 9.474230766296387],
[2976143083, 7.996630668640137],
[2976143750, 6.141619682312012],
[2976144291, 6.235862731933594],
[2976144750, 7.766075134277344],
[2982450583, 9.4476318359375],
[3005089666, 11.395790100097656],
[3005090166, 13.665634155273438],
[3034649458, 12.188034057617188],
[3034650416, 10.710433959960938],
[3034650875, 9.232833862304688],
[3034651333, 7.7552337646484375],
[3034651833, 6.1151275634765625],
[3034652333, 6.2093706130981445],
[3034652750, 7.7322282791137695],
[3034653166, 9.413784980773926],
[3034653541, 11.361943244934082],
[3046986333, 13.631756782531738],
[3060237208, 15.588459968566895],
[3060237833, 14.025959968566895],
[3060242791, 16.769291877746582],
[3060243500, 15.019291877746582],
[3072034000, 18.10942554473877],
[3072034791, 16.14067554473877],
[3086001625, 19.620945930480957],
[3086002791, 17.402195930480957],
[3086003500, 15.924603462219238],
[3086004000, 14.447003364562988],
[3086004458, 12.969403266906738],
[3086004916, 11.491803169250488],
[3086005500, 10.014203071594238],
[3086006125, 6.088788032531738],
[3086006708, 6.18303108215332],
[3109486416, 7.713602066040039],
[3109487083, 7.807845115661621],
[3122066000, 9.364432334899902],
[3130358250, 7.886832237243652],
[3130358916, 6.031821250915527],
[3130359458, 6.126064300537109],
[3130359916, 7.656276702880859],
[3147035875, 9.33786392211914],
[3147036416, 11.286052703857422],
[3157043666, 13.555866241455078],
[3174609375, 12.078266143798828],
[3174610083, 10.600666046142578],
[3174610625, 9.123065948486328],
[3174611083, 7.645465850830078],
[3174611541, 6.005390167236328],
[3174612041, 6.09963321685791],
[3174612500, 7.622490882873535],
[3183564708, 9.304047584533691],
[3192816000, 11.252236366271973],
[3199070708, 13.522049903869629],
[3219448875, 15.478753089904785],
[3219449791, 13.916253089904785],
[3219450333, 16.659615516662598],
[3219450833, 14.909615516662598],
[3219451250, 17.99971866607666],
[3219451791, 16.03096866607666],
[3232043625, 19.511269569396973],
[3232044708, 17.292519569396973],
[3232045208, 15.814927101135254],
[3232045625, 14.337327003479004],
[3232046125, 12.859726905822754],
[3232046541, 11.382126808166504],
[3232046958, 9.904526710510254],
[3232047541, 5.979111671447754],
[3232048083, 6.073354721069336],
[3265022458, 7.603918075561523],
[3265023083, 7.6981611251831055],
[3271316583, 9.254679679870605],
[3282563750, 7.7770795822143555],
[3282564458, 5.9220991134643555],
[3282565000, 6.0163421630859375],
[3282565458, 7.5465545654296875],
[3293271708, 9.228141784667969],
[3299543541, 11.176300048828125],
[3315502083, 13.446144104003906],
[3328144541, 11.968544006347656],
[3328145333, 10.490943908691406],
[3328145916, 9.013343811035156],
[3328146375, 7.535743713378906],
[3328146958, 5.895637512207031],
[3328147791, 5.989880561828613],
[3328148250, 7.512738227844238],
[3337771291, 9.19426441192627],
[3347566083, 11.14245319366455],
[3358794416, 13.412297248840332],
[3375066916, 15.369030952453613],
[3375067958, 13.806530952453613],
[3375068458, 16.549893379211426],
[3375069000, 14.799893379211426],
[3375069458, 17.890103340148926],
[3375069916, 15.921353340148926],
[3382583958, 19.40165424346924],
[3382585500, 17.18290424346924],
[3393219166, 15.70531177520752],
[3393220125, 14.22771167755127],
[3393220750, 12.75011157989502],
[3393221208, 11.27251148223877],
[3393224000, 9.79491138458252],
[3393224791, 5.8694963455200195],
[3393225458, 5.963739395141602],
[3422212166, 7.494386672973633],
[3422213000, 7.588629722595215],
[3437602000, 9.145247459411621],
[3437603291, 7.667647361755371],
[3437604000, 5.812666893005371],
[3437604500, 5.906909942626953],
[3437604916, 7.437091827392578],
[3449235125, 9.11867904663086],
[3459932500, 11.06686782836914],
[3471862208, 13.336711883544922],
[3483691291, 11.859111785888672],
[3483692208, 10.381511688232422],
[3483692708, 8.903911590576172],
[3483693166, 7.426311492919922],
[3483693625, 5.786205291748047],
[3483694208, 5.880448341369629],
[3483694666, 7.403336524963379],
[3498917333, 9.08486270904541],
[3498918041, 11.033051490783691],
[3507067000, 13.302865028381348],
[3517777750, 15.259598731994629],
[3517778666, 13.697098731994629],
[3534453375, 16.440430641174316],
[3534454166, 14.690430641174316],
[3534454666, 17.78059482574463],
[3534455125, 15.811844825744629],
[3540744125, 19.292115211486816],
[3540745250, 17.073365211486816],
[3540745750, 15.595772743225098],
[3540746250, 14.118172645568848],
[3540746708, 12.640572547912598],
[3540747083, 11.162972450256348],
[3540747541, 9.685372352600098],
[3540748166, 5.759957313537598],
[3540748666, 5.85420036315918],
[3575509666, 7.384756088256836],
[3575510208, 7.478999137878418],
[3584537583, 9.035616874694824],
[3592698750, 7.558016777038574],
[3592699458, 5.703036308288574],
[3592700000, 5.797279357910156],
[3592700458, 7.327491760253906],
[3599233166, 9.009078979492188],
[3613639166, 10.957237243652344],
[3620069125, 13.227081298828125],
[3636921708, 11.749481201171875],
[3636922500, 10.271881103515625],
[3636923000, 8.794281005859375],
[3636923458, 7.316680908203125],
[3636924000, 5.67657470703125],
[3636924583, 5.770817756652832],
[3636925000, 7.293675422668457],
[3643251250, 8.975232124328613],
[3649553250, 10.92339038848877],
[3665513958, 13.193203926086426],
[3681309083, 15.149937629699707],
[3681309958, 13.587437629699707],
[3681310416, 16.33080005645752],
[3681310916, 14.58080005645752],
[3681311375, 17.670903205871582],
[3681311958, 15.702153205871582],
[3694522291, 19.182454109191895],
[3694523541, 16.963704109191895],
[3694524083, 15.486111640930176],
[3694524500, 14.008511543273926],
[3694525000, 12.530911445617676],
[3694525416, 11.053311347961426],
[3694525833, 9.575711250305176],
[3694526583, 5.650296211242676],
[3694527166, 5.744539260864258],
[3723738708, 7.275102615356445],
[3723739291, 7.369345664978027],
[3734446291, 8.925963401794434],
[3745654458, 7.448363304138184],
[3745655458, 5.593352317810059],
[3745655958, 5.687595367431641],
[3745656375, 7.217838287353516],
[3756014416, 8.899394989013672],
[3766548375, 10.847583770751953],
[3778433041, 13.117427825927734],
[3790074625, 11.639827728271484],
[3790075708, 10.162227630615234],
[3790076250, 8.684627532958984],
[3790076708, 7.207027435302734],
[3790077291, 5.566951751708984],
[3790080833, 5.661194801330566],
[3790081416, 7.184052467346191],
[3798908250, 8.865555763244629],
[3808254916, 10.81374454498291],
[3815907375, 13.083588600158691],
[3822187458, 15.040291786193848],
[3822188583, 13.477791786193848],
[3828484250, 16.221177101135254],
[3828484916, 14.471177101135254],
[3840434916, 17.561440467834473],
[3840438208, 15.592690467834473],
[3846811333, 19.07296085357666],
[3846812083, 16.85421085357666],
[3846812583, 15.376618385314941],
[3846812958, 13.899018287658691],
[3846813458, 12.421418190002441],
[3846813916, 10.943818092346191],
[3846814333, 9.466217994689941],
[3846814875, 5.540833473205566],
[3846815375, 5.635076522827148],
[3881888500, 7.165685653686523],
[3881889083, 7.2599287033081055],
[3897167041, 8.816546440124512],
[3897168041, 7.338946342468262],
[3897168583, 5.483965873718262],
[3897169000, 5.578208923339844],
[3897169500, 7.108390808105469],
[3915722958, 8.789947509765625],
[3915723458, 10.738136291503906],
[3931951333, 13.007949829101562],
[3943408541, 11.530349731445312],
[3943409375, 10.052749633789062],
[3943409916, 8.575149536132812],
[3943410416, 7.0975494384765625],
[3943410916, 5.4574737548828125],
[3943411458, 5.5517168045043945],
[3943411916, 7.0746049880981445],
[3958364916, 8.756131172180176],
[3958365416, 10.704319953918457],
[3966163166, 12.974133491516113],
[3981614583, 14.93083667755127],
[3981615500, 13.36833667755127],
[3981616041, 16.111668586730957],
[3981616541, 14.361668586730957],
[3989145666, 17.451802253723145],
[3989146375, 15.483052253723145],
[4000956083, 18.963269233703613],
[4000957166, 16.744519233703613],
[4000957666, 15.266926765441895],
[4000958125, 13.789326667785645],
[4000958541, 12.311726570129395],
[4000958958, 10.834126472473145],
[4000959375, 9.356526374816895],
[4000960125, 5.4311418533325195],
[4000960625, 5.525384902954102],
[4034436833, 7.056039810180664],
[4034437416, 7.150282859802246],
[4050000166, 8.706870079040527],
[4050001166, 7.229269981384277],
[4050001791, 5.374289512634277],
[4050002291, 5.468532562255859],
[4050002875, 6.998714447021484],
[4059487416, 8.680301666259766],
[4072034541, 10.628459930419922],
[4084398625, 12.898273468017578],
[4095844458, 11.420673370361328],
[4095845291, 9.943073272705078],
[4095845833, 8.465473175048828],
[4095846375, 6.987873077392578],
[4095846833, 5.347797393798828],
[4095847541, 5.44204044342041],
[4095848000, 6.964898109436035],
[4105105916, 8.646454811096191],
[4114601541, 10.594643592834473],
[4122070375, 12.864487648010254],
[4134662791, 14.82119083404541],
[4134663958, 13.25869083404541],
[4134664625, 16.002022743225098],
[4134665166, 14.252022743225098],
[4147021041, 17.34212589263916],
[4147021708, 15.37337589263916],
[4153329541, 18.853676795959473],
[4153330708, 16.634926795959473],
[4153331250, 15.157334327697754],
[4153331708, 13.679734230041504],
[4153332208, 12.202134132385254],
[4153332625, 10.724534034729004],
[4153333041, 9.246933937072754],
[4153333750, 5.321518898010254],
[4153334250, 5.415761947631836],
[4184476000, 6.946355819702148],
[4184476666, 7.0405988693237305],
[4197048916, 8.59711742401123],
[4205570375, 7.1195173263549805],
[4205571333, 5.2645063400268555],
[4205571958, 5.3587493896484375],
[4205572458, 6.8889617919921875],
[4222327541, 8.570549011230469],
[4222328125, 10.51873779296875],
[4234438750, 12.788551330566406],
[4244769625, 11.310951232910156],
[4244770541, 9.833351135253906],
[4244771041, 8.355751037597656],
[4244771583, 6.878150939941406],
[4244772041, 5.238075256347656],
[4244772791, 5.332318305969238],
[4244773208, 6.855175971984863],
[4257109833, 8.53673267364502],
[4263438958, 10.484890937805176],
[4278885750, 12.754704475402832],
[4294703250, 14.711438179016113],
[4294704333, 13.148938179016113],
[4294704875, 15.892300605773926],
[4294705416, 14.142300605773926],
[4294705916, 17.23240375518799],
[4294706458, 15.263653755187988],
[4306226541, 18.7439546585083],
[4306227583, 16.5252046585083],
[4306228250, 15.047612190246582],
[4306228791, 13.570012092590332],
[4306229375, 12.092411994934082],
[4306229875, 10.614811897277832],
[4306230500, 9.137211799621582],
[4306231291, 5.211796760559082],
[4312647583, 5.306039810180664],
[4347720458, 6.836626052856445],
[4347721000, 6.930869102478027],
[4347721458, 8.487486839294434],
[4358549291, 7.009886741638184],
[4358550125, 5.154875755310059],
[4358550708, 5.249118804931641],
[4358551166, 6.779331207275391],
[4365445208, 8.460918426513672],
[4379412625, 10.409076690673828],
[4388702625, 12.678852081298828],
[4402719833, 11.201251983642578],
[4402720625, 9.723651885986328],
[4402721166, 8.246051788330078],
[4402721625, 6.768451690673828],
[4402722166, 5.128345489501953],
[4402722791, 5.222588539123535],
[4402723250, 6.74544620513916],
[4411434708, 8.426972389221191],
[4420922583, 10.375161170959473],
[4431463916, 12.645005226135254],
[4438014583, 14.601738929748535],
[4438015250, 13.039238929748535],
[4453011666, 15.782624244689941],
[4453012333, 14.032624244689941],
[4453012791, 17.122788429260254],
[4453013291, 15.154038429260254],
[4459542375, 18.63430881500244],
[4459543500, 16.41555881500244],
[4459544041, 14.937966346740723],
[4459544458, 13.460366249084473],
[4459544875, 11.982766151428223],
[4459545291, 10.505166053771973],
[4459545750, 9.027565956115723],
[4459546416, 5.102150917053223],
[4459546875, 5.196393966674805],
[4492833291, 6.727071762084961],
[4492833916, 6.821314811706543],
[4502904958, 8.377902030944824],
[4511007333, 6.900301933288574],
[4511007916, 5.045321464538574],
[4511008416, 5.139564514160156],
[4511008875, 6.669776916503906],
[4517759375, 8.351364135742188],
[4531946583, 10.299522399902344],
[4540444291, 12.569366455078125],
[4555224875, 11.091766357421875],
[4555225541, 9.614166259765625],
[4555226250, 8.136566162109375],
[4555226750, 6.658966064453125],
[4555227291, 5.01885986328125],
[4555227833, 5.113102912902832],
[4555228291, 6.635960578918457],
[4563665291, 8.317517280578613],
[4569929666, 10.26567554473877],
[4590299750, 12.535489082336426],
[4590300291, 14.492222785949707],
[4590301166, 12.929722785949707],
[4599284458, 15.67302417755127],
[4599285291, 13.92302417755127],
[4599285750, 17.013188362121582],
[4599286250, 15.044438362121582],
[4611797791, 18.524739265441895],
[4611798666, 16.305989265441895],
[4611799166, 14.828396797180176],
[4611799625, 13.350796699523926],
[4611800041, 11.873196601867676],
[4611800541, 10.395596504211426],
[4611800958, 8.917996406555176],
[4611801791, 4.992581367492676],
[4611802333, 5.086824417114258],
[4646526333, 6.617380142211914],
[4646527000, 6.711623191833496],
[4661985708, 8.268240928649902],
[4661986791, 6.790640830993652],
[4661987541, 4.935660362243652],
[4661988041, 5.029903411865234],
[4661988458, 6.560085296630859],
[4672054708, 8.24167251586914],
[4684627791, 10.189830780029297],
[4702979458, 12.459644317626953],
[4702980791, 10.982044219970703],
[4702981458, 9.504444122314453],
[4702982000, 8.026844024658203],
[4702982458, 6.549243927001953],
[4702982958, 4.909168243408203],
[4702983500, 5.003411293029785],
[4702984041, 6.526238441467285],
[4717036125, 8.207795143127441],
[4726367583, 10.155983924865723],
[4734430041, 12.425827980041504],
[4740754500, 14.38253116607666],
[4740755458, 12.82003116607666],
[4752316000, 15.563416481018066],
[4752316791, 13.813416481018066],
[4752317291, 16.90358066558838],
[4752317833, 14.934830665588379],
[4765001458, 18.415101051330566],
[4765002458, 16.196351051330566],
[4765003000, 14.718758583068848],
[4765003458, 13.241158485412598],
[4765003958, 11.763558387756348],
[4765004416, 10.285958290100098],
[4765004875, 8.808358192443848],
[4765005625, 4.882973670959473],
[4765006166, 4.977216720581055],
[4805867833, 6.50782585144043],
[4805868416, 6.602068901062012],
[4805868875, 8.158686637878418],
[4816659583, 6.681086540222168],
[4816660166, 4.826075553894043],
[4816660708, 4.920318603515625],
[4816661125, 6.450531005859375],
[4823793916, 8.132118225097656],
[4836392083, 10.080276489257812],
[4846973833, 12.350120544433594],
[4860935375, 10.872520446777344],
[4860936208, 9.394920349121094],
[4860936708, 7.917320251464844],
[4860937208, 6.439720153808594],
[4860937666, 4.799613952636719],
[4860938291, 4.893857002258301],
[4860938791, 6.416745185852051],
[4869182625, 8.098271369934082],
[4879623000, 10.046460151672363],
[4890473166, 12.316304206848145],
[4897018916, 14.273037910461426],
[4897020083, 12.710537910461426],
[4906043916, 15.453923225402832],
[4906045250, 13.703923225402832],
[4912880875, 16.794087409973145],
[4912882250, 14.825337409973145],
[4919803625, 18.305577278137207],
[4919804833, 16.086827278137207],
[4919805375, 14.609234809875488],
[4919805791, 13.131634712219238],
[4919806208, 11.654034614562988],
[4919806666, 10.176434516906738],
[4919807083, 8.698834419250488],
[4919807750, 4.773419380187988],
[4919808250, 4.86766242980957],
[4954279791, 6.398340225219727],
[4954280625, 6.492583274841309],
[4963331000, 8.049201011657715],
[4971794833, 6.571600914001465],
[4971795666, 4.716620445251465],
[4971796291, 4.810863494873047],
[4971796708, 6.341075897216797],
[4980337708, 8.022663116455078],
[4992509125, 9.97085189819336],
[5005161583, 12.24069595336914],
[5023299958, 10.76309585571289],
[5023300875, 9.28549575805664],
[5023301416, 7.807895660400391],
[5023301958, 6.330295562744141],
[5023302458, 4.690189361572266],
[5023303125, 4.784432411193848],
[5023303666, 6.307320594787598],
[5023304208, 7.988846778869629],
[5029638416, 9.937005043029785],
[5044778666, 12.206818580627441],
[5050833625, 14.163552284240723],
[5050834750, 12.601052284240723],
[5057135791, 15.34438419342041],
[5057136416, 13.59438419342041],
[5063445708, 16.684517860412598],
[5063446375, 14.715767860412598],
[5069768250, 18.195984840393066],
[5069768875, 15.977234840393066],
[5078150875, 14.499642372131348],
[5078151791, 13.022042274475098],
[5078152333, 11.544442176818848],
[5078152750, 10.066842079162598],
[5078153166, 8.589241981506348],
[5078154083, 4.663826942443848],
[5078154708, 4.75806999206543],
[5108192000, 6.288686752319336],
[5108192625, 6.382929801940918],
[5123289625, 7.939547538757324],
[5123290666, 6.461947441101074],
[5123291375, 4.606966972351074],
[5123291833, 4.701210021972656],
[5123292333, 6.231391906738281],
[5134424666, 7.9129791259765625],
[5146178375, 9.861167907714844],
[5157161166, 12.131011962890625],
[5167799333, 10.653411865234375],
[5167800083, 9.175811767578125],
[5167800708, 7.698211669921875],
[5167801250, 6.220611572265625],
[5167801750, 4.580535888671875],
[5167802416, 4.674778938293457],
[5167802875, 6.197636604309082],
[5177584333, 7.879162788391113],
[5194535541, 9.827351570129395],
[5194536083, 12.097195625305176],
[5202336500, 14.053898811340332],
[5202337416, 12.491398811340332],
[5220407416, 15.23473072052002],
[5220408291, 13.48473072052002],
[5220408791, 16.574894905090332],
[5220409250, 14.606144905090332],
[5226684250, 18.08641529083252],
[5226685166, 15.86766529083252],
[5226685666, 14.3900728225708],
[5226686125, 12.91247272491455],
[5226686541, 11.4348726272583],
[5226686958, 9.95727252960205],
[5226687375, 8.4796724319458],
[5226688083, 4.554257392883301],
[5226688583, 4.648500442504883],
[5261451875, 6.179033279418945],
[5261452458, 6.273276329040527],
[5270580041, 7.829894065856934],
[5278665625, 6.352293968200684],
[5278666291, 4.497313499450684],
[5278667791, 4.591556549072266],
[5278668208, 6.121768951416016],
[5288731833, 7.803356170654297],
[5299483500, 9.751514434814453],
[5311406375, 12.021358489990234],
[5322807416, 10.543758392333984],
[5322808125, 9.066158294677734],
[5322808666, 7.588558197021484],
[5322809125, 6.110958099365234],
[5322809666, 4.470882415771484],
[5322810208, 4.565125465393066],
[5322810666, 6.087983131408691],
[5331669666, 7.769539833068848],
[5338282458, 9.717728614807129],
[5350851458, 11.987542152404785],
[5359493541, 13.944275856018066],
[5359494333, 12.381775856018066],
[5365810500, 15.125107765197754],
[5365811333, 13.375107765197754],
[5372039583, 16.46524143218994],
[5372040250, 14.496491432189941],
[5380457666, 17.97676181793213],
[5380458625, 15.758011817932129],
[5380459083, 14.28041934967041],
[5380459500, 12.80281925201416],
[5380459916, 11.32521915435791],
[5380460333, 9.84761905670166],
[5380460750, 8.37001895904541],
[5380461375, 4.44460391998291],
[5380461833, 4.538846969604492],
[5413462666, 6.069440841674805],
[5413463250, 6.163683891296387],
[5423096291, 7.720301628112793],
[5430319250, 6.242701530456543],
[5430319916, 4.387721061706543],
[5430320500, 4.481964111328125],
[5430320958, 6.012176513671875],
[5441570375, 7.693733215332031],
[5452075333, 9.641921997070312],
[5470306958, 11.911766052246094],
[5470308000, 10.434165954589844],
[5470308583, 8.956565856933594],
[5470309083, 7.478965759277344],
[5470309625, 6.001365661621094],
[5470310125, 4.361289978027344],
[5470310583, 4.455533027648926],
[5470311041, 5.978360176086426],
[5478482166, 7.659916877746582],
[5493521333, 9.608075141906738],
[5501086166, 11.87791919708252],
[5507371750, 13.834622383117676],
[5507372541, 12.272122383117676],
[5525668541, 15.015507698059082],
[5525669541, 13.265507698059082],
[5525670083, 16.355671882629395],
[5525670583, 14.386921882629395],
[5532032458, 17.867161750793457],
[5532033208, 15.648411750793457],
[5532033666, 14.170819282531738],
[5532034125, 12.693219184875488],
[5532034541, 11.215619087219238],
[5532034916, 9.738018989562988],
[5532035375, 8.260418891906738],
[5532036041, 4.335034370422363],
[5532036500, 4.429277420043945],
[5565803583, 5.959833145141602],
[5565804208, 6.054076194763184],
[5575695708, 7.61063289642334],
[5582184583, 6.13303279876709],
[5582185333, 4.27805233001709],
[5582185916, 4.372295379638672],
[5582186416, 5.902507781982422],
[5592821958, 7.584095001220703],
[5604733833, 9.53225326538086],
[5616643958, 11.80209732055664],
[5628017333, 10.32449722290039],
[5628018083, 8.84689712524414],
[5628018625, 7.369297027587891],
[5628019125, 5.891696929931641],
[5628019708, 4.251621246337891],
[5628020291, 4.345864295959473],
[5628020791, 5.868721961975098],
[5636952291, 7.550278663635254],
[5646289375, 9.498467445373535],
[5655360583, 11.768311500549316],
[5661691916, 13.725014686584473],
[5661692750, 12.162514686584473],
[5672171208, 14.905900001525879],
[5672171916, 13.155900001525879],
[5672172375, 16.246033668518066],
[5672172916, 14.277283668518066],
[5684706583, 17.75752353668213],
[5684707500, 15.538773536682129],
[5684708000, 14.06118106842041],
[5684708500, 12.58358097076416],
[5684709000, 11.10598087310791],
[5684709500, 9.62838077545166],
[5684709916, 8.15078067779541],
[5684710500, 4.22536563873291],
[5684710958, 4.319608688354492],
[5713620750, 5.850225448608398],
[5713621375, 5.9444684982299805],
[5726138625, 7.501086235046387],
[5732462250, 6.023486137390137],
[5732462958, 4.168475151062012],
[5732463583, 4.262718200683594],
[5732464041, 5.792930603027344],
[5746844625, 7.474540710449219],
[5757283083, 9.4227294921875],
[5763543916, 11.692573547363281],
[5776172041, 10.214973449707031],
[5776172791, 8.737373352050781],
[5776173375, 7.259773254394531],
[5776173916, 5.782173156738281],
[5776174458, 4.142097473144531],
[5776175000, 4.236340522766113],
[5776175458, 5.759198188781738],
[5788313791, 7.4407548904418945],
[5798864166, 9.38891315460205],
[5809497375, 11.658757209777832],
[5825323291, 13.615490913391113],
[5825324333, 12.052990913391113],
[5825324791, 14.796353340148926],
[5825325291, 13.046353340148926],
[5825325750, 16.13645648956299],
[5825326250, 14.167706489562988],
[5834424541, 17.648655891418457],
[5834428125, 15.429905891418457],
[5843290541, 13.952313423156738],
[5843291500, 12.474713325500488],
[5843292041, 10.997113227844238],
[5843292458, 9.519513130187988],
[5843292875, 8.041913032531738],
[5843293708, 4.116497993469238],
[5843294375, 4.21074104309082],
[5872046083, 5.741365432739258],
[5872046708, 5.83560848236084],
[5881277583, 7.392195701599121],
[5889366666, 5.914595603942871],
[5889367333, 4.059615135192871],
[5889367875, 4.153858184814453],
[5889368458, 5.684070587158203],
[5896962250, 7.365657806396484],
[5909522041, 9.31381607055664],
[5920174208, 11.583660125732422],
[5932738083, 10.106060028076172],
[5932738750, 8.628459930419922],
[5932739333, 7.150859832763672],
[5932739875, 5.673259735107422],
[5932740333, 4.033153533935547],
[5932740958, 4.127396583557129],
[5932741416, 5.650284767150879],
[5942300625, 7.33181095123291],
[5951733416, 9.279999732971191],
[5968639708, 11.549843788146973],
[5968640291, 13.506577491760254],
[5968641250, 11.944077491760254],
[5983952791, 14.687378883361816],
[5983953458, 12.937378883361816],
[5983953916, 16.02754306793213],
[5983954416, 14.058793067932129],
[5996574333, 17.539063453674316],
[5996575333, 15.320313453674316],
[5996575791, 13.842720985412598],
[5996576250, 12.365120887756348],
[5996576666, 10.887520790100098],
[5996577125, 9.409920692443848],
[5996577541, 7.932320594787598],
[5996578083, 4.006905555725098],
[5996578541, 4.10114860534668],
[6023854250, 5.631811141967773],
[6023854875, 5.7260541915893555],
[6033950166, 7.282641410827637],
[6042210333, 5.805041313171387],
[6042211041, 3.9500608444213867],
[6042211625, 4.044303894042969],
[6042212125, 5.574516296386719],
[6052701375, 7.256103515625],
[6059513083, 9.204292297363281],
[6070225541, 11.474136352539062],
[6082716166, 9.996536254882812],
[6082716750, 8.518936157226562],
[6082717250, 7.0413360595703125],
[6082717750, 5.5637359619140625],
[6082718208, 3.9236602783203125],
[6082718791, 4.0179033279418945],
[6082719208, 5.5407609939575195],
[6093240458, 7.222317695617676],
[6099498041, 9.170475959777832],
[6115766666, 11.440289497375488],
[6125366416, 13.39702320098877],
[6125367125, 11.83452320098877],
[6125367625, 14.577885627746582],
[6125368125, 12.827885627746582],
[6137461166, 15.917988777160645],
[6137462125, 13.949238777160645],
[6143745375, 17.429539680480957],
[6143746291, 15.210789680480957],
[6143746791, 13.733197212219238],
[6143747208, 12.255597114562988],
[6143747666, 10.777997016906738],
[6143748083, 9.300396919250488],
[6143748500, 7.822796821594238],
[6143749208, 3.8973817825317383],
[6143749708, 3.9916248321533203],
[6176584125, 5.522188186645508],
[6176584708, 5.61643123626709],
[6182905625, 7.173018455505371],
[6201793041, 5.695418357849121],
[6201793583, 3.840407371520996],
[6201794083, 3.934650421142578],
[6201794500, 5.464862823486328],
[6201794916, 7.146450042724609],
[6216200666, 9.094608306884766],
[6234594666, 11.364452362060547],
[6234595708, 9.886852264404297],
[6234596291, 8.409252166748047],
[6234596916, 6.931652069091797],
[6234597416, 5.454051971435547],
[6234597916, 3.813976287841797],
[6234598416, 3.908219337463379],
[6234598875, 5.431046485900879],
[6243242791, 7.112603187561035],
[6257783000, 9.060761451721191],
[6266028333, 11.330605506896973],
[6272331416, 13.287308692932129],
[6272332166, 11.724808692932129],
[6289983500, 14.468194007873535],
[6289984208, 12.718194007873535],
[6289984666, 15.808358192443848],
[6289985166, 13.839608192443848],
[6302579416, 17.31984806060791],
[6302580541, 15.10109806060791],
[6302581041, 13.623505592346191],
[6302581416, 12.145905494689941],
[6302581833, 10.668305397033691],
[6302582291, 9.190705299377441],
[6302582708, 7.713105201721191],
[6302583458, 3.7877206802368164],
[6302583916, 3.8819637298583984],
[6331909375, 5.412542343139648],
[6331910166, 5.5067853927612305],
[6348601083, 7.063403129577637],
[6348602458, 5.585803031921387],
[6348603083, 3.7308225631713867],
[6348603666, 3.8250656127929688],
[6348604083, 5.355247497558594],
[6366771875, 7.036834716796875],
[6366772916, 8.985023498535156],
[6390463166, 11.254837036132812],
[6390464500, 9.777236938476562],
[6390465083, 8.299636840820312],
[6390465541, 6.8220367431640625],
[6390466041, 5.3444366455078125],
[6390466500, 3.7043609619140625],
[6390466958, 3.7986040115356445],
[6390467416, 5.3214311599731445],
[6401087000, 7.002987861633301],
[6412862208, 8.951176643371582],
[6419122541, 11.220990180969238],
[6434475458, 13.177693367004395],
[6434476625, 11.615193367004395],
[6434477125, 14.358555793762207],
[6434477625, 12.608555793762207],
[6446840500, 15.69871997833252],
[6446841375, 13.72996997833252],
[6455593916, 17.210240364074707],
[6455595250, 14.991490364074707],
[6455595750, 13.513897895812988],
[6455596166, 12.036297798156738],
[6455596625, 10.558697700500488],
[6455597041, 9.081097602844238],
[6455597416, 7.603497505187988],
[6455598125, 3.6780824661254883],
[6455598583, 3.7723255157470703],
[6484438208, 5.302881240844727],
[6484439166, 5.397124290466309],
[6496959250, 6.953742027282715],
[6506738750, 5.476141929626465],
[6506739541, 3.62113094329834],
[6506740166, 3.715373992919922],
[6506740583, 5.245586395263672],
[6517142458, 6.927173614501953],
[6527674708, 8.875362396240234],
[6539903791, 11.145206451416016],
[6551325041, 9.667606353759766],
[6551325875, 8.190006256103516],
[6551326375, 6.712406158447266],
[6551326833, 5.234806060791016],
[6551327500, 3.5947303771972656],
[6551328083, 3.6889734268188477],
[6551328541, 5.211831092834473],
[6566540416, 6.893387794494629],
[6566540958, 8.84157657623291],
[6578056666, 11.111390113830566],
[6602234916, 13.068093299865723],
[6602236041, 11.505593299865723],
[6602236541, 14.248955726623535],
[6602237041, 12.498955726623535],
[6602237458, 15.589142799377441],
[6602237958, 13.620392799377441],
[6608582875, 17.10066318511963],
[6608584041, 14.881913185119629],
[6608584500, 13.40432071685791],
[6608590208, 11.92672061920166],
[6608590583, 10.44912052154541],
[6608591125, 8.97152042388916],
[6608591583, 7.49392032623291],
[6608592375, 3.56850528717041],
[6608592875, 3.662748336791992],
[6638717125, 5.193334579467773],
[6638717750, 5.2875776290893555],
[6651080916, 6.844195365905762],
[6659813291, 5.366595268249512],
[6659814000, 3.5115842819213867],
[6659814583, 3.6058273315429688],
[6659814958, 5.136039733886719],
[6670072250, 6.817626953125],
[6680508166, 8.765815734863281],
[6688712875, 11.035659790039062],
[6703730208, 9.558059692382812],
[6703730958, 8.080459594726562],
[6703731416, 6.6028594970703125],
[6703731875, 5.1252593994140625],
[6703732416, 3.4851531982421875],
[6703733000, 3.5793962478637695],
[6703733458, 5.1022539138793945],
[6718681791, 6.783780097961426],
[6718682375, 8.731968879699707],
[6726149291, 11.001782417297363],
[6741932083, 12.95848560333252],
[6741932833, 11.39598560333252],
[6741933291, 14.139317512512207],
[6741933791, 12.389317512512207],
[6751073416, 15.479451179504395],
[6751074041, 13.510701179504395],
[6757382916, 16.990971565246582],
[6757383583, 14.772221565246582],
[6763719458, 13.294629096984863],
[6763720166, 11.817028999328613],
[6763720708, 10.339428901672363],
[6763721208, 8.861828804016113],
[6763721708, 7.384228706359863],
[6763722541, 3.4588136672973633],
[6763723125, 3.5530567169189453],
[6788687791, 5.083703994750977],
[6788688458, 5.177947044372559],
[6803872166, 6.73453426361084],
[6811951625, 5.25693416595459],
[6811952375, 3.401923179626465],
[6811952916, 3.496166229248047],
[6811953333, 5.026378631591797],
[6822389166, 6.707965850830078],
[6832955666, 8.65615463256836],
[6851135125, 10.92599868774414],
[6851136333, 9.44839859008789],
[6851137000, 7.970798492431641],
[6851137541, 6.493198394775391],
[6851138041, 5.015598297119141],
[6851138541, 3.3755226135253906],
[6851139041, 3.4697656631469727],
[6851139500, 4.992592811584473],
[6859496416, 6.674149513244629],
[6874400958, 8.622307777404785],
[6882231416, 10.892151832580566],
[6888535625, 12.848855018615723],
[6888536291, 11.286355018615723],
[6894834416, 14.029740333557129],
[6894835000, 12.279740333557129],
[6906421750, 15.369874000549316],
[6906422333, 13.401124000549316],
[6912780916, 16.881394386291504],
[6912782125, 14.662644386291504],
[6912782666, 13.185051918029785],
[6912783125, 11.707451820373535],
[6912783541, 10.229851722717285],
[6912784000, 8.752251625061035],
[6912784416, 7.274651527404785],
[6912785000, 3.349236488342285],
[6912785500, 3.443479537963867],
[6942823791, 4.974020004272461],
[6942824416, 5.068263053894043],
[6953653208, 6.624880790710449],
[6959921000, 5.147280693054199],
[6959921916, 3.292269706726074],
[6959922666, 3.3865127563476562],
[6959923125, 4.916725158691406],
[6981277875, 6.598335266113281],
[6981278458, 8.546524047851562],
[7003751416, 10.816337585449219],
[7003752541, 9.338737487792969],
[7003753166, 7.861137390136719],
[7003753666, 6.383537292480469],
[7003754125, 4.905937194824219],
[7003754708, 3.2658615112304688],
[7003755250, 3.360104560852051],
[7003755750, 4.882931709289551],
[7011606291, 6.564488410949707],
[7027225458, 8.512646675109863],
[7033460416, 10.782490730285645],
[7046692791, 12.739224433898926],
[7046693791, 11.176724433898926],
[7053889041, 13.920056343078613],
[7053890041, 12.170056343078613],
[7053890583, 15.260220527648926],
[7053891125, 13.291470527648926],
[7067512791, 16.771740913391113],
[7067514000, 14.552990913391113],
[7067514458, 13.075398445129395],
[7067514875, 11.597798347473145],
[7067515375, 10.120198249816895],
[7067515791, 8.642598152160645],
[7067516208, 7.1649980545043945],
[7067517000, 3.2395830154418945],
[7067517458, 3.3338260650634766],
[7096955541, 4.864442825317383],
[7096956208, 4.958685874938965],
[7109522708, 6.515303611755371],
[7124609541, 5.037703514099121],
[7124610250, 3.182692527770996],
[7124610708, 3.276935577392578],
[7124611125, 4.807147979736328],
[7124611541, 6.488735198974609],
[7139067416, 8.436893463134766],
[7151224291, 10.706737518310547],
[7168917250, 9.229137420654297],
[7168918166, 7.751537322998047],
[7168918666, 6.273937225341797],
[7168919125, 4.796337127685547],
[7168919666, 3.156261444091797],
[7168920291, 3.250504493713379],
[7168920708, 4.773362159729004],
[7168921125, 6.45491886138916],
[7176563333, 8.403077125549316],
[7191589875, 10.672890663146973],
[7199425083, 12.629624366760254],
[7199426083, 11.067124366760254],
[7206955625, 13.810456275939941],
[7206956500, 12.060456275939941],
[7206957041, 15.150620460510254],
[7206957500, 13.181870460510254],
[7220330166, 16.662171363830566],
[7220331291, 14.443421363830566],
[7220331791, 12.965828895568848],
[7220332250, 11.488228797912598],
[7220332708, 10.010628700256348],
[7220333125, 8.533028602600098],
[7220333500, 7.055428504943848],
[7220334250, 3.1300134658813477],
[7220334750, 3.2242565155029297],
[7254355666, 4.754880905151367],
[7254356375, 4.849123954772949],
[7263428583, 6.4057416915893555],
[7271664875, 4.9281415939331055],
[7271665625, 3.0731611251831055],
[7271666125, 3.1674041748046875],
[7271666583, 4.6976165771484375],
[7280303958, 6.379203796386719],
[7286623666, 8.327362060546875],
[7303583583, 10.597206115722656],
[7309860166, 9.119606018066406],
[7309861125, 7.642005920410156],
[7309861625, 6.164405822753906],
[7309862083, 4.686805725097656],
[7309862541, 3.0466995239257812],
[7309863333, 3.1409425735473633],
[7316081000, 4.663830757141113],
[7325135625, 6.3453874588012695],
[7334578291, 8.29357624053955],
[7351633000, 10.563420295715332],
[7351633541, 12.520153999328613],
[7351634416, 10.957653999328613],
[7359893500, 13.7009859085083],
[7359894416, 11.9509859085083],
[7367199541, 15.041119575500488],
[7367200291, 13.072369575500488],
[7373479125, 16.5526704788208],
[7373480333, 14.3339204788208],
[7373480875, 12.856328010559082],
[7373481333, 11.378727912902832],
[7373481750, 9.901127815246582],
[7373482208, 8.423527717590332],
[7373482666, 6.945927619934082],
[7373483291, 3.020512580871582],
[7373486458, 3.114755630493164],
[7408251375, 4.645288467407227],
[7408252041, 4.739531517028809],
[7417204625, 6.296149253845215],
[7425287583, 4.818549156188965],
[7425288375, 2.963568687438965],
[7425288916, 3.057811737060547],
[7425289333, 4.588024139404297],
[7432749125, 6.269611358642578],
[7445316375, 8.217769622802734],
[7453587708, 10.487613677978516],
[7466119875, 9.010013580322266],
[7466120833, 7.532413482666016],
[7466121375, 6.054813385009766],
[7466122000, 4.577213287353516],
[7466122458, 2.9371376037597656],
[7466123208, 3.0313806533813477],
[7466123708, 4.554238319396973],
[7476554458, 6.235795021057129],
[7482886250, 8.183953285217285],
[7499232083, 10.453766822814941],
[7508868208, 12.410500526428223],
[7508869083, 10.848000526428223],
[7508869625, 13.591362953186035],
[7508870166, 11.841362953186035],
[7520257708, 14.931496620178223],
[7520258333, 12.962746620178223],
[7528214708, 16.44301700592041],
[7528215708, 14.22426700592041],
[7528216166, 12.746674537658691],
[7528216625, 11.269074440002441],
[7528217208, 9.791474342346191],
[7528217625, 8.313874244689941],
[7528218041, 6.836274147033691],
[7528218666, 2.9108591079711914],
[7528219166, 3.0051021575927734],
[7557256625, 4.535665512084961],
[7557257291, 4.629908561706543],
[7569854541, 6.186495780944824],
[7585410291, 4.708895683288574],
[7585411083, 2.853884696960449],
[7585411583, 2.9481277465820312],
[7585412041, 4.478370666503906],
[7585412458, 6.1599273681640625],
[7600042583, 8.108085632324219],
[7618270875, 10.3779296875],
[7618271833, 8.90032958984375],
[7618272375, 7.4227294921875],
[7618272875, 5.94512939453125],
[7618273375, 4.467529296875],
[7618273875, 2.82745361328125],
[7618274333, 2.921696662902832],
[7618274791, 4.444523811340332],
[7626569541, 6.126080513000488],
[7641589250, 8.074238777160645],
[7649424750, 10.344082832336426],
[7655704916, 12.300786018371582],
[7655705916, 10.738286018371582],
[7667454208, 13.481671333312988],
[7667455083, 11.731671333312988],
[7667455583, 14.8218355178833],
[7667456083, 12.8530855178833],
[7679967791, 16.33335590362549],
[7679968791, 14.114605903625488],
[7679969250, 12.63701343536377],
[7679969666, 11.15941333770752],
[7679970083, 9.68181324005127],
[7679970500, 8.20421314239502],
[7679970916, 6.7266130447387695],
[7679971500, 2.8012285232543945],
[7679971916, 2.8954715728759766],
[7714993416, 4.42607307434082],
[7714994083, 4.520316123962402],
[7730193458, 6.076933860778809],
[7730194583, 4.599333763122559],
[7730195250, 2.7443532943725586],
[7730195666, 2.8385963439941406],
[7730196125, 4.368778228759766],
[7739118125, 6.050365447998047],
[7751065083, 7.998554229736328],
[7763608625, 10.268367767333984],
[7773971166, 8.790767669677734],
[7773972000, 7.313167572021484],
[7773972541, 5.835567474365234],
[7773973000, 4.357967376708984],
[7773973458, 2.7178916931152344],
[7773974208, 2.8121347427368164],
[7773974666, 4.334992408752441],
[7784399875, 6.016549110412598],
[7790657833, 7.964707374572754],
[7810966833, 10.23452091217041],
[7810967333, 12.191254615783691],
[7810968000, 10.628754615783691],
[7817743833, 13.372086524963379],
[7817744833, 11.622086524963379],
[7832548958, 14.712220191955566],
[7832549875, 12.743470191955566],
[7832550375, 16.22377109527588],
[7832550833, 14.005021095275879],
[7832551291, 12.52742862701416],
[7832551750, 11.04982852935791],
[7832552208, 9.57222843170166],
[7832552666, 8.09462833404541],
[7832553083, 6.61702823638916],
[7832553791, 2.691582679748535],
[7832554250, 2.785825729370117],
[7866115583, 4.316427230834961],
[7866116208, 4.410670280456543],
[7875905500, 5.967257499694824],
[7890265208, 4.489657402038574],
[7890265916, 2.634676933288574],
[7890266458, 2.7289199829101562],
[7890266875, 4.259132385253906],
[7890267333, 5.9407196044921875],
[7899434041, 7.888877868652344],
[7922976500, 10.15869140625],
[7922977458, 8.68109130859375],
[7922978041, 7.2034912109375],
[7922978500, 5.72589111328125],
[7922978958, 4.248291015625],
[7922979375, 2.60821533203125],
[7922979875, 2.702458381652832],
[7922980291, 4.225285530090332],
[7932772000, 5.906842231750488],
[7945333500, 7.8550004959106445],
[7953608625, 10.124844551086426],
[7959885458, 12.081547737121582],
[7959886500, 10.519047737121582],
[7966052083, 13.262433052062988],
[7966052666, 11.512433052062988],
[7977989166, 14.602566719055176],
[7977990000, 12.633816719055176],
[7984335666, 16.114087104797363],
[7984336541, 13.895337104797363],
[7984337000, 12.417744636535645],
[7984337458, 10.940144538879395],
[7984338041, 9.462544441223145],
[7984338458, 7.9849443435668945],
[7984338875, 6.5073442459106445],
[7984339458, 2.5819292068481445],
[7984339916, 2.6761722564697266],
[8013593708, 4.206743240356445],
[8013594250, 4.300986289978027],
[8026052416, 5.857604026794434],
[8032382916, 4.380003929138184],
[8032383583, 2.5249929428100586],
[8032384208, 2.6192359924316406],
[8032384666, 4.149448394775391],
[8052679500, 5.831058502197266],
[8052680000, 7.779247283935547],
[8075210583, 10.049060821533203],
[8075211583, 8.571460723876953],
[8075212125, 7.093860626220703],
[8075212625, 5.616260528564453],
[8075213083, 4.138660430908203],
[8075213583, 2.498584747314453],
[8075214041, 2.592827796936035],
[8075214500, 4.115654945373535],
[8082779208, 5.797211647033691],
[8098278708, 7.745369911193848],
[8108780750, 10.015213966369629],
[8116126958, 11.97194766998291],
[8116127875, 10.40944766998291],
[8124240625, 13.152779579162598],
[8124241458, 11.402779579162598],
[8124241958, 14.49294376373291],
[8124242458, 12.52419376373291],
[8137002916, 16.004494667053223],
[8137004208, 13.785744667053223],
[8137004750, 12.308152198791504],
[8137005166, 10.830552101135254],
[8137005583, 9.352952003479004],
[8137006000, 7.875351905822754],
[8137006416, 6.397751808166504],
[8137007208, 2.472336769104004],
[8137007708, 2.566579818725586],
[8170265375, 4.097265243530273],
[8170266000, 4.1915082931518555],
[8180639458, 5.748095512390137],
[8188870583, 4.270495414733887],
[8188871250, 2.4155149459838867],
[8188871750, 2.5097579956054688],
[8188872166, 4.039970397949219],
[8199111625, 5.7215576171875],
[8206806750, 7.669746398925781],
[8221567500, 9.939559936523438],
[8228809208, 8.461959838867188],
[8228810041, 6.9843597412109375],
[8228810541, 5.5067596435546875],
[8228811041, 4.0291595458984375],
[8228811500, 2.3890838623046875],
[8228812208, 2.4833269119262695],
[8228812750, 4.0061845779418945],
[8240676958, 5.687741279602051],
[8251052250, 7.635930061340332],
[8257328458, 9.905743598937988],
[8271149000, 11.862446784973145],
[8271150041, 10.299946784973145],
[8271150583, 13.043309211730957],
[8271151125, 11.293309211730957],
[8282643750, 14.38341236114502],
[8282645083, 12.41466236114502],
[8291112416, 15.894963264465332],
[8291113541, 13.676213264465332],
[8291116375, 12.198620796203613],
[8291116791, 10.721020698547363],
[8291117166, 9.243420600891113],
[8291117583, 7.765820503234863],
[8291118000, 6.288220405578613],
[8291118666, 2.3628053665161133],
[8291119166, 2.4570484161376953],
[8320635791, 3.9876651763916016],
[8320636583, 4.081908226013184],
[8332796666, 5.63852596282959],
[8342206250, 4.16092586517334],
[8342207083, 2.305914878845215],
[8342207708, 2.400157928466797],
[8342208166, 3.930400848388672],
[8352692166, 5.611957550048828],
[8363297458, 7.560146331787109],
[8375223166, 9.82999038696289],
[8392933833, 8.35239028930664],
[8392934500, 6.874790191650391],
[8392935083, 5.397190093994141],
[8392935625, 3.9195899963378906],
[8392936083, 2.2795143127441406],
[8392936750, 2.3737573623657227],
[8392937208, 3.8966150283813477],
[8392937625, 5.578171730041504],
[8403634708, 7.52632999420166],
[8409887791, 9.796143531799316],
[8431105291, 11.752846717834473],
[8431106125, 10.190346717834473],
[8431106708, 12.933709144592285],
[8431107291, 11.183709144592285],
[8431107750, 14.273812294006348],
[8431108291, 12.305062294006348],
[8439098333, 15.78536319732666],
[8439098958, 13.56661319732666],
[8449059083, 12.089020729064941],
[8449060000, 10.611420631408691],
[8449060500, 9.133820533752441],
[8449061000, 7.656220436096191],
[8449061458, 6.178620338439941],
[8449062208, 2.2532052993774414],
[8449062833, 2.3474483489990234],
[8473971125, 3.8780956268310547],
[8473971750, 3.9723386764526367],
[8484420500, 5.528956413269043],
[8495065791, 4.051356315612793],
[8495066541, 2.196345329284668],
[8495067000, 2.29058837890625],
[8495067416, 3.82080078125],
[8505472250, 5.502388000488281],
[8516063666, 7.4505767822265625],
[8527978250, 9.720420837402344],
[8539408208, 8.242820739746094],
[8539409041, 6.765220642089844],
[8539409583, 5.287620544433594],
[8539410083, 3.8100204467773438],
[8539410625, 2.1699447631835938],
[8539411208, 2.264187812805176],
[8539411625, 3.787045478820801],
[8548269791, 5.468602180480957],
[8555779666, 7.416790962219238],
[8562087166, 9.686604499816895],
[8583985791, 11.64330768585205],
[8583986625, 10.08080768585205],
[8583987083, 12.824170112609863],
[8583987583, 11.074170112609863],
[8583988000, 14.164273262023926],
[8583988458, 12.195523262023926],
[8597085125, 15.675824165344238],
[8597086125, 13.457074165344238],
[8597086583, 11.97948169708252],
[8597087000, 10.50188159942627],
[8597087458, 9.02428150177002],
[8597087875, 7.5466814041137695],
[8597088333, 6.0690813064575195],
[8597089125, 2.1436662673950195],
[8597089666, 2.2379093170166016],
[8626535916, 3.7685108184814453],
[8626536458, 3.8627538681030273],
[8636977875, 5.419371604919434],
[8643240916, 3.9417715072631836],
[8643241708, 2.0867605209350586],
[8643242458, 2.1810035705566406],
[8649698583, 3.7112159729003906],
[8658579208, 5.392803192138672],
[8669096083, 7.340991973876953],
[8681022458, 9.610836029052734],
[8692394583, 8.133235931396484],
[8692395333, 6.655635833740234],
[8692395791, 5.178035736083984],
[8692396250, 3.7004356384277344],
[8692396750, 2.0603599548339844],
[8692397291, 2.1546030044555664],
[8692397708, 3.6774911880493164],
[8707324791, 5.359017372131348],
[8707325291, 7.307206153869629],
[8717719541, 9.577019691467285],
[8728505791, 11.533753395080566],
[8728506750, 9.971253395080566],
[8742284333, 12.714585304260254],
[8742285083, 10.964585304260254],
[8742285583, 14.054749488830566],
[8742286166, 12.085999488830566],
[8754885625, 15.566239356994629],
[8754886458, 13.347489356994629],
[8754886916, 11.86989688873291],
[8754887333, 10.39229679107666],
[8754887750, 8.91469669342041],
[8754888166, 7.43709659576416],
[8754888541, 5.95949649810791],
[8754889083, 2.034111976623535],
[8754889500, 2.128355026245117],
[8783215291, 3.6589794158935547],
[8783215875, 3.7532224655151367],
[8792146791, 5.309840202331543],
[8800233500, 3.832240104675293],
[8800234041, 1.977259635925293],
[8800234541, 2.071502685546875],
[8800234916, 3.601715087890625],
[8809380250, 5.283302307128906],
[8815653791, 7.2314605712890625],
[8839318250, 9.501304626464844],
[8839319500, 8.023704528808594],
[8839320083, 6.546104431152344],
[8839320583, 5.068504333496094],
[8839321208, 3.5909042358398438],
[8839321708, 1.9508285522460938],
[8839322166, 2.045071601867676],
[8839322625, 3.567898750305176],
[8853244791, 5.249455451965332],
[8862650375, 7.197644233703613],
[8870233708, 9.467488288879395],
[8876535750, 11.42419147491455],
[8876536875, 9.86169147491455],
[8882639625, 12.605076789855957],
[8882640291, 10.855076789855957],
[8894574000, 13.945210456848145],
[8894574583, 11.976460456848145],
[8907172041, 15.456730842590332],
[8907173208, 13.237980842590332],
[8907173666, 11.760388374328613],
[8907174083, 10.282788276672363],
[8907174458, 8.805188179016113],
[8907174833, 7.327588081359863],
[8907175250, 5.849987983703613],
[8907175916, 1.9246034622192383],
[8907176375, 2.0188465118408203],
[8935515833, 3.5494556427001953],
[8935516416, 3.6436986923217773],
[8950772666, 5.200316429138184],
[8950773625, 3.7227163314819336],
[8950774333, 1.8677358627319336],
[8950774916, 1.9619789123535156],
[8950775375, 3.4921607971191406],
[8959490166, 5.173748016357422],
[8973357541, 7.121906280517578],
[8980812833, 9.39175033569336],
[8996627125, 7.914150238037109],
[8996627750, 6.436550140380859],
[8996628208, 4.958950042724609],
[8996628708, 3.4813499450683594],
[8996629208, 1.8412437438964844],
[8996629791, 1.9354867935180664],
[8996630250, 3.4583444595336914],
[9005353416, 5.139870643615723],
[9014699500, 7.088059425354004],
[9025217125, 9.357903480529785],
[9034620000, 11.314637184143066],
[9034620833, 9.752137184143066],
[9034621291, 12.495469093322754],
[9034621791, 10.745469093322754],
[9042825583, 13.835709571838379],
[9042826416, 11.866959571838379],
[9053959333, 15.347229957580566],
[9053960041, 13.128479957580566],
[9053960500, 11.650887489318848],
[9053960916, 10.173287391662598],
[9053961333, 8.695687294006348],
[9053961750, 7.218087196350098],
[9053962166, 5.740487098693848],
[9053962708, 1.8151025772094727],
[9053963208, 1.9093456268310547],
[9087620625, 3.439970016479492],
[9087621125, 3.534213066101074],
[9096655208, 5.0908308029174805],
[9104690916, 3.6132307052612305],
[9104691625, 1.7588300704956055],
[9104692250, 1.8530731201171875],
[9104692750, 3.3832855224609375],
[9113229750, 5.065467834472656],
[9119525291, 7.0136260986328125],
[9134376208, 9.283470153808594],
[9144588000, 7.805870056152344],
[9144588666, 6.328269958496094],
[9144589208, 4.850669860839844],
[9144589666, 3.3730697631835938],
[9144590166, 1.7329940795898438],
[9144591041, 1.8272371292114258],
[9144591583, 3.350094795227051],
[9157166875, 5.031651496887207],
[9167322000, 6.979809761047363],
[9178107666, 9.249653816223145],
[9193995375, 11.206387519836426],
[9193996250, 9.643887519836426],
[9193996750, 12.387249946594238],
[9193997208, 10.637249946594238],
[9193997625, 13.7273530960083],
[9193998125, 11.7586030960083],
[9201045833, 15.238903999328613],
[9201046416, 13.020153999328613],
[9207333916, 11.542561531066895],
[9207334500, 10.064961433410645],
[9207334916, 8.587361335754395],
[9207335333, 7.1097612380981445],
[9207335750, 5.6321611404418945],
[9207336291, 1.7067461013793945],
[9207336791, 1.8009891510009766],
[9238707208, 3.331697463989258],
[9238707750, 3.42594051361084],
[9249850375, 4.982527732849121],
[9258133916, 3.504927635192871],
[9258134750, 1.649947166442871],
[9258135333, 1.7441902160644531],
[9258135791, 3.274402618408203],
[9268503083, 4.955989837646484],
[9276179833, 6.904178619384766],
[9291071750, 9.173992156982422],
[9302416208, 7.696392059326172],
[9302418125, 6.218791961669922],
[9302418625, 4.741191864013672],
[9302419083, 3.263591766357422],
[9302419541, 1.6234855651855469],
[9302420083, 1.717728614807129],
[9302420541, 3.240616798400879],
[9311149375, 4.92214298248291],
[9320641333, 6.870331764221191],
[9331269291, 9.140175819396973],
[9338272375, 11.096909523010254],
[9338273166, 9.534409523010254],
[9352655916, 12.27779483795166],
[9352656666, 10.52779483795166],
[9352657125, 13.617959022521973],
[9352657791, 11.649209022521973],
[9360048583, 15.129448890686035],
[9360049708, 12.910698890686035],
[9360050166, 11.433106422424316],
[9360050583, 9.955506324768066],
[9360051000, 8.477906227111816],
[9360051416, 7.000306129455566],
[9360051875, 5.522706031799316],
[9360052541, 1.5973520278930664],
[9360053000, 1.6915950775146484],
[9393342583, 3.2223033905029297],
[9393343250, 3.3165464401245117],
[9409339541, 4.873133659362793],
[9409340791, 3.395533561706543],
[9409341416, 1.540553092956543],
[9409341875, 1.634796142578125],
[9409342375, 3.16497802734375],
[9416166583, 4.847198486328125],
[9432210791, 6.795356750488281],
[9444122125, 9.065200805664062],
[9455910083, 7.5876007080078125],
[9455910916, 6.1100006103515625],
[9455911416, 4.6324005126953125],
[9455911875, 3.1548004150390625],
[9455912416, 1.5147247314453125],
[9455913041, 1.6089677810668945],
[9455913541, 3.1318254470825195],
[9464773416, 4.813382148742676],
[9472788916, 6.761570930480957],
[9479085458, 9.031384468078613],
[9500765833, 10.98808765411377],
[9500766791, 9.42558765411377],
[9500767375, 12.168950080871582],
[9500768000, 10.418950080871582],
[9500768458, 13.509053230285645],
[9500769041, 11.540303230285645],
[9513719333, 15.020604133605957],
[9513720541, 12.801854133605957],
[9513721083, 11.324261665344238],
[9513721500, 9.846661567687988],
[9513721916, 8.369061470031738],
[9513722333, 6.891461372375488],
[9513722791, 5.413861274719238],
[9513723416, 1.4884462356567383],
[9513723875, 1.5826892852783203],
[9542839416, 3.1133060455322266],
[9542839958, 3.2075490951538086],
[9556591166, 4.76413631439209],
[9564732750, 3.28653621673584],
[9564733333, 1.4315252304077148],
[9564733916, 1.5257682800292969],
[9564734375, 3.056011199951172],
[9575086208, 4.737567901611328],
[9585684958, 6.685756683349609],
[9597604875, 8.95560073852539],
[9609045333, 7.478000640869141],
[9609046000, 6.000400543212891],
[9609046500, 4.522800445556641],
[9609046958, 3.0452003479003906],
[9609047458, 1.4051246643066406],
[9609048125, 1.4993677139282227],
[9609048583, 3.0222253799438477],
[9624223125, 4.703782081604004],
[9624223583, 6.651970863342285],
[9634509041, 8.921784400939941],
[9647052875, 10.878487586975098],
[9647053666, 9.315987586975098],
[9647054125, 12.059319496154785],
[9647054625, 10.309319496154785],
[9657360666, 13.399453163146973],
[9657361250, 11.430703163146973],
[9666868541, 14.91097354888916],
[9666869416, 12.69222354888916],
[9666869958, 11.214631080627441],
[9666870375, 9.737030982971191],
[9666870833, 8.259430885314941],
[9666871291, 6.781830787658691],
[9666871708, 5.304230690002441],
[9666872375, 1.3788461685180664],
[9666872875, 1.4730892181396484],
[9700382000, 3.0036983489990234],
[9700382708, 3.0979413986206055],
[9709375041, 4.654559135437012],
[9717553291, 3.1769590377807617],
[9717554083, 1.3219785690307617],
[9717554583, 1.4162216186523438],
[9717555041, 2.9464340209960938],
[9726163458, 4.628021240234375],
[9732437708, 6.576179504394531],
[9749526583, 8.846023559570312],
[9755947583, 7.3684234619140625],
[9755948458, 5.8908233642578125],
[9755949000, 4.4132232666015625],
[9755949458, 2.9356231689453125],
[9755949916, 1.2955169677734375],
[9755950500, 1.3897600173950195],
[9761915666, 2.9126176834106445],
[9770365000, 4.594204902648926],
[9776642458, 6.542363166809082],
[9791085541, 8.812176704406738],
[9806946000, 10.76891040802002],
[9806946958, 9.20641040802002],
[9806947500, 11.949772834777832],
[9806948041, 10.199772834777832],
[9806948541, 13.289875984191895],
[9806949125, 11.321125984191895],
[9816190458, 14.801426887512207],
[9816191208, 12.582676887512207],
[9831386791, 11.105084419250488],
[9831387625, 9.627484321594238],
[9831388041, 8.149884223937988],
[9831388416, 6.672284126281738],
[9831388875, 5.194684028625488],
[9831389416, 1.2692689895629883],
[9831390000, 1.3635120391845703],
[9849533083, 2.894113540649414],
[9849533750, 2.988356590270996],
[9860013000, 4.544974327087402],
[9877544833, 3.0673742294311523],
[9877545541, 1.2123632431030273],
[9877546083, 1.3066062927246094],
[9877546541, 2.8368492126464844],
[9877547000, 4.518405914306641],
[9898580875, 6.466564178466797],
[9898581458, 8.736408233642578],
[9909517291, 7.258808135986328],
[9909518208, 5.781208038330078],
[9909518791, 4.303607940673828],
[9909519291, 2.826007843017578],
[9909519791, 1.1859016418457031],
[9909520333, 1.2801446914672852],
[9916724375, 2.80300235748291],
[9924695875, 4.484589576721191],
[9932870000, 6.432778358459473],
[9939150125, 8.702591896057129],
[9960538166, 10.659295082092285],
[9960539250, 9.096795082092285],
[9960539750, 11.840157508850098],
[9960540291, 10.090157508850098],
[9960540708, 13.18026065826416],
[9960541250, 11.21151065826416],
[9967833500, 14.691811561584473],
[9967834083, 12.473061561584473],
[9974130791, 10.995469093322754],
[9974131666, 9.517868995666504],
[9974132125, 8.040268898010254],
[9974132666, 6.562668800354004],
[9974133250, 5.085068702697754],
[9974134291, 1.159653663635254],
[9974134833, 1.253896713256836],
[10003724916, 2.784605026245117],
[10003725541, 2.878848075866699],
[10015714541, 4.4354658126831055],
[10022002000, 2.9578657150268555],
[10022002791, 1.1028547286987305],
[10022003500, 1.1970977783203125],
[10022003916, 2.7273101806640625],
[10034558833, 4.408866882324219],
[10051390166, 6.3570556640625],
[10051390833, 8.626899719238281],
[10068880875, 7.149299621582031],
[10068881583, 5.671699523925781],
[10068882083, 4.194099426269531],
[10068882541, 2.7164993286132812],
[10068883000, 1.0763931274414062],
[10068883541, 1.1706361770629883],
[10068884000, 2.6934938430786133],
[10077669166, 4.3750505447387695],
[10087131250, 6.323239326477051],
[10097712458, 8.593083381652832],
[10107286333, 10.549817085266113],
[10107287333, 8.987317085266113],
[10107287833, 11.7306489944458],
[10107288333, 9.9806489944458],
[10116212041, 13.070889472961426],
[10116212666, 11.102139472961426],
[10126699875, 14.582409858703613],
[10126700791, 12.363659858703613],
[10126701208, 10.886067390441895],
[10126701666, 9.408467292785645],
[10126702125, 7.9308671951293945],
[10126702541, 6.4532670974731445],
[10126702958, 4.9756669998168945],
[10126703708, 1.0502824783325195],
[10126704125, 1.1445255279541016],
[10166647541, 2.675233840942383],
[10166648208, 2.769476890563965],
[10166648666, 4.326094627380371],
[10176167000, 2.848494529724121],
[10176167666, 0.9934835433959961],
[10176168208, 1.0877265930175781],
[10176168625, 2.617938995361328],
[10187814625, 4.299495697021484],
[10204751625, 6.247684478759766],
[10204752416, 8.517528533935547],
[10228380750, 7.039928436279297],
[10228381458, 5.562328338623047],
[10228381958, 4.084728240966797],
[10228382416, 2.607128143310547],
[10228382875, 0.9670219421386719],
[10228383583, 1.061264991760254],
[10228384166, 2.584122657775879],
[10228384625, 4.265679359436035],
[10240192208, 6.213837623596191],
[10247060500, 8.483681678771973],
[10259651416, 10.440384864807129],
[10259652416, 8.877884864807129],
[10272064375, 11.621216773986816],
[10272065166, 9.871216773986816],
[10272065708, 12.961380958557129],
[10272066208, 10.992630958557129],
[10280281166, 14.472870826721191],
[10280282375, 12.254120826721191],
[10280283000, 10.776528358459473],
[10280283458, 9.298928260803223],
[10280283958, 7.821328163146973],
[10280284500, 6.343728065490723],
[10280284958, 4.866127967834473],
[10280285750, 0.9407129287719727],
[10280286250, 1.0349559783935547],
[10309488333, 2.5655269622802734],
[10309489000, 2.6597700119018555],
[10322070125, 4.216357231140137],
[10343421625, 2.7387571334838867],
[10343422291, 0.8837461471557617],
[10343422833, 0.9779891967773438],
[10343423291, 2.5082015991210938],
[10343423666, 4.189788818359375],
[10351887750, 6.137947082519531],
[10363843500, 8.407791137695312],
[10375241208, 6.9301910400390625],
[10375241833, 5.4525909423828125],
[10375242291, 3.9749908447265625],
[10375242750, 2.4973907470703125],
[10375243208, 0.8573150634765625],
[10375243791, 0.9515581130981445],
[10375244250, 2.4744157791137695],
[10383930875, 4.155972480773926],
[10390735458, 6.104161262512207],
[10403265458, 8.373974800109863],
[10413502875, 10.33067798614502],
[10413503708, 8.76817798614502],
[10413506291, 11.511540412902832],
[10413506916, 9.761540412902832],
[10425544375, 12.851696968078613],
[10425545166, 10.882946968078613],
[10431808500, 14.363247871398926],
[10431809333, 12.144497871398926],
[10431809833, 10.666905403137207],
[10431810250, 9.189305305480957],
[10431810708, 7.711705207824707],
[10431811125, 6.234105110168457],
[10431811541, 4.756505012512207],
[10431812291, 0.831089973449707],
[10431812750, 0.9253330230712891],
[10463712625, 2.455934524536133],
[10463713166, 2.550177574157715],
[10475260291, 4.106764793395996],
[10483372833, 2.629164695739746],
[10483373458, 0.7741842269897461],
[10483373916, 0.8684272766113281],
[10483374333, 2.398639678955078],
[10493672416, 4.080226898193359],
[10501161541, 6.028415679931641],
[10516115541, 8.298229217529297],
[10527499666, 6.820629119873047],
[10527500291, 5.343029022216797],
[10527500791, 3.865428924560547],
[10527501250, 2.387828826904297],
[10527501708, 0.7477226257324219],
[10527502208, 0.8419656753540039],
[10527502625, 2.364853858947754],
[10542499958, 4.046380043029785],
[10542500416, 5.994568824768066],
[10551164666, 8.264382362365723],
[10565689666, 10.221085548400879],
[10565690375, 8.658585548400879],
[10565690875, 11.401917457580566],
[10565691375, 9.651917457580566],
[10576163750, 12.742051124572754],
[10576164541, 10.773301124572754],
[10585149041, 14.253571510314941],
[10585150291, 12.034821510314941],
[10585150833, 10.557229042053223],
[10585151250, 9.079628944396973],
[10585151625, 7.602028846740723],
[10585152083, 6.124428749084473],
[10585152458, 4.646828651428223],
[10585153125, 0.7214136123657227],
[10585153583, 0.8156566619873047],
[10613971583, 2.346220016479492],
[10613972125, 2.440463066101074],
[10627735958, 3.9970502853393555],
[10635842500, 2.5194501876831055],
[10635843208, 0.6644392013549805],
[10635843750, 0.7586822509765625],
[10635844166, 2.2888946533203125],
[10646196250, 3.9704818725585938],
[10656749583, 5.918670654296875],
[10663702916, 8.188514709472656],
[10679887958, 6.710914611816406],
[10679888708, 5.233314514160156],
[10679889208, 3.7557144165039062],
[10679889708, 2.2781143188476562],
[10679890250, 0.6380081176757812],
[10679890791, 0.7322511672973633],
[10679891250, 2.2551088333129883],
[10694783708, 3.9366350173950195],
[10694784333, 5.884823799133301],
[10707463208, 8.154637336730957],
[10718126000, 10.111371040344238],
[10718126708, 8.548871040344238],
[10718127208, 11.292202949523926],
[10718127750, 9.542202949523926],
[10736498291, 12.632336616516113],
[10736499250, 10.663586616516113],
[10736499750, 14.143887519836426],
[10736500208, 11.925137519836426],
[10736500666, 10.447545051574707],
[10736501083, 8.969944953918457],
[10736501541, 7.492344856262207],
[10736502000, 6.014744758605957],
[10736502458, 4.537144660949707],
[10736503291, 0.611699104309082],
[10736503750, 0.7059421539306641],
[10767831666, 2.236543655395508],
[10767832250, 2.33078670501709],
[10779920500, 3.887373924255371],
[10788054500, 2.409773826599121],
[10788055250, 0.5547933578491211],
[10788055875, 0.6490364074707031],
[10788056250, 2.179248809814453],
[10804901166, 3.8608360290527344],
[10804901833, 5.809024810791016],
[10816462125, 8.078838348388672],
[10840265666, 6.601238250732422],
[10840266583, 5.123638153076172],
[10840267125, 3.646038055419922],
[10840267541, 2.168437957763672],
[10840268000, 0.5283622741699219],
[10840268708, 0.6226053237915039],
[10840269166, 2.145462989807129],
[10840269583, 3.827019691467285],
[10849606833, 5.775177955627441],
[10860018500, 8.045022010803223],
[10872590291, 10.001725196838379],
[10872591375, 8.439225196838379],
[10872592041, 11.182557106018066],
[10872592625, 9.432557106018066],
[10882912958, 12.522690773010254],
[10882913541, 10.553940773010254],
[10905067375, 14.034211158752441],
[10905068541, 11.815461158752441],
[10905069000, 10.337868690490723],
[10905069375, 8.860268592834473],
[10905069791, 7.382668495178223],
[10905070166, 5.905068397521973],
[10905070666, 4.427468299865723],
[10905071208, 0.5020837783813477],
[10905071708, 0.5963268280029297],
[10926136041, 2.1269893646240234],
[10926136833, 2.2212324142456055],
[10935084916, 3.7778501510620117],
[10943143166, 2.3002500534057617],
[10943143833, 0.4452695846557617],
[10943144416, 0.5395126342773438],
[10943144916, 2.0697250366210938],
[10949582291, 3.751312255859375],
[10961032250, 5.699501037597656],
[10976159166, 7.9693145751953125],
[10982949875, 6.4917144775390625],
[10982951041, 5.0141143798828125],
[10982951625, 3.5365142822265625],
[10982952083, 2.0589141845703125],
[10982952541, 0.4188385009765625],
[10982953416, 0.5130815505981445],
[10982953916, 2.0359392166137695],
[10993334500, 3.717495918273926],
[11003763708, 5.665684700012207],
[11016290958, 7.935528755187988],
[11026686333, 9.892231941223145],
[11026687208, 8.329731941223145],
[11026687708, 11.073094367980957],
[11026688250, 9.323094367980957],
[11037190458, 12.413228034973145],
[11037191125, 10.444478034973145],
[11046139541, 13.924748420715332],
[11046141041, 11.705998420715332],
[11046141541, 10.228405952453613],
[11046141958, 8.750805854797363],
[11046142458, 7.273205757141113],
[11046142875, 5.795605659484863],
[11046143291, 4.318005561828613],
[11046144000, 0.3925905227661133],
[11046144541, 0.4868335723876953],
[11075593125, 2.017404556274414],
[11075593875, 2.111647605895996],
[11088155583, 3.6682348251342773],
[11096832666, 2.1906347274780273],
[11096833291, 0.33562374114990234],
[11096833791, 0.4298667907714844],
[11096834208, 1.9600791931152344],
[11107363458, 3.6416664123535156],
[11118512041, 5.589855194091797],
[11130513458, 7.859699249267578],
[11142087416, 6.382099151611328],
[11142088083, 4.904499053955078],
[11142088583, 3.426898956298828],
[11142089000, 1.9492988586425781],
[11142089500, 0.3092231750488281],
[11142090083, 0.40346622467041016],
[11142090500, 1.9263238906860352],
[11157117583, 3.6078805923461914],
[11157118291, 5.556069374084473],
[11166255375, 7.825882911682129],
[11176655125, 9.78261661529541],
[11176656083, 8.22011661529541],
[11192574375, 10.963448524475098],
[11192575166, 9.213448524475098],
[11192575666, 12.30361270904541],
[11192576166, 10.33486270904541],
[11199870500, 13.815102577209473],
[11199871625, 11.596352577209473],
[11199872208, 10.118760108947754],
[11199872708, 8.641160011291504],
[11199873166, 7.163559913635254],
[11199873666, 5.685959815979004],
[11199874125, 4.208359718322754],
[11199874791, 0.2829751968383789],
[11199875250, 0.37721824645996094],
[11232939625, 1.9078807830810547],
[11232940375, 2.0021238327026367],
[11242617708, 3.558711051940918],
[11257045333, 2.081110954284668],
[11257046333, 0.22613048553466797],
[11257046875, 0.32037353515625],
[11257047333, 1.8505859375],
[11257047750, 3.5321731567382812],
[11266258666, 5.4803314208984375],
[11283567833, 7.750144958496094],
[11290265000, 6.272544860839844],
[11290265708, 4.794944763183594],
[11290266208, 3.3173446655273438],
[11290266708, 1.8397445678710938],
[11290267125, 0.19966888427734375],
[11290267791, 0.2939119338989258],
[11290268208, 1.8167695999145508],
[11301162875, 3.498326301574707],
[11307442333, 5.446484565734863],
[11323840250, 7.7162981033325195],
[11339670916, 9.6730318069458],
[11339671875, 8.1105318069458],
[11339672458, 10.853894233703613],
[11339673000, 9.103894233703613],
[11339673541, 12.193997383117676],
[11339674041, 10.225247383117676],
[11351273708, 13.705548286437988],
[11351274500, 11.486798286437988],
[11351275125, 10.00920581817627],
[11351275666, 8.53160572052002],
[11351276166, 7.0540056228637695],
[11351276708, 5.5764055252075195],
[11351277208, 4.0988054275512695],
[11351278041, 0.17339038848876953],
[11363950708, 0.26763343811035156],
[11384779166, 1.7982349395751953],
[11384779750, 1.8924779891967773],
[11391129166, 3.4490652084350586],
[11397362208, 1.9714651107788086],
[11397362958, 0.1164541244506836],
[11397363541, 0.21069717407226562],
[11403666916, 1.7409095764160156],
[11409927125, 3.422496795654297],
[11425555583, 5.370685577392578],
[11438270208, 7.640529632568359],
[11459207791, 6.162929534912109],
[11459210500, 4.685329437255859],
[11459212250, 3.2077293395996094],
[11459213750, 1.7301292419433594],
[11459215458, 0.09005355834960938],
[11459217500, 0.1842966079711914],
[11459219166, 1.7071542739868164],
[11459220750, 3.3887109756469727],
[11479406541, 5.336899757385254],
[11497716500, 7.60671329498291],
[11514436791, 9.563446998596191],
[11514438333, 8.000946998596191],
[11525424250, 10.744309425354004],
[11525425333, 8.994309425354004],
[11531655458, 12.084473609924316],
[11531656458, 10.115723609924316],
[11545962583, 13.595993995666504],
[11545963708, 11.377243995666504],
[11545964166, 9.899651527404785],
[11545964583, 8.422051429748535],
[11545965000, 6.944451332092285],
[11545965333, 5.466851234436035],
[11545965750, 3.989251136779785],
[11545966375, 0.06386661529541016],
[11545966791, 0.1581096649169922],
[11573768708, 1.6887569427490234],
[11573769541, 1.7829999923706055],
[11582842250, 3.3396177291870117],
[11591298958, 1.8620176315307617],
[11591299833, 0.007037162780761719],
[11591300500, 0.10128021240234375],
[11591300916, 1.6314926147460938],
[11602014083, 3.313079833984375],
[11608265208, 5.261268615722656],
[11622095125, 7.5311126708984375],
[11637128125, 6.0535125732421875],
[11637128958, 4.5759124755859375],
[11637129458, 3.0983123779296875],
[11637129916, 1.6207122802734375],
[11637130583, 0],
[11637131416, 0.09424304962158203],
[11637131916, 1.617100715637207],
[11646075875, 3.2986268997192383],
[11655687208, 5.2468156814575195],
[11666417000, 7.516659736633301],
[11676156041, 9.474095344543457],
[11676157083, 7.911595344543457],
[11676157750, 10.654927253723145],
[11676158333, 8.904927253723145],
[11684474833, 11.99516773223877],
[11684475750, 10.02641773223877],
[11694942500, 13.506688117980957],
[11694943833, 11.287938117980957],
[11694944375, 9.810345649719238],
[11694944833, 8.332745552062988],
[11694948625, 6.855145454406738],
[11694949083, 5.377545356750488],
[11694949583, 3.8999452590942383],
[11694950375, 0],
[11701325291, 0.09424304962158203],
[11737127416, 1.6248445510864258],
[11737128166, 1.7190876007080078],
[11737128583, 3.275705337524414],
[11747069458, 1.798105239868164],
[11747070708, 0],
[11747071541, 0.09424304962158203],
[11747072041, 1.624455451965332],
[11758414458, 3.3060121536254883],
[11769110875, 5.2542009353637695],
[11781372000, 7.524044990539551],
[11793048791, 6.046444892883301],
[11793049541, 4.568844795227051],
[11793050083, 3.091244697570801],
[11793050541, 1.6136445999145508],
[11793051208, 0],
[11793051916, 0.09424304962158203],
[11793052416, 1.617100715637207],
[11801807541, 3.2986574172973633],
[11809489958, 5.2468461990356445],
[11815788833, 7.516659736633301],
[11837611875, 9.473362922668457],
[11837612958, 7.910862922668457],
[11837613500, 10.65422534942627],
[11837614000, 8.90422534942627],
[11837614458, 11.994328498840332],
[11837614916, 10.025578498840332],
[11849383583, 13.505879402160645],
[11849384833, 11.287129402160645],
[11849385375, 9.809536933898926],
[11849385833, 8.331936836242676],
[11849386333, 6.854336738586426],
[11849386791, 5.376736640930176],
[11849387250, 3.899136543273926],
[11849388000, 0],
[11855799125, 0.09424304962158203],
[11882959291, 1.6248445510864258],
[11882960000, 1.7190876007080078],
[11893305375, 3.275705337524414],
[11907861000, 1.798105239868164],
[11907861958, 0],
[11907862625, 0.09424304962158203],
[11907863166, 1.624455451965332],
[11907863583, 3.3060426712036133],
[11916294791, 5.2542009353637695],
[11934470500, 7.524044990539551],
[11945975291, 6.046444892883301],
[11945976041, 4.568844795227051],
[11945976541, 3.091244697570801],
[11945976958, 1.6136445999145508],
[11945977666, 0],
[11945978375, 0.09424304962158203],
[11945978833, 1.617100715637207],
[11954876958, 3.2986574172973633],
[11964166958, 5.2468461990356445],
[11971817958, 7.516690254211426],
[11984355791, 9.473393440246582],
[11984356541, 7.910893440246582],
[11984357000, 10.65422534942627],
[11984357541, 8.90422534942627],
[11993305291, 11.994359016418457],
[11993305916, 10.025609016418457],
[11999586541, 13.505879402160645],
[11999587166, 11.287129402160645],
[12005901000, 9.809536933898926],
[12005901791, 8.331936836242676],
[12005902250, 6.854336738586426],
[12005902666, 5.376736640930176],
[12005903083, 3.899136543273926],
[12005903958, 0],
[12005904583, 0.09424304962158203],
[12037360208, 1.6248979568481445],
[12037360791, 1.7191410064697266],
[12046404541, 3.275758743286133],
[12054500041, 1.7981586456298828],
[12054500750, 0],
[12054501291, 0.09424304962158203],
[12054501708, 1.624455451965332],
[12063257541, 3.3060426712036133],
[12074136000, 5.2542314529418945],
[12084477416, 7.524075508117676],
[12094917541, 6.046475410461426],
[12094918250, 4.568875312805176],
[12094918791, 3.091275215148926],
[12094919333, 1.6136751174926758],
[12094919875, 0],
[12094920583, 0.09424304962158203],
[12094921041, 1.617100715637207],
[12107394583, 3.2986268997192383],
[12123027083, 5.2468156814575195],
[12123027625, 7.516659736633301],
[12142991583, 9.473362922668457],
[12142992458, 7.910862922668457],
[12142993041, 10.65422534942627],
[12142993583, 8.90422534942627],
[12142994041, 11.994328498840332],
[12142994583, 10.025578498840332],
[12156171708, 13.505879402160645],
[12156172916, 11.287129402160645],
[12156173500, 9.809536933898926],
[12156173958, 8.331936836242676],
[12156174500, 6.854336738586426],
[12156174958, 5.376736640930176],
[12156175500, 3.899136543273926],
[12156176458, 0],
[12156176958, 0.09424304962158203],
[12184469083, 1.6248140335083008],
[12184469708, 1.7190570831298828],
[12196993625, 3.275674819946289],
[12203325958, 1.798074722290039],
[12203326666, 0],
[12203327250, 0.09424304962158203],
[12203327708, 1.624455451965332],
[12217593833, 3.306065559387207],
[12229393375, 5.254254341125488],
[12249104583, 7.5240983963012695],
[12249106208, 6.0464982986450195],
[12249106791, 4.5688982009887695],
[12249107208, 3.0912981033325195],
[12249107583, 1.6136980056762695],
[12249108041, 0],
[12249108541, 0.09424304962158203],
[12255297458, 1.617100715637207],
[12263781750, 3.2986574172973633],
[12273487416, 5.247906684875488],
[12284248750, 7.517926216125488],
[12294003791, 9.47465991973877],
[12294004916, 7.9121599197387695],
[12294005458, 10.655491828918457],
[12294006000, 8.905491828918457],
[12306503666, 11.995732307434082],
[12306504750, 10.026982307434082],
[12312782416, 13.507283210754395],
[12312783750, 11.288533210754395],
[12312784291, 9.810940742492676],
[12312784708, 8.333340644836426],
[12312785125, 6.855740547180176],
[12312785583, 5.378140449523926],
[12312786000, 3.900540351867676],
[12312786791, 0],
[12312787541, 0.09424304962158203],
[12343368750, 1.6248292922973633],
[12343369666, 1.7190723419189453],
[12353690125, 3.2756900787353516],
[12366374458, 1.7980899810791016],
[12366375750, 0],
[12366376583, 0.09424304962158203],
[12366377083, 1.624455451965332],
[12376683750, 3.3060426712036133],
[12383007958, 5.2542009353637695],
[12399666166, 7.524044990539551],
[12412253000, 6.046444892883301],
[12412253750, 4.568844795227051],
[12412254250, 3.091244697570801],
[12412255041, 1.6136445999145508],
[12412255583, 0],
[12412256125, 0.09424304962158203],
[12412256625, 1.617100715637207],
[12420498041, 3.2986574172973633],
[12430566583, 5.2468156814575195],
[12441197375, 7.516659736633301],
[12456966166, 9.473393440246582],
[12456967041, 7.910893440246582],
[12456967625, 10.654255867004395],
[12456968208, 8.904255867004395],
[12456968708, 11.994412422180176],
[12456969291, 10.025662422180176],
[12468587666, 13.505963325500488],
[12468588375, 11.287213325500488],
[12468588916, 9.80962085723877],
[12468589375, 8.33202075958252],
[12468589916, 6.8544206619262695],
[12468590416, 5.3768205642700195],
[12468590958, 3.8992204666137695],
[12468591833, 0],
[12475001916, 0.09424304962158203],
[12501159916, 1.6248598098754883],
[12501160791, 1.7191028594970703],
[12519035875, 3.2756900787353516],
[12519037125, 1.7980899810791016],
[12519037750, 0],
[12519038375, 0.09424304962158203],
[12519038791, 1.624424934387207],
[12531292833, 3.3060121536254883],
[12541779750, 5.2542009353637695],
[12553646125, 7.524044990539551],
[12565095625, 6.046444892883301],
[12565096333, 4.568844795227051],
[12565096833, 3.091244697570801],
[12565097250, 1.6136445999145508],
[12565097791, 0],
[12565098375, 0.09424304962158203],
[12565098833, 1.617100715637207],
[12573886875, 3.2986574172973633],
[12583134375, 5.2468461990356445],
[12589985583, 7.516690254211426],
[12602700791, 9.473393440246582],
[12602701750, 7.910893440246582],
[12602702208, 10.65422534942627],
[12602702708, 8.90422534942627],
[12615074500, 11.994389533996582],
[12615075125, 10.025639533996582],
[12622630583, 13.50590991973877],
[12622631750, 11.28715991973877],
[12622632333, 9.80956745147705],
[12622632750, 8.3319673538208],
[12622633208, 6.854367256164551],
[12622633625, 5.376767158508301],
[12622634041, 3.899167060852051],
[12622634958, 0],
[12622635541, 0.09424304962158203],
[12651152333, 1.6247835159301758],
[12651152958, 1.7190265655517578],
[12663168166, 3.275644302368164],
[12669433291, 1.798044204711914],
[12669434083, 0],
[12669434708, 0.09424304962158203],
[12669435208, 1.624455451965332],
[12683717458, 3.306065559387207],
[12694430708, 5.254254341125488],
[12712884958, 7.5240983963012695],
[12712886125, 6.0464982986450195],
[12712886666, 4.5688982009887695],
[12712887166, 3.0912981033325195],
[12712887583, 1.6136980056762695],
[12712888083, 0],
[12712888583, 0.09424304962158203],
[12712889000, 1.617100715637207],
[12726883916, 3.2986268997192383],
[12736323583, 5.2468156814575195],
[12742813041, 7.516659736633301],
[12755357125, 9.473362922668457],
[12755357875, 7.910862922668457],
[12761630541, 10.654194831848145],
[12761631375, 8.904194831848145],
[12767874833, 11.994359016418457],
[12767875500, 10.025609016418457],
[12788592583, 13.505879402160645],
[12788593666, 11.287129402160645],
[12788594125, 9.809536933898926],
[12788594583, 8.331936836242676],
[12788595000, 6.854336738586426],
[12788595375, 5.376736640930176],
[12788595791, 3.899136543273926],
[12788596458, 0],
[12788596958, 0.09424304962158203],
[12815932416, 1.6249208450317383],
[12815933000, 1.7191638946533203],
[12815933416, 3.2757816314697266],
[12826637333, 1.7981815338134766],
[12826638083, 0],
[12826638750, 0.09424304962158203],
[12826639250, 1.624455451965332],
[12833008041, 3.3060426712036133],
[12843308250, 5.2542314529418945],
[12859610541, 7.524044990539551],
[12866371083, 6.046444892883301],
[12866371750, 4.568844795227051],
[12866372291, 3.091244697570801],
[12866372791, 1.6136445999145508],
[12866373333, 0],
[12866374083, 0.09424304962158203],
[12866374583, 1.617100715637207],
[12877735375, 3.2986574172973633],
[12884009875, 5.2468156814575195],
[12899731625, 7.516629219055176],
[12915533458, 9.473362922668457],
[12915534416, 7.910862922668457],
[12915534916, 10.65422534942627],
[12915535458, 8.90422534942627],
[12915535916, 11.994328498840332],
[12915536458, 10.025578498840332],
[12924178041, 13.505879402160645],
[12924178708, 11.287129402160645],
[12939773083, 9.809536933898926],
[12939773958, 8.331936836242676],
[12939774416, 6.854336738586426],
[12939774833, 5.376736640930176],
[12939775250, 3.899136543273926],
[12939776083, 0],
[12939776750, 0.09424304962158203],
],
};
================================================
FILE: scalene/scalene-gui/gemini.ts
================================================
interface GeminiErrorResponse {
error?: {
code?: number;
message?: string;
status?: string;
};
}
interface GeminiContentPart {
text: string;
}
interface GeminiContent {
parts: GeminiContentPart[];
role: string;
}
interface GeminiCandidate {
content: GeminiContent;
}
interface GeminiResponse extends GeminiErrorResponse {
candidates?: GeminiCandidate[];
}
interface GeminiModelInfo {
name: string;
displayName: string;
supportedGenerationMethods: string[];
}
interface GeminiModelsResponse extends GeminiErrorResponse {
models?: GeminiModelInfo[];
}
export async function sendPromptToGemini(
prompt: string,
apiKey: string
): Promise {
// Check for custom URL override (for Gemini-compatible servers)
const customUrlElement = document.getElementById("gemini-custom-url") as HTMLInputElement | null;
const customUrl = customUrlElement?.value?.trim() || "";
// Check for custom model override
const customModelElement = document.getElementById("gemini-custom-model") as HTMLInputElement | null;
const customModel = customModelElement?.value?.trim() || "";
const modelElement = document.getElementById("language-model-gemini") as HTMLSelectElement | null;
const model = customModel || modelElement?.value || "gemini-2.0-flash";
// Construct endpoint URL
const baseUrl = customUrl || "https://generativelanguage.googleapis.com/v1beta";
const endpoint = `${baseUrl}/models/${model}:generateContent?key=${apiKey}`;
const body = JSON.stringify({
contents: [
{
parts: [
{
text: prompt,
},
],
},
],
systemInstruction: {
parts: [
{
text: "You are a Python programming assistant who ONLY responds with blocks of commented, optimized code. You never respond with text. Just code, starting with ``` and ending with ```.",
},
],
},
generationConfig: {
temperature: 0.3,
maxOutputTokens: 4096,
},
});
console.log(body);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: body,
});
const data: GeminiResponse = await response.json();
if (data.error) {
console.error("Gemini API error:", data.error);
if (data.error.status === "INVALID_ARGUMENT" || data.error.code === 400) {
alert(`Gemini API error: ${data.error.message || "Invalid request"}`);
} else if (data.error.status === "UNAUTHENTICATED" || data.error.code === 401) {
alert("Invalid Gemini API key. Please check your API key and try again.");
} else if (data.error.status === "RESOURCE_EXHAUSTED" || data.error.code === 429) {
alert("Rate limit exceeded. Please wait a moment and try again.");
} else {
alert(`Gemini API error: ${data.error.message || "Unknown error"}`);
}
return "";
}
try {
if (data.candidates && data.candidates[0] && data.candidates[0].content) {
const text = data.candidates[0].content.parts
.map((part) => part.text)
.join("");
console.log(
`Debugging info: Retrieved ${JSON.stringify(data.candidates[0], null, 4)}`
);
return text.replace(/^\s*[\r\n]/gm, "");
}
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
} catch {
return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
}
}
// Fetch available models from Gemini API
export async function fetchGeminiModels(apiKey: string): Promise {
if (!apiKey) return [];
// Check for custom URL
const customUrlElement = document.getElementById("gemini-custom-url") as HTMLInputElement | null;
const customUrl = customUrlElement?.value?.trim() || "";
const baseUrl = customUrl || "https://generativelanguage.googleapis.com/v1beta";
const endpoint = `${baseUrl}/models?key=${apiKey}`;
try {
const response = await fetch(endpoint, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const data: GeminiModelsResponse = await response.json();
if (data.error || !data.models) {
console.error("Failed to fetch Gemini models:", data.error);
return [];
}
// Filter for models that support generateContent and extract model ID
const chatModels = data.models
.filter((m) => m.supportedGenerationMethods?.includes("generateContent"))
.map((m) => m.name.replace("models/", ""))
.filter((id) => id.includes("gemini"))
.sort();
return chatModels;
} catch (error) {
console.error("Error fetching Gemini models:", error);
return [];
}
}
================================================
FILE: scalene/scalene-gui/gui-elements.ts
================================================
import { memory_consumed_str, time_consumed_str } from "./utils";
export const Lightning = "⚡"; // lightning bolt (for optimizing a line)
export const Explosion = "💥"; // explosion (for optimizing a region)
export const WhiteLightning = `${Lightning}`; // invisible but same width as lightning bolt
export const WhiteExplosion = `${Explosion}`; // invisible but same width as explosion
export const RightTriangle = "►"; // right-facing triangle symbol (collapsed view)
export const DownTriangle = "▼"; // downward-facing triangle symbol (expanded view)
// Type for chart parameters
export interface ChartParams {
width: number;
height: number;
}
// Type for profile data - extending globalThis
declare global {
interface Window {
profile?: {
elapsed_time_sec: number;
[key: string]: unknown;
};
}
// eslint-disable-next-line no-var
var profile: {
elapsed_time_sec: number;
max_footprint_mb: number;
growth_rate: number;
gpu: boolean;
gpu_device: string;
memory: boolean;
samples: Array<[number, number]>;
files: Record;
program?: string;
stacks?: unknown;
};
}
export interface LineProfile {
lineno: number;
line: string;
n_cpu_percent_python: number;
n_cpu_percent_c: number;
n_sys_percent: number;
n_gpu_percent: number;
n_gpu_peak_memory_mb: number;
n_peak_mb: number;
n_avg_mb: number;
n_python_fraction: number;
n_usage_fraction: number;
n_copy_mb_s: number;
n_copy_mb: number;
n_malloc_mb: number;
n_core_utilization: number;
memory_samples: Array<[number, number]>;
start_region_line: number;
end_region_line: number;
nrt_time_ms?: number;
nrt_percent?: number;
nc_time_ms?: number;
cpu_samples_nc_overlap_percent?: number;
}
export interface FileProfile {
lines: LineProfile[];
functions: LineProfile[];
imports: string[];
percent_cpu_time: number;
leaks?: Record;
}
function makeTooltip(title: string, value: number): string {
// Tooltip for time bars, below
const secs = (value / 100) * globalThis.profile.elapsed_time_sec;
return (
`(${title}) ` +
value.toFixed(1) +
"%" +
" [" +
time_consumed_str(secs * 1e3) +
"]"
);
}
export function makeBar(
python: number,
native: number,
system: number,
params: ChartParams
): object {
// Make a time bar
const widthThreshold1 = 20;
const widthThreshold2 = 10;
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
x: 0,
y: python.toFixed(1),
c: makeTooltip("Python", python),
d:
python >= widthThreshold1
? python.toFixed(0) + "%"
: python >= widthThreshold2
? python.toFixed(0)
: "",
q: python / 2,
},
{
x: 0,
y: native.toFixed(1),
c: makeTooltip("native", native),
d:
native >= widthThreshold1
? native.toFixed(0) + "%"
: native >= widthThreshold2
? native.toFixed(0)
: "",
q: python + native / 2,
},
{
x: 0,
y: system.toFixed(1),
c: makeTooltip("system", system),
d:
system >= widthThreshold1
? system.toFixed(0) + "%"
: system >= widthThreshold2
? system.toFixed(0)
: "",
q: python + native + system / 2,
},
],
},
layer: [
{
mark: { type: "bar" },
encoding: {
x: {
aggregate: "sum",
field: "y",
axis: false,
stack: "zero",
scale: { domain: [0, 100] },
},
color: {
field: "c",
type: "nominal",
legend: false,
scale: { range: ["darkblue", "#6495ED", "blue"] },
},
tooltip: [{ field: "c", type: "nominal", title: "time" }],
},
},
{
mark: {
type: "text",
align: "center",
baseline: "middle",
dx: 0,
},
encoding: {
x: {
aggregate: "sum",
field: "q",
axis: false,
},
text: { field: "d" },
color: { value: "white" },
tooltip: [{ field: "c", type: "nominal", title: "time" }],
},
},
],
};
}
export function makeAwaitPie(
await_pct: number,
params: ChartParams,
startAngle: number = 0
): object {
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
category: "await",
value: await_pct.toFixed(1),
c: "await: " + await_pct.toFixed(1) + "%",
},
{
category: "other",
value: (100 - await_pct).toFixed(1),
c: "",
},
],
},
mark: "arc",
encoding: {
theta: {
field: "value",
type: "quantitative",
scale: {
range: [startAngle, startAngle + 2 * Math.PI],
},
},
color: {
field: "category",
type: "nominal",
legend: false,
scale: {
domain: ["await", "other"],
range: ["darkcyan", "#e0f2f1"],
},
},
tooltip: [{ field: "c", type: "nominal", title: "await" }],
},
};
}
export function makeGPUPie(
util: number,
gpu_device: string,
params: ChartParams,
startAngle: number = 0
): object {
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
category: "in use",
value: util.toFixed(1),
c: "in use: " + util.toFixed(1) + "%",
},
{
category: "idle",
value: (100 - util).toFixed(1),
c: "",
},
],
},
mark: "arc",
encoding: {
theta: {
field: "value",
type: "quantitative",
scale: {
range: [startAngle, startAngle + 2 * Math.PI],
},
},
color: {
field: "category",
type: "nominal",
legend: false,
scale: {
domain: ["in use", "idle"],
range: ["goldenrod", "#f4e6c2"],
},
},
tooltip: [{ field: "c", type: "nominal", title: gpu_device }],
},
};
}
export function makeGPUBar(
util: number,
gpu_device: string,
params: ChartParams
): object {
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
x: 0,
y: util.toFixed(0),
q: (util / 2).toFixed(0),
d: util >= 20 ? util.toFixed(0) + "%" : "",
dd: "in use: " + util.toFixed(0) + "%",
},
],
},
layer: [
{
mark: { type: "bar" },
encoding: {
x: {
aggregate: "sum",
field: "y",
axis: false,
scale: { domain: [0, 100] },
},
color: {
field: "dd",
type: "nominal",
legend: false,
scale: { range: ["goldenrod", "#f4e6c2"] },
},
tooltip: [{ field: "dd", type: "nominal", title: gpu_device + ":" }],
},
},
{
mark: {
type: "text",
align: "center",
baseline: "middle",
dx: 0,
},
encoding: {
x: {
aggregate: "sum",
field: "q",
axis: false,
},
text: { field: "d" },
color: { value: "white" },
tooltip: [{ field: "dd", type: "nominal", title: gpu_device + ":" }],
},
},
],
};
}
export function makeMemoryPie(
native_mem: number,
python_mem: number,
params: { width: number }
): object {
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
width: params.width,
height: 20,
padding: 0,
data: {
values: [
{
category: 1,
value: native_mem.toFixed(1),
c: "native: " + native_mem.toFixed(1) + "%",
},
{
category: 2,
value: python_mem.toFixed(1),
c: "Python: " + python_mem.toFixed(1) + "%",
},
],
},
mark: "arc",
encoding: {
theta: {
field: "value",
type: "quantitative",
scale: { domain: [0, 100] },
},
color: {
field: "c",
type: "nominal",
legend: false,
scale: { range: ["darkgreen", "#50C878"] },
},
tooltip: [{ field: "c", type: "nominal", title: "memory" }],
},
};
}
export function makeMemoryBar(
memory: number | string,
_title: string,
python_percent: number,
total: number | string,
color: string,
params: ChartParams
): object {
const memoryNum = typeof memory === "string" ? parseFloat(memory) : memory;
const totalNum = typeof total === "string" ? parseFloat(total) : total;
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
x: 0,
y: python_percent * memoryNum,
c: "(Python) " + memory_consumed_str(python_percent * memoryNum),
d:
python_percent * memoryNum > totalNum * 0.2
? memory_consumed_str(python_percent * memoryNum)
: "",
q: (python_percent * memoryNum) / 2,
},
{
x: 0,
y: (1.0 - python_percent) * memoryNum,
c: "(native) " + memory_consumed_str((1.0 - python_percent) * memoryNum),
d:
(1.0 - python_percent) * memoryNum > totalNum * 0.2
? memory_consumed_str((1.0 - python_percent) * memoryNum)
: "",
q: python_percent * memoryNum + ((1.0 - python_percent) * memoryNum) / 2,
},
],
},
layer: [
{
mark: { type: "bar" },
encoding: {
x: {
aggregate: "sum",
field: "y",
axis: false,
scale: { domain: [0, totalNum] },
},
color: {
field: "c",
type: "nominal",
legend: false,
scale: { range: [color, "#50C878", "green"] },
},
},
},
{
mark: {
type: "text",
align: "center",
baseline: "middle",
dx: 0,
},
encoding: {
x: {
aggregate: "sum",
field: "q",
axis: false,
},
text: { field: "d" },
color: { value: "white" },
},
},
],
};
}
export function makeSparkline(
samples: Array<[number, number]>,
max_x: number,
max_y: number,
leak_velocity: number = 0,
params: ChartParams
): object {
const values = samples.map((v) => {
let leak_str = "";
if (leak_velocity != 0) {
leak_str = `; possible leak (${memory_consumed_str(leak_velocity)}/s)`;
}
return {
x: v[0],
y: v[1],
y_text:
memory_consumed_str(v[1]) +
" (@ " +
time_consumed_str(v[0] / 1e6) +
")" +
leak_str,
};
});
let leak_info = "";
let height = params.height;
if (leak_velocity != 0) {
leak_info = "possible leak";
height -= 10; // FIXME should be actual height of font
}
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
data: { values: values },
width: params.width,
height: height,
padding: 0,
title: {
text: leak_info,
baseline: "line-bottom",
color: "red",
offset: 0,
lineHeight: 10,
orient: "bottom",
fontStyle: "italic",
},
encoding: {
x: {
field: "x",
type: "quantitative",
title: "",
axis: {
tickCount: 10,
tickSize: 0,
labelExpr: "",
},
scale: {
domain: [0, max_x],
},
},
},
layer: [
{
encoding: {
y: {
field: "y",
type: "quantitative",
axis: null,
scale: {
domain: [0, max_y],
},
},
color: {
field: "c",
type: "nominal",
legend: null,
scale: {
range: ["darkgreen"],
},
},
},
layer: [
{ mark: "line" },
{
transform: [{ filter: { param: "hover", empty: false } }],
mark: "point",
},
],
},
{
mark: "rule",
encoding: {
opacity: {
condition: { value: 0.3, param: "hover", empty: false },
value: 0,
},
tooltip: [{ field: "y_text", type: "nominal", title: "memory" }],
},
params: [
{
name: "hover",
select: {
type: "point",
fields: ["y"],
nearest: true,
on: "mousemove",
},
},
],
},
],
};
}
export function makeNRTBar(
nrt_time_ms: number,
elapsed_time_sec: number,
params: ChartParams
): object {
const widthThreshold1 = 15;
const widthThreshold2 = 8;
const elapsed_time_ms = elapsed_time_sec * 1000;
const nrt_percent =
elapsed_time_ms > 0 ? (nrt_time_ms / elapsed_time_ms) * 100 : 0;
const tooltipText =
"NRT: " +
nrt_percent.toFixed(1) +
"% of elapsed time [" +
time_consumed_str(nrt_time_ms) +
"]";
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
x: 0,
y: nrt_percent.toFixed(1),
c: tooltipText,
d:
nrt_percent >= widthThreshold1
? nrt_percent.toFixed(0) + "%"
: nrt_percent >= widthThreshold2
? nrt_percent.toFixed(0)
: "",
q: nrt_percent / 2,
},
],
},
layer: [
{
mark: { type: "bar" },
encoding: {
x: {
aggregate: "sum",
field: "y",
axis: false,
stack: "zero",
scale: { domain: [0, 100] },
},
color: {
field: "c",
type: "nominal",
legend: false,
scale: { range: ["purple"] },
},
tooltip: [{ field: "c", type: "nominal", title: "NRT time" }],
},
},
{
mark: {
type: "text",
align: "center",
baseline: "middle",
dx: 0,
},
encoding: {
x: {
aggregate: "sum",
field: "q",
axis: false,
},
text: { field: "d" },
color: { value: "white" },
tooltip: [{ field: "c", type: "nominal", title: "NRT time" }],
},
},
],
};
}
export function makeNCNRTPie(
nc_time_ms: number,
nrt_time_ms: number,
params: ChartParams
): object {
const total_time = nc_time_ms + nrt_time_ms;
const nc_proportion = (nc_time_ms / total_time) * 100;
const nrt_proportion = (nrt_time_ms / total_time) * 100;
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
category: "NC",
value: nc_time_ms,
c:
"NC: " +
time_consumed_str(nc_time_ms) +
" (" +
nc_proportion.toFixed(1) +
"%)",
},
{
category: "NRT",
value: nrt_time_ms,
c:
"NRT: " +
time_consumed_str(nrt_time_ms) +
" (" +
nrt_proportion.toFixed(1) +
"%)",
},
],
},
mark: "arc",
encoding: {
theta: {
field: "value",
type: "quantitative",
},
color: {
field: "category",
type: "nominal",
legend: false,
scale: {
domain: ["NC", "NRT"],
range: ["darkorange", "white"],
},
},
tooltip: [{ field: "c", type: "nominal", title: "NC vs NRT time" }],
},
};
}
export function makeNCTimeBar(
nc_time_ms: number,
elapsed_time_sec: number,
params: ChartParams
): object {
const widthThreshold1 = 15;
const widthThreshold2 = 8;
const elapsed_time_ms = elapsed_time_sec * 1000;
const nc_percent =
elapsed_time_ms > 0 ? (nc_time_ms / elapsed_time_ms) * 100 : 0;
const tooltipText =
"NC: " +
nc_percent.toFixed(1) +
"% of elapsed time [" +
time_consumed_str(nc_time_ms) +
"]";
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
x: 0,
y: nc_percent.toFixed(1),
c: tooltipText,
d:
nc_percent >= widthThreshold1
? nc_percent.toFixed(0) + "%"
: nc_percent >= widthThreshold2
? nc_percent.toFixed(0)
: "",
q: nc_percent / 2,
},
],
},
layer: [
{
mark: { type: "bar" },
encoding: {
x: {
aggregate: "sum",
field: "y",
axis: false,
stack: "zero",
scale: { domain: [0, 100] },
},
color: {
field: "c",
type: "nominal",
legend: false,
scale: { range: ["darkorange"] },
},
tooltip: [{ field: "c", type: "nominal", title: "NC time" }],
},
},
{
mark: {
type: "text",
align: "center",
baseline: "middle",
dx: 0,
},
encoding: {
x: {
aggregate: "sum",
field: "q",
axis: false,
},
text: { field: "d" },
color: { value: "white" },
tooltip: [{ field: "c", type: "nominal", title: "NC time" }],
},
},
],
};
}
export function makeTotalNeuronBar(
total_time_ms: number,
elapsed_time_sec: number,
label: string,
color: string,
params: ChartParams
): object {
const widthThreshold1 = 15;
const widthThreshold2 = 8;
const elapsed_time_ms = elapsed_time_sec * 1000;
const time_percent =
elapsed_time_ms > 0 ? (total_time_ms / elapsed_time_ms) * 100 : 0;
const tooltipText = `${label}: ${time_percent.toFixed(1)}% of elapsed time [${time_consumed_str(total_time_ms)}]`;
return {
$schema: "https://vega.github.io/schema/vega-lite/v5.json",
config: {
view: {
stroke: "transparent",
},
},
autosize: {
contains: "padding",
},
width: params.width,
height: params.height,
padding: 0,
data: {
values: [
{
x: 0,
y: time_percent.toFixed(1),
c: tooltipText,
d:
time_percent >= widthThreshold1
? time_percent.toFixed(0) + "%"
: time_percent >= widthThreshold2
? time_percent.toFixed(0)
: "",
q: time_percent / 2,
},
],
},
layer: [
{
mark: { type: "bar" },
encoding: {
x: {
aggregate: "sum",
field: "y",
axis: false,
stack: "zero",
scale: { domain: [0, 100] },
},
color: {
field: "c",
type: "nominal",
legend: false,
scale: { range: [color] },
},
tooltip: [{ field: "c", type: "nominal", title: label + " time" }],
},
},
{
mark: {
type: "text",
align: "center",
baseline: "middle",
dx: 0,
},
encoding: {
x: {
aggregate: "sum",
field: "q",
axis: false,
},
text: { field: "d" },
color: { value: "white" },
tooltip: [{ field: "c", type: "nominal", title: label + " time" }],
},
},
],
};
}
================================================
FILE: scalene/scalene-gui/index.html
================================================
Scalene
advanced optionsProposed optimizations
Click on an explosion (💥) to see proposed optimizations for a region of code,
or on a lightning bolt (⚡) to propose optimizations for a specific line.
Click again to generate a different one. Note that optimizations are AI-generated and may not be correct.
Profile your Python code
with Scalene,
then select the generated
file profile.json.