Full Code of plasma-umass/scalene for AI

master 58c1b708ace1 cached
396 files
5.5 MB
1.5M tokens
5997 symbols
1 requests
Download .txt
Showing preview only (5,826K chars total). Download the full file or copy to clipboard to get everything.
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
<input type="password" id="api-key" autocomplete="one-time-code">
```

**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
<input type="text" id="api-key" class="persistent">
```
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., `<script src="jquery-3.6.0.slim.min.js">`)
- When `standalone=True`: All assets are embedded inline (JS/CSS as text, images as base64)

The Jinja2 template uses conditionals:
```html
{% if standalone %}
<script>{{ jquery_js }}</script>
<style>{{ bootstrap_css }}</style>
{% else %}
<script src="jquery-3.6.0.slim.min.js"></script>
<link href="bootstrap.min.css" rel="stylesheet">
{% 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<string> {
     // API call implementation
   }

   export async function fetchNewProviderModels(apiKey: string): Promise<string[]> {
     // 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 `<string>` and other headers. **Fix:** Include C++ standard headers BEFORE vendor headers in `src/source/libscalene.cpp`:

```cpp
// Include C++ standard headers FIRST
#include <cstddef>
#include <string>

// Then vendor headers that define conflicting macros
#include <heaplayers.h>  // 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](https://github.com/plasma-umass/scalene/raw/master/docs/scalene-icon-white.png)

# 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).

[![Scalene community Slack](https://github.com/plasma-umass/scalene/raw/master/docs/images/slack-logo.png)](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)

[![PyPI Latest Release](https://img.shields.io/pypi/v/scalene.svg)](https://pypi.org/project/scalene/)[![Anaconda-Server Badge](https://img.shields.io/conda/v/conda-forge/scalene)](https://anaconda.org/conda-forge/scalene) [![Downloads](https://static.pepy.tech/badge/scalene)](https://pepy.tech/project/scalene)[![Anaconda downloads](https://img.shields.io/conda/d/conda-forge/scalene?logo=conda)](https://anaconda.org/conda-forge/scalene) [![Downloads](https://static.pepy.tech/badge/scalene/month)](https://pepy.tech/project/scalene) ![Python versions](https://img.shields.io/pypi/pyversions/scalene.svg?style=flat-square)[![Visual Studio Code Extension version](https://img.shields.io/visual-studio-marketplace/v/emeryberger.scalene?logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=EmeryBerger.scalene) ![License](https://img.shields.io/github/license/plasma-umass/scalene) [![GitHub Repo stars](https://img.shields.io/github/stars/plasma-umass/scalene?style=social)](https://github.com/plasma-umass/scalene)


![Ozsvald tweet](https://github.com/plasma-umass/scalene/raw/master/docs/Ozsvald-tweet.png)

(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))

![Semantic Scholar success story](https://github.com/plasma-umass/scalene/raw/master/docs/semantic-scholar-success.png)

[_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".
>
> <img width="607" height="316" alt="AI Optimization Options" src="https://github.com/user-attachments/assets/3c803237-063f-481a-8624-5c1d7f205c8a" />


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.

<img width="571" alt="example proposed optimization" src="https://user-images.githubusercontent.com/1612723/211639968-37cf793f-3290-43d1-9282-79e579558388.png">

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.

<details>
  <summary>
    Using the Scalene VS Code Extension:
  </summary>
  

First, install <a href="https://marketplace.visualstudio.com/items?itemName=EmeryBerger.scalene">the Scalene extension from the VS Code Marketplace</a> 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 <a href="https://code.visualstudio.com/docs/getstarted/userinterface">Command Palette</a>. Then select <b>"Scalene: AI-powered profiling..."</b> (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.
  
<img width="734" alt="Screenshot 2023-09-20 at 7 09 06 PM" src="https://github.com/plasma-umass/scalene/assets/1612723/7e78e3d2-e649-4f02-86fd-0da2a259a1a4">

</details>

<details>
<summary>
Commonly used command-line options:
</summary>

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
```

</details>

<details>
<summary>
Using a YAML configuration file:
</summary>

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.

</details>

<details>
<summary>
Using Scalene programmatically in your code:
</summary>

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
```

</details>

<details>
<summary>
Using Scalene to profile only specific functions via <code>@profile</code>:
</summary>

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)
```

</details>

#### 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.

[![Scalene web GUI](https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/scalene-gui-example.png)](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!

[![Scalene presentation at PyCon 2021](https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/images/scalene-video-img.png)](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.

![Profiler accuracy](https://github.com/plasma-umass/scalene/raw/master/docs/cpu-accuracy-comparison.png)

- 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.

![Performance and feature comparison](https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/images/profiler-comparison.png)

- **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`.

![Example profile](https://raw.githubusercontent.com/plasma-umass/scalene/master/docs/images/sample-profile-pystone.png)

* **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
```

<details>
 <summary>
  Click to see all Scalene's options (available by running with <code>--help</code>)
 </summary>

```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 <PID>   # resume profiling
    % python3 -m scalene.profile --off --pid <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)
```
</details>

### Scalene with Jupyter

<details>
<summary>
Instructions for installing and using Scalene with Jupyter notebooks
</summary>

[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...
```
</details>

## Installation

<details open>
<summary>Using <code>pip</code> (Mac OS X, Linux, Windows, and WSL2)</summary>

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
```
</details>

<details>
<summary>Using <code>conda</code> (Mac OS X, Linux, Windows, and WSL2)</summary>

```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.
>
</details>

<details>
<summary>On ArchLinux</summary>

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.
</details>

# Frequently Asked Questions

<details>
<summary>
Can I use Scalene with PyTest?
</summary>

**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` 

</details>

<details>
<summary>
Is there any way to get shorter profiles or do more targeted profiling?
</summary>

**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`).
</details>

<details>
<summary>
How do I run Scalene in PyCharm?
</summary>

**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 <your program>`). Then use `scalene view --html` to generate an HTML file (`scalene-profile.html`) that you can view in the IDE.
</details>

<details>
<summary>
How do I use Scalene with Django?
</summary>

**A:** Pass in the `--noreload` option (see https://github.com/plasma-umass/scalene/issues/178).
</details>


<details>
<summary>
Does Scalene work with gevent/Greenlets?
</summary>

**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)
```
</details>



<details>
<summary>
How do I use Scalene with PyTorch on the Mac?
</summary>

**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.
</details>

# 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.)

<details>
<summary>
To cite Scalene in an academic paper, please use the following:
</summary>

```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
}
```
</details>


# 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 `<span id="chart_name${index}">` 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<void*, size_t> 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": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-style: italic\">                                             [1]: % of time = 100.00% out of   6.02s.                                             </span>\n",
       "        ╷        ╷       ╷       ╷                                                                                                 \n",
       " <span style=\"font-weight: bold\">  Line </span>│<span style=\"font-weight: bold\">Time    </span>│<span style=\"font-weight: bold\">–––––– </span>│<span style=\"font-weight: bold\">–––––– </span>│<span style=\"font-weight: bold\">                                                                                                </span> \n",
       "        │<span style=\"font-weight: bold; font-style: italic\">Python</span><span style=\"font-weight: bold\">  </span>│<span style=\"font-weight: bold; font-style: italic\">native</span><span style=\"font-weight: bold\"> </span>│<span style=\"font-weight: bold; font-style: italic\">system</span><span style=\"font-weight: bold\"> </span>│<span style=\"font-weight: bold\">[1]                                                                                            </span> \n",
       "╺━━━━━━━┿━━━━━━━━┿━━━━━━━┿━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸\n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     1 </span>│        │       │       │<span style=\"color: #000080; text-decoration-color: #000080; background-color: #000000\"># An example program to profile</span><span style=\"background-color: #000000\">                                                               </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     2 </span>│        │       │       │<span style=\"background-color: #000000\">                                                                                              </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     3 </span>│        │       │       │<span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">import</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> numpy </span><span style=\"color: #cdcd00; text-decoration-color: #cdcd00; background-color: #000000\">as</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> np</span><span style=\"background-color: #000000\">                                                                            </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     4 </span>│        │       │       │<span style=\"background-color: #000000\">                                                                                              </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     5 </span>│        │       │       │<span style=\"color: #cdcd00; text-decoration-color: #cdcd00; background-color: #000000\">def</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> test_me():</span><span style=\"background-color: #000000\">                                                                                </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     6 </span>│        │       │       │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">    </span><span style=\"color: #cdcd00; text-decoration-color: #cdcd00; background-color: #000000\">for</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> i </span><span style=\"color: #cdcd00; text-decoration-color: #cdcd00; background-color: #000000\">in</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> </span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">range</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">6</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">):</span><span style=\"background-color: #000000\">                                                                        </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     7 </span>│<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">    1%</span>  │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   35%</span> │   7%  │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">        x </span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> np</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">array(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">range</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">10</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">**</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">7</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">))</span><span style=\"background-color: #000000\">                                                            </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     8 </span>│<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">    2%</span>  │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   55%</span> │       │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">        y </span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> np</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">array(np</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">random</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">uniform(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">0</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">, </span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">100</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">, size</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">10</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">**</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">8</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">)))</span><span style=\"background-color: #000000\">                                 </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">       </span>│        │       │       │                                                                                                 \n",
       "╶───────┼────────┼───────┼───────┼────────────────────────────────────────────────────────────────────────────────────────────────╴\n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">       </span>│        │       │       │<span style=\"font-weight: bold; font-style: italic\">function summary for &lt;ipython-input-14-3a53cdc5d2d5&gt;                                           </span>  \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     5 </span>│<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">    3%</span>  │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   91%</span> │   6%  │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">test_me</span><span style=\"background-color: #000000\">                                                                                       </span>   \n",
       "        ╵        ╵       ╵       ╵                                                                                                 \n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x1050b0d60>"
      ]
     },
     "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": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-style: italic\">                                             [1]: % of time = 100.00% out of   6.67s.                                             </span>\n",
       "        ╷        ╷       ╷       ╷                                                                                                 \n",
       " <span style=\"font-weight: bold\">  Line </span>│<span style=\"font-weight: bold\">Time    </span>│<span style=\"font-weight: bold\">–––––– </span>│<span style=\"font-weight: bold\">–––––– </span>│<span style=\"font-weight: bold\">                                                                                                </span> \n",
       "        │<span style=\"font-weight: bold; font-style: italic\">Python</span><span style=\"font-weight: bold\">  </span>│<span style=\"font-weight: bold; font-style: italic\">native</span><span style=\"font-weight: bold\"> </span>│<span style=\"font-weight: bold; font-style: italic\">system</span><span style=\"font-weight: bold\"> </span>│<span style=\"font-weight: bold\">[1]                                                                                            </span> \n",
       "╺━━━━━━━┿━━━━━━━━┿━━━━━━━┿━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸\n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">   ... </span>│        │       │       │                                                                                                 \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     7 </span>│        │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   34%</span> │   7%  │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">        x </span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> np</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">array(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">range</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">10</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">**</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">7</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">))</span><span style=\"background-color: #000000\">                                                            </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     8 </span>│<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">    2%</span>  │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   49%</span> │   8%  │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">        y </span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> np</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">array(np</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">random</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">.</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">uniform(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">0</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">, </span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">100</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">, size</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">10</span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">**</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">8</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">)))</span><span style=\"background-color: #000000\">                                 </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">       </span>│        │       │       │                                                                                                 \n",
       "╶───────┼────────┼───────┼───────┼────────────────────────────────────────────────────────────────────────────────────────────────╴\n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">       </span>│        │       │       │<span style=\"font-weight: bold; font-style: italic\">function summary for &lt;ipython-input-14-3a53cdc5d2d5&gt;                                           </span>  \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     5 </span>│<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">    2%</span>  │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   83%</span> │  15%  │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">test_me</span><span style=\"background-color: #000000\">                                                                                       </span>   \n",
       "        ╵        ╵       ╵       ╵                                                                                                 \n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x105073220>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Generate a reduced profile (only lines with non-zero counts)\n",
    "%scrun --reduced-profile test_me()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "minimal-society",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-style: italic\">         /var/folders/m7/sln1lr497jqcchb2ddh32rw00000gq/T/scalene_profile_qxy9xnh3.py: % of time = 100.00% out of   0.09s.         </span>\n",
       "        ╷        ╷       ╷       ╷                                                                                                 \n",
       " <span style=\"font-weight: bold\">  Line </span>│<span style=\"font-weight: bold\">Time    </span>│<span style=\"font-weight: bold\">–––––– </span>│<span style=\"font-weight: bold\">–––––– </span>│<span style=\"font-weight: bold\">                                                                                                </span> \n",
       "        │<span style=\"font-weight: bold; font-style: italic\">Python</span><span style=\"font-weight: bold\">  </span>│<span style=\"font-weight: bold; font-style: italic\">native</span><span style=\"font-weight: bold\"> </span>│<span style=\"font-weight: bold; font-style: italic\">system</span><span style=\"font-weight: bold\"> </span>│<span style=\"font-weight: bold\">/var/folders/m7/sln1lr497jqcchb2ddh32rw00000gq/T/scalene_profile_qxy9xnh3.py                    </span> \n",
       "╺━━━━━━━┿━━━━━━━━┿━━━━━━━┿━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸\n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">   ... </span>│        │       │       │                                                                                                 \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     4 </span>│   21%  │       │       │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">    </span><span style=\"color: #cdcd00; text-decoration-color: #cdcd00; background-color: #000000\">for</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> j </span><span style=\"color: #cdcd00; text-decoration-color: #cdcd00; background-color: #000000\">in</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> </span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">range</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">(</span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">1000</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">):</span><span style=\"background-color: #000000\">                                                                     </span>   \n",
       " <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">     5 </span>│<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">   59%</span>  │<span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">    6%</span> │  13%  │<span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\">        x </span><span style=\"color: #3399cc; text-decoration-color: #3399cc; background-color: #000000\">+=</span><span style=\"color: #cccccc; text-decoration-color: #cccccc; background-color: #000000\"> </span><span style=\"color: #cd00cd; text-decoration-color: #cd00cd; background-color: #000000\">1</span><span style=\"background-color: #000000\">                                                                                </span>   \n",
       "        ╵        ╵       ╵       ╵                                                                                                 \n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x10743c640>"
      ]
     },
     "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 <https://emeryberger.com>`__, `Sam
Stern <https://samstern.me/>`__, and `Juan Altmayer
Pizzorno <https://github.com/jaltmayerpizzorno>`__.

|Scalene community Slack|\ `Scalene community
Slack <https://join.slack.com/t/scaleneprofil-jge3234/shared_invite/zt-110vzrdck-xJh5d4gHnp5vKXIjYD3Uwg>`__

|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 <https://smile.amazon.com/High-Performance-Python-Performant-Programming/dp/1492055026/ref=sr_1_1?crid=texbooks>`__)

.. 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 <https://openai.com/api/>`__ 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

   <details>

.. raw:: html

   <summary>

Using the Scalene VS Code Extension:

.. raw:: html

   </summary>

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

   </details>

.. raw:: html

   <details>

.. raw:: html

   <summary>

Commonly used command-line options:

.. raw:: html

   </summary>

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

   </details>

.. raw:: html

   <details>

.. raw:: html

   <summary>

Using Scalene programmatically in your code:

.. raw:: html

   </summary>

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

   </details>

.. raw:: html

   <details>

.. raw:: html

   <summary>

Using Scalene to profile only specific functions via @profile:

.. raw:: html

   </summary>

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

   </details>

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 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 <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!

|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 t
Download .txt
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
Download .txt
Showing preview only (450K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (5997 symbols across 274 files)

FILE: benchmarks/bench_torch_memory.py
  function main (line 34) | def main() -> None:

FILE: benchmarks/julia1_nopil.py
  function profile (line 16) | def profile(func):
  function calculate_z_serial_purepython (line 34) | def calculate_z_serial_purepython(maxiter, zs, cs):
  function calc_pure_python (line 49) | def calc_pure_python(desired_width, max_iterations):

FILE: benchmarks/measure_profiler_memory.py
  function _get_rss_mb (line 42) | def _get_rss_mb(pid: int) -> float | None:
  class RSSMonitor (line 64) | class RSSMonitor:
    method __init__ (line 67) | def __init__(self, pid: int, interval: float = SAMPLE_INTERVAL) -> None:
    method start (line 74) | def start(self) -> None:
    method stop (line 77) | def stop(self) -> None:
    method _run (line 81) | def _run(self) -> None:
    method peak_mb (line 89) | def peak_mb(self) -> float:
    method final_mb (line 93) | def final_mb(self) -> float:
  function run_scalene_benchmark (line 99) | def run_scalene_benchmark(bench_script: str) -> tuple[float, float, float]:
  function git (line 147) | def git(*args: str) -> str:
  function compare_master (line 153) | def compare_master() -> None:
  function main (line 196) | def main() -> None:

FILE: benchmarks/new_benchmark.py
  function main (line 42) | def main():

FILE: benchmarks/pystone.py
  class Record (line 44) | class Record:
    method __init__ (line 46) | def __init__(self, PtrComp=None, Discr=0, EnumComp=0, IntComp=0, Strin...
    method copy (line 53) | def copy(self):
  function main (line 63) | def main(loops=LOOPS):
  function pystones (line 69) | def pystones(loops=LOOPS):
  function Proc0 (line 83) | def Proc0(loops=LOOPS):
  function Proc1 (line 142) | def Proc1(PtrParIn):
  function Proc2 (line 159) | def Proc2(IntParIO):
  function Proc3 (line 171) | def Proc3(PtrParOut):
  function Proc4 (line 182) | def Proc4():
  function Proc5 (line 190) | def Proc5():
  function Proc6 (line 198) | def Proc6(EnumParIn):
  function Proc7 (line 218) | def Proc7(IntParI1, IntParI2):
  function Proc8 (line 224) | def Proc8(Array1Par, Array2Par, IntParI1, IntParI2):
  function Func1 (line 238) | def Func1(CharPar1, CharPar2):
  function Func2 (line 247) | def Func2(StrParI1, StrParI2):
  function Func3 (line 265) | def Func3(EnumParIn):
  function error (line 275) | def error(msg):

FILE: demo_torch_jit.py
  function compute_intensive (line 6) | def compute_intensive(x: torch.Tensor) -> torch.Tensor:
  function main (line 15) | def main():

FILE: scalene/__main__.py
  function main (line 5) | def main() -> None:

FILE: scalene/adaptive.py
  class Adaptive (line 4) | class Adaptive:
    method __init__ (line 7) | def __init__(self, size: int) -> None:
    method __add__ (line 13) | def __add__(self: "Adaptive", other: "Adaptive") -> "Adaptive":
    method __iadd__ (line 20) | def __iadd__(self: "Adaptive", other: "Adaptive") -> "Adaptive":
    method add (line 26) | def add(self, value: float) -> None:
    method get (line 39) | def get(self) -> List[float]:
    method len (line 42) | def len(self) -> int:

FILE: scalene/find_browser.py
  function find_browser (line 5) | def find_browser(browserClass: Optional[str] = None) -> Optional[str]:

FILE: scalene/get_module_details.py
  function _get_module_details (line 12) | def _get_module_details(

FILE: scalene/launchbrowser.py
  function launch_browser_insecure (line 18) | def launch_browser_insecure(url: str) -> None:
  class CustomHandler (line 51) | class CustomHandler(http.server.SimpleHTTPRequestHandler):
    method do_GET (line 52) | def do_GET(self) -> Any:
  function monitor_heartbeat (line 63) | def monitor_heartbeat() -> None:
  function serve_forever (line 73) | def serve_forever(httpd: Any) -> None:
  function run_server (line 78) | def run_server(host: str, port: int) -> None:
  function is_port_available (line 84) | def is_port_available(port: int) -> bool:
  function generate_html (line 103) | def generate_html(profile_fname: Filename, output_fname: Filename) -> None:
  function start (line 141) | def start(filename: str, port: int) -> None:

FILE: scalene/merge_scalene_neuron_profiles.py
  function parse_debug_file_programmatic (line 9) | def parse_debug_file_programmatic(
  function calculate_cpu_sample_overlap (line 55) | def calculate_cpu_sample_overlap(
  function merge_neuron_into_scalene_programmatic (line 96) | def merge_neuron_into_scalene_programmatic(

FILE: scalene/redirect_python.py
  function redirect_python (line 7) | def redirect_python(preface: str, cmdline: str, python_alias_dir: pathli...

FILE: scalene/replacement_asyncio.py
  function replacement_asyncio (line 12) | def replacement_asyncio(scalene: Scalene) -> None:

FILE: scalene/replacement_exec.py
  function _caller_future_flags (line 36) | def _caller_future_flags(frame: FrameType) -> int:
  function _is_synthetic_filename (line 41) | def _is_synthetic_filename(filename: str) -> bool:
  function _register_source_in_linecache (line 46) | def _register_source_in_linecache(filename: str, source: str) -> None:
  function _make_virtual_filename (line 57) | def _make_virtual_filename(kind: str, caller_frame: FrameType) -> str:
  function replacement_exec (line 70) | def replacement_exec(scalene: Scalene) -> None:  # noqa: ARG001

FILE: scalene/replacement_exit.py
  function replacement_exit (line 8) | def replacement_exit(scalene: Scalene) -> None:

FILE: scalene/replacement_fork.py
  function replacement_fork (line 7) | def replacement_fork(scalene: Scalene) -> None:

FILE: scalene/replacement_get_context.py
  function replacement_mp_get_context (line 8) | def replacement_mp_get_context(scalene: Scalene) -> None:

FILE: scalene/replacement_lock.py
  function replacement_lock (line 11) | def replacement_lock(scalene: Scalene) -> None:

FILE: scalene/replacement_mp_lock.py
  function replacement_mp_semlock (line 14) | def replacement_mp_semlock(scalene: Scalene) -> None:

FILE: scalene/replacement_pjoin.py
  function replacement_pjoin (line 13) | def replacement_pjoin(scalene: Scalene) -> None:

FILE: scalene/replacement_poll_selector.py
  function replacement_poll_selector (line 11) | def replacement_poll_selector(scalene: Scalene) -> None:

FILE: scalene/replacement_sem_lock.py
  function _make_replacement_semlock (line 11) | def _make_replacement_semlock(method: Optional[str] = None) -> "Replacem...
  class ReplacementSemLock (line 17) | class ReplacementSemLock(multiprocessing.synchronize.Lock):
    method __init__ (line 18) | def __init__(
    method __enter__ (line 34) | def __enter__(self) -> bool:
    method __exit__ (line 51) | def __exit__(self, *args: Any) -> None:
    method __reduce__ (line 54) | def __reduce__(self) -> Tuple[Callable[..., Any], Tuple[Any, ...]]:

FILE: scalene/replacement_signal_fns.py
  function replacement_signal_fns (line 10) | def replacement_signal_fns(scalene: Scalene) -> None:

FILE: scalene/replacement_thread_join.py
  function replacement_thread_join (line 10) | def replacement_thread_join(scalene: Scalene) -> None:

FILE: scalene/runningstats.py
  class RunningStats (line 5) | class RunningStats:
    method __init__ (line 10) | def __init__(self) -> None:
    method __add__ (line 15) | def __add__(self: "RunningStats", other: "RunningStats") -> "RunningSt...
    method clear (line 28) | def clear(self) -> None:
    method push (line 34) | def push(self, x: float) -> None:
    method peak (line 42) | def peak(self) -> float:
    method size (line 46) | def size(self) -> int:
    method mean (line 50) | def mean(self) -> float:

FILE: scalene/scalene-gui/amazon.ts
  type AnthropicResponse (line 6) | interface AnthropicResponse {
  type OpenAIStyleResponse (line 10) | interface OpenAIStyleResponse {
  function sendPromptToAmazon (line 18) | async function sendPromptToAmazon(prompt: string): Promise<string> {

FILE: scalene/scalene-gui/anthropic.ts
  type AnthropicErrorResponse (line 1) | interface AnthropicErrorResponse {
  type AnthropicContentBlock (line 8) | interface AnthropicContentBlock {
  type AnthropicResponse (line 13) | interface AnthropicResponse extends AnthropicErrorResponse {
  function sendPromptToAnthropic (line 17) | async function sendPromptToAnthropic(

FILE: scalene/scalene-gui/azure.ts
  type AzureOpenAIChoice (line 1) | interface AzureOpenAIChoice {
  type AzureOpenAIResponse (line 7) | interface AzureOpenAIResponse {
  function sendPromptToAzureOpenAI (line 14) | async function sendPromptToAzureOpenAI(

FILE: scalene/scalene-gui/gemini.ts
  type GeminiErrorResponse (line 1) | interface GeminiErrorResponse {
  type GeminiContentPart (line 9) | interface GeminiContentPart {
  type GeminiContent (line 13) | interface GeminiContent {
  type GeminiCandidate (line 18) | interface GeminiCandidate {
  type GeminiResponse (line 22) | interface GeminiResponse extends GeminiErrorResponse {
  type GeminiModelInfo (line 26) | interface GeminiModelInfo {
  type GeminiModelsResponse (line 32) | interface GeminiModelsResponse extends GeminiErrorResponse {
  function sendPromptToGemini (line 36) | async function sendPromptToGemini(
  function fetchGeminiModels (line 119) | async function fetchGeminiModels(apiKey: string): Promise<string[]> {

FILE: scalene/scalene-gui/gui-elements.ts
  type ChartParams (line 11) | interface ChartParams {
  type Window (line 18) | interface Window {
  type LineProfile (line 39) | interface LineProfile {
  type FileProfile (line 64) | interface FileProfile {
  function makeTooltip (line 72) | function makeTooltip(title: string, value: number): string {
  function makeBar (line 85) | function makeBar(
  function makeAwaitPie (line 189) | function makeAwaitPie(
  function makeGPUPie (line 244) | function makeGPUPie(
  function makeGPUBar (line 300) | function makeGPUBar(
  function makeMemoryPie (line 370) | function makeMemoryPie(
  function makeMemoryBar (line 412) | function makeMemoryBar(
  function makeSparkline (line 499) | function makeSparkline(
  function makeNRTBar (line 612) | function makeNRTBar(
  function makeNCNRTPie (line 702) | function makeNCNRTPie(
  function makeNCTimeBar (line 768) | function makeNCTimeBar(
  function makeTotalNeuronBar (line 858) | function makeTotalNeuronBar(

FILE: scalene/scalene-gui/ollama.ts
  type OllamaModel (line 1) | interface OllamaModel {
  type OllamaTagsResponse (line 5) | interface OllamaTagsResponse {
  type OllamaMessage (line 9) | interface OllamaMessage {
  type OllamaResponse (line 13) | interface OllamaResponse {
  function fetchModelNames (line 18) | async function fetchModelNames(
  function sendPromptToOllama (line 43) | async function sendPromptToOllama(

FILE: scalene/scalene-gui/openai.ts
  type OpenAIErrorResponse (line 1) | interface OpenAIErrorResponse {
  type OpenAIChoice (line 8) | interface OpenAIChoice {
  type OpenAIResponse (line 14) | interface OpenAIResponse extends OpenAIErrorResponse {
  type OpenAIModel (line 18) | interface OpenAIModel {
  type OpenAIModelsResponse (line 23) | interface OpenAIModelsResponse extends OpenAIErrorResponse {
  function tryApi (line 27) | async function tryApi(apiKey: string): Promise<Response> {
  function isValidApiKey (line 38) | async function isValidApiKey(apiKey: string): Promise<boolean> {
  function fetchOpenAIModels (line 58) | async function fetchOpenAIModels(apiKey: string): Promise<string[]> {
  function checkApiKey (line 100) | function checkApiKey(apiKey: string): void {
  function sendPromptToOpenAI (line 137) | async function sendPromptToOpenAI(

FILE: scalene/scalene-gui/optimizations.ts
  type LineData (line 25) | interface LineData {
  type OptimizationParams (line 41) | interface OptimizationParams {
  function copyOnClick (line 45) | async function copyOnClick(event: Event, message: string): Promise<void> {
  function extractCode (line 51) | function extractCode(text: string): string {
  function generateScaleneOptimizedCodeRequest (line 87) | function generateScaleneOptimizedCodeRequest(
  function extractPythonCodeBlock (line 167) | function extractPythonCodeBlock(markdown: string): string {
  function optimizeCode (line 185) | async function optimizeCode(
  function proposeOptimization (line 369) | function proposeOptimization(

FILE: scalene/scalene-gui/persistence.ts
  function restoreState (line 25) | function restoreState(el: HTMLInputElement): void {
  function saveState (line 47) | function saveState(el: HTMLInputElement): void {
  function processPersistentElements (line 62) | function processPersistentElements(): void {

FILE: scalene/scalene-gui/prism.js
  function insertHighlightedCode (line 598) | function insertHighlightedCode(highlightedCode) {
  function Token (line 798) | function Token(type, content, alias, matchedStr) {
  function matchPattern (line 922) | function matchPattern(pattern, pos, text, lookbehind) {
  function matchGrammar (line 948) | function matchGrammar(
  function LinkedList (line 1127) | function LinkedList() {
  function addAfter (line 1150) | function addAfter(list, node, value) {
  function removeRange (line 1169) | function removeRange(list, node, count) {
  function toArray (line 1183) | function toArray(list) {
  function highlightAutomaticallyCallback (line 1232) | function highlightAutomaticallyCallback() {
  function NormalizeWhitespace (line 1892) | function NormalizeWhitespace(defaults) {
  function toCamelCase (line 1896) | function toCamelCase(value) {
  function tabLen (line 1902) | function tabLen(str) {

FILE: scalene/scalene-gui/scalene-gui-bundle.js
  method "node_modules/base64-js/index.js" (line 35) | "node_modules/base64-js/index.js"(exports2) {
  method "node_modules/ieee754/index.js" (line 136) | "node_modules/ieee754/index.js"(exports2) {
  method "node_modules/buffer/index.js" (line 219) | "node_modules/buffer/index.js"(exports2) {
  method "node_modules/bowser/es5.js" (line 1811) | "node_modules/bowser/es5.js"(exports2, module5) {
  function stringify (line 2470) | function stringify(passedObj, options = {}) {
  function accessor (line 2785) | function accessor(fn, fields, name4) {
  function accessorName (line 2790) | function accessorName(fn) {
  function accessorFields (line 2793) | function accessorFields(fn) {
  function getter (line 2796) | function getter(path3) {
  function error (line 2811) | function error(message) {
  function splitAccessPath (line 2814) | function splitAccessPath(p2) {
  function field (line 2864) | function field(field3, name4, opt) {
  function log$1 (line 2875) | function log$1(method2, level, input) {
  function logger (line 2884) | function logger(_, method2) {
  function isObject (line 2915) | function isObject(_) {
  function mergeConfig (line 2919) | function mergeConfig() {
  function writeConfig (line 2937) | function writeConfig(output3, key2, value3, recurse2) {
  function mergeNamed (line 2953) | function mergeNamed(a4, b3) {
  function peek (line 2966) | function peek(array4) {
  function toNumber (line 2969) | function toNumber(_) {
  function pan (line 2977) | function pan(domain4, delta, lift, ground) {
  function panLinear (line 2981) | function panLinear(domain4, delta) {
  function panLog (line 2984) | function panLog(domain4, delta) {
  function panPow (line 2988) | function panPow(domain4, delta, exponent) {
  function panSymlog (line 2991) | function panSymlog(domain4, delta, constant3) {
  function zoom (line 2994) | function zoom(domain4, anchor, scale7, lift, ground) {
  function zoomLinear (line 2998) | function zoomLinear(domain4, anchor, scale7) {
  function zoomLog (line 3001) | function zoomLog(domain4, anchor, scale7) {
  function zoomPow (line 3005) | function zoomPow(domain4, anchor, scale7, exponent) {
  function zoomSymlog (line 3008) | function zoomSymlog(domain4, anchor, scale7, constant3) {
  function quarter (line 3011) | function quarter(date2) {
  function utcquarter (line 3014) | function utcquarter(date2) {
  function array (line 3017) | function array(_) {
  function clampRange (line 3020) | function clampRange(range7, min4, max4) {
  function isFunction (line 3030) | function isFunction(_) {
  function compare (line 3034) | function compare(fields, orders, opt) {
  function constant (line 3062) | function constant(_) {
  function debounce (line 3065) | function debounce(delay, handler) {
  function extend (line 3072) | function extend(_) {
  function extent (line 3081) | function extent(array4, f2) {
  function extentIndex (line 3108) | function extentIndex(array4, f2) {
  function has (line 3160) | function has(object2, property2) {
  function fastmap (line 3164) | function fastmap(input) {
  function flush (line 3225) | function flush(range7, value3, threshold2, left, right, center) {
  function inherits (line 3238) | function inherits(child, parent, members) {
  function inrange (line 3248) | function inrange(value3, range7, left, right) {
  function isBoolean (line 3259) | function isBoolean(_) {
  function isDate (line 3262) | function isDate(_) {
  function isIterable (line 3265) | function isIterable(_) {
  function isNumber (line 3268) | function isNumber(_) {
  function isRegExp (line 3271) | function isRegExp(_) {
  function isString (line 3274) | function isString(_) {
  function key (line 3277) | function key(fields, flat, opt) {
  function lerp (line 3302) | function lerp(array4, frac) {
  function lruCache (line 3307) | function lruCache(maxsize) {
  function merge (line 3331) | function merge(compare4, array0, array1, output3) {
  function repeat (line 3348) | function repeat(str, reps) {
  function pad (line 3353) | function pad(str, length3, padchar, align2) {
  function span (line 3357) | function span(array4) {
  function $ (line 3360) | function $(x5) {
  function toBoolean (line 3367) | function toBoolean(_) {
  function toDate (line 3371) | function toDate(_, parser4) {
  function toString (line 3375) | function toString(_) {
  function toSet (line 3378) | function toSet(_) {
  function truncate (line 3383) | function truncate(str, length3, align2, ellipsis) {
  function visitArray (line 3387) | function visitArray(array4, filter3, visitor) {
  function objectConverter (line 3407) | function objectConverter(columns2) {
  function customConverter (line 3412) | function customConverter(columns2, f2) {
  function inferColumns (line 3418) | function inferColumns(rows) {
  function pad2 (line 3429) | function pad2(value3, width2) {
  function formatYear (line 3433) | function formatYear(year) {
  function formatDate (line 3436) | function formatDate(date2) {
  function dsv_default (line 3440) | function dsv_default(delimiter) {
  function identity_default (line 3522) | function identity_default(x5) {
  function transform_default (line 3527) | function transform_default(transform4) {
  function reverse_default (line 3541) | function reverse_default(array4, n2) {
  function feature_default (line 3547) | function feature_default(topology, o2) {
  function feature (line 3553) | function feature(topology, o2) {
  function object (line 3557) | function object(topology, o2) {
  function stitch_default (line 3615) | function stitch_default(topology, arcs) {
  function mesh_default (line 3681) | function mesh_default(topology) {
  function meshArcs (line 3684) | function meshArcs(topology, object2, filter3) {
  function extractArcs (line 3690) | function extractArcs(topology, object2, filter3) {
  function ascending2 (line 3732) | function ascending2(a4, b3) {
  function descending (line 3737) | function descending(a4, b3) {
  function bisector (line 3742) | function bisector(f2) {
  function zero2 (line 3781) | function zero2() {
  function number (line 3786) | function number(x5) {
  function variance (line 3814) | function variance(values4, valueof) {
  function deviation (line 3841) | function deviation(values4, valueof) {
  method constructor (line 3848) | constructor() {
  method add (line 3852) | add(x5) {
  method valueOf (line 3864) | valueOf() {
  method constructor (line 3888) | constructor(entries3, key2 = keyof) {
  method get (line 3893) | get(key2) {
  method has (line 3896) | has(key2) {
  method set (line 3899) | set(key2, value3) {
  method delete (line 3902) | delete(key2) {
  method constructor (line 3907) | constructor(values4, key2 = keyof) {
  method has (line 3912) | has(value3) {
  method add (line 3915) | add(value3) {
  method delete (line 3918) | delete(value3) {
  function intern_get (line 3922) | function intern_get({ _intern, _key }, value3) {
  function intern_set (line 3926) | function intern_set({ _intern, _key }, value3) {
  function intern_delete (line 3932) | function intern_delete({ _intern, _key }, value3) {
  function keyof (line 3940) | function keyof(value3) {
  function permute (line 3945) | function permute(source4, keys4) {
  function compareDefined (line 3950) | function compareDefined(compare4 = ascending2) {
  function ascendingDefined (line 3959) | function ascendingDefined(a4, b3) {
  function tickSpec (line 3967) | function tickSpec(start, stop2, count2) {
  function ticks (line 3987) | function ticks(start, stop2, count2) {
  function tickIncrement (line 4003) | function tickIncrement(start, stop2, count2) {
  function tickStep (line 4007) | function tickStep(start, stop2, count2) {
  function max (line 4014) | function max(values4, valueof) {
  function min (line 4034) | function min(values4, valueof) {
  function quickselect (line 4054) | function quickselect(array4, k2, left = 0, right = Infinity, compare4) {
  function swap (line 4088) | function swap(array4, i2, j2) {
  function quantile (line 4095) | function quantile(values4, p2, valueof) {
  function quantileSorted (line 4103) | function quantileSorted(values4, p2, valueof = number) {
  function mean (line 4112) | function mean(values4, valueof) {
  function median (line 4133) | function median(values4, valueof) {
  function merge2 (line 4143) | function merge2(arrays) {
  function range (line 4148) | function range(start, stop2, step) {
  function sum (line 4158) | function sum(values4, valueof) {
  function intersection (line 4178) | function intersection(values4, ...others) {
  function set (line 4191) | function set(values4) {
  function union (line 4196) | function union(...others) {
  function formatDecimal_default (line 4207) | function formatDecimal_default(x5) {
  function formatDecimalParts (line 4210) | function formatDecimalParts(x5, p2) {
  function exponent_default (line 4220) | function exponent_default(x5) {
  function formatGroup_default (line 4225) | function formatGroup_default(grouping, thousands) {
  function formatNumerals_default (line 4239) | function formatNumerals_default(numerals) {
  function formatSpecifier (line 4249) | function formatSpecifier(specifier) {
  function FormatSpecifier (line 4266) | function FormatSpecifier(specifier) {
  function formatTrim_default (line 4283) | function formatTrim_default(s2) {
  function formatPrefixAuto_default (line 4304) | function formatPrefixAuto_default(x5, p2) {
  function formatRounded_default (line 4312) | function formatRounded_default(x5, p2) {
  function identity_default2 (line 4337) | function identity_default2(x5) {
  function locale_default (line 4344) | function locale_default(locale4) {
  function defaultLocale (line 4424) | function defaultLocale(definition3) {
  function precisionFixed_default (line 4432) | function precisionFixed_default(step) {
  function precisionPrefix_default (line 4437) | function precisionPrefix_default(step, value3) {
  function precisionRound_default (line 4442) | function precisionRound_default(step, max4) {
  function timeInterval (line 4450) | function timeInterval(floori, offseti, count2, field3) {
  function timeWeekday (line 4624) | function timeWeekday(i2) {
  function utcWeekday (line 4648) | function utcWeekday(i2) {
  function ticker (line 4740) | function ticker(year, month, week2, day, hour, minute) {
  function timeUnits (line 4795) | function timeUnits(units) {
  function timeUnitSpecifier (line 4828) | function timeUnitSpecifier(units, specifiers) {
  function localYear (line 4844) | function localYear(y5) {
  function dayofyear (line 4851) | function dayofyear(d2) {
  function week (line 4854) | function week(d2) {
  function localDayOfYear (line 4857) | function localDayOfYear(d2) {
  function localWeekNum (line 4860) | function localWeekNum(d2) {
  function localFirst (line 4863) | function localFirst(y5) {
  function localDate (line 4866) | function localDate(y5, m4, d2, H, M2, S, L) {
  function utcdayofyear (line 4874) | function utcdayofyear(d2) {
  function utcweek (line 4877) | function utcweek(d2) {
  function utcDayOfYear (line 4880) | function utcDayOfYear(d2) {
  function utcWeekNum (line 4884) | function utcWeekNum(d2) {
  function utcFirst (line 4888) | function utcFirst(y5) {
  function utcDate (line 4892) | function utcDate(y5, m4, d2, H, M2, S, L) {
  function floor (line 4900) | function floor(units, step, get6, inv, newDate2) {
  function getUnit (line 4912) | function getUnit(f2, inv, step, phase) {
  function weekday (line 4916) | function weekday(week2, day, firstDay) {
  function timeFloor (line 4937) | function timeFloor(units, step) {
  function utcFloor (line 4958) | function utcFloor(units, step) {
  function timeInterval2 (line 4987) | function timeInterval2(unit2) {
  function utcInterval (line 4990) | function utcInterval(unit2) {
  function offset (line 4993) | function offset(ival, date2, step) {
  function timeOffset (line 4996) | function timeOffset(unit2, date2, step) {
  function utcOffset (line 4999) | function utcOffset(unit2, date2, step) {
  function sequence (line 5002) | function sequence(ival, start, stop2, step) {
  function timeSequence (line 5005) | function timeSequence(unit2, start, stop2, step) {
  function utcSequence (line 5008) | function utcSequence(unit2, start, stop2, step) {
  function bin (line 5027) | function bin(opt) {
  function localDate2 (line 5047) | function localDate2(d2) {
  function utcDate2 (line 5055) | function utcDate2(d2) {
  function newDate (line 5063) | function newDate(y5, m4, d2) {
  function formatLocale (line 5066) | function formatLocale(locale4) {
  function pad3 (line 5351) | function pad3(value3, fill2, width2) {
  function requote (line 5355) | function requote(s2) {
  function formatRe (line 5358) | function formatRe(names) {
  function formatLookup (line 5361) | function formatLookup(names) {
  function parseWeekdayNumberSunday (line 5364) | function parseWeekdayNumberSunday(d2, string, i2) {
  function parseWeekdayNumberMonday (line 5368) | function parseWeekdayNumberMonday(d2, string, i2) {
  function parseWeekNumberSunday (line 5372) | function parseWeekNumberSunday(d2, string, i2) {
  function parseWeekNumberISO (line 5376) | function parseWeekNumberISO(d2, string, i2) {
  function parseWeekNumberMonday (line 5380) | function parseWeekNumberMonday(d2, string, i2) {
  function parseFullYear (line 5384) | function parseFullYear(d2, string, i2) {
  function parseYear (line 5388) | function parseYear(d2, string, i2) {
  function parseZone (line 5392) | function parseZone(d2, string, i2) {
  function parseQuarter (line 5396) | function parseQuarter(d2, string, i2) {
  function parseMonthNumber (line 5400) | function parseMonthNumber(d2, string, i2) {
  function parseDayOfMonth (line 5404) | function parseDayOfMonth(d2, string, i2) {
  function parseDayOfYear (line 5408) | function parseDayOfYear(d2, string, i2) {
  function parseHour24 (line 5412) | function parseHour24(d2, string, i2) {
  function parseMinutes (line 5416) | function parseMinutes(d2, string, i2) {
  function parseSeconds (line 5420) | function parseSeconds(d2, string, i2) {
  function parseMilliseconds (line 5424) | function parseMilliseconds(d2, string, i2) {
  function parseMicroseconds (line 5428) | function parseMicroseconds(d2, string, i2) {
  function parseLiteralPercent (line 5432) | function parseLiteralPercent(d2, string, i2) {
  function parseUnixTimestamp (line 5436) | function parseUnixTimestamp(d2, string, i2) {
  function parseUnixTimestampSeconds (line 5440) | function parseUnixTimestampSeconds(d2, string, i2) {
  function formatDayOfMonth (line 5444) | function formatDayOfMonth(d2, p2) {
  function formatHour24 (line 5447) | function formatHour24(d2, p2) {
  function formatHour12 (line 5450) | function formatHour12(d2, p2) {
  function formatDayOfYear (line 5453) | function formatDayOfYear(d2, p2) {
  function formatMilliseconds (line 5456) | function formatMilliseconds(d2, p2) {
  function formatMicroseconds (line 5459) | function formatMicroseconds(d2, p2) {
  function formatMonthNumber (line 5462) | function formatMonthNumber(d2, p2) {
  function formatMinutes (line 5465) | function formatMinutes(d2, p2) {
  function formatSeconds (line 5468) | function formatSeconds(d2, p2) {
  function formatWeekdayNumberMonday (line 5471) | function formatWeekdayNumberMonday(d2) {
  function formatWeekNumberSunday (line 5475) | function formatWeekNumberSunday(d2, p2) {
  function dISO (line 5478) | function dISO(d2) {
  function formatWeekNumberISO (line 5482) | function formatWeekNumberISO(d2, p2) {
  function formatWeekdayNumberSunday (line 5486) | function formatWeekdayNumberSunday(d2) {
  function formatWeekNumberMonday (line 5489) | function formatWeekNumberMonday(d2, p2) {
  function formatYear2 (line 5492) | function formatYear2(d2, p2) {
  function formatYearISO (line 5495) | function formatYearISO(d2, p2) {
  function formatFullYear (line 5499) | function formatFullYear(d2, p2) {
  function formatFullYearISO (line 5502) | function formatFullYearISO(d2, p2) {
  function formatZone (line 5507) | function formatZone(d2) {
  function formatUTCDayOfMonth (line 5511) | function formatUTCDayOfMonth(d2, p2) {
  function formatUTCHour24 (line 5514) | function formatUTCHour24(d2, p2) {
  function formatUTCHour12 (line 5517) | function formatUTCHour12(d2, p2) {
  function formatUTCDayOfYear (line 5520) | function formatUTCDayOfYear(d2, p2) {
  function formatUTCMilliseconds (line 5523) | function formatUTCMilliseconds(d2, p2) {
  function formatUTCMicroseconds (line 5526) | function formatUTCMicroseconds(d2, p2) {
  function formatUTCMonthNumber (line 5529) | function formatUTCMonthNumber(d2, p2) {
  function formatUTCMinutes (line 5532) | function formatUTCMinutes(d2, p2) {
  function formatUTCSeconds (line 5535) | function formatUTCSeconds(d2, p2) {
  function formatUTCWeekdayNumberMonday (line 5538) | function formatUTCWeekdayNumberMonday(d2) {
  function formatUTCWeekNumberSunday (line 5542) | function formatUTCWeekNumberSunday(d2, p2) {
  function UTCdISO (line 5545) | function UTCdISO(d2) {
  function formatUTCWeekNumberISO (line 5549) | function formatUTCWeekNumberISO(d2, p2) {
  function formatUTCWeekdayNumberSunday (line 5553) | function formatUTCWeekdayNumberSunday(d2) {
  function formatUTCWeekNumberMonday (line 5556) | function formatUTCWeekNumberMonday(d2, p2) {
  function formatUTCYear (line 5559) | function formatUTCYear(d2, p2) {
  function formatUTCYearISO (line 5562) | function formatUTCYearISO(d2, p2) {
  function formatUTCFullYear (line 5566) | function formatUTCFullYear(d2, p2) {
  function formatUTCFullYearISO (line 5569) | function formatUTCFullYearISO(d2, p2) {
  function formatUTCZone (line 5574) | function formatUTCZone() {
  function formatLiteralPercent (line 5577) | function formatLiteralPercent() {
  function formatUnixTimestamp (line 5580) | function formatUnixTimestamp(d2) {
  function formatUnixTimestampSeconds (line 5583) | function formatUnixTimestampSeconds(d2) {
  function defaultLocale2 (line 5603) | function defaultLocale2(definition3) {
  function memoize (line 5613) | function memoize(method2) {
  function trimZeroes (line 5617) | function trimZeroes(numberFormat2, decimalChar) {
  function rightmostDigit (line 5630) | function rightmostDigit(str, dec) {
  function numberLocale (line 5638) | function numberLocale(locale4) {
  function resetNumberFormatDefaultLocale (line 5702) | function resetNumberFormatDefaultLocale() {
  function numberFormatLocale (line 5708) | function numberFormatLocale(definition3) {
  function numberFormatDefaultLocale (line 5711) | function numberFormatDefaultLocale(definition3) {
  function timeMultiFormat (line 5714) | function timeMultiFormat(format5, interval3, spec) {
  function timeLocale (line 5722) | function timeLocale(locale4) {
  function resetTimeFormatDefaultLocale (line 5733) | function resetTimeFormatDefaultLocale() {
  function timeFormatLocale (line 5741) | function timeFormatLocale(definition3) {
  function timeFormatDefaultLocale (line 5744) | function timeFormatDefaultLocale(definition3) {
  function locale3 (line 5748) | function locale3(numberSpec, timeSpec) {
  function defaultLocale3 (line 5753) | function defaultLocale3(numberSpec, timeSpec) {
  function resetDefaultLocale (line 5760) | function resetDefaultLocale() {
  function loaderFactory (line 5771) | function loaderFactory(fetch2, fs) {
  function load (line 5781) | async function load(uri, options) {
  function sanitize (line 5785) | async function sanitize(uri, options) {
  function fileLoader (line 5828) | function fileLoader(fs) {
  function fileReject (line 5836) | async function fileReject() {
  function httpLoader (line 5839) | function httpLoader(fetch2) {
  function httpReject (line 5845) | async function httpReject() {
  function inferType (line 5863) | function inferType(values4, field3) {
  function inferTypes (line 5878) | function inferTypes(data3, fields) {
  function delimitedFormat (line 5884) | function delimitedFormat(delimiter) {
  function dsv (line 5894) | function dsv(data3, format5) {
  function isBuffer (line 5901) | function isBuffer(_) {
  function json (line 5904) | function json(data3, format5) {
  function parseJSON (line 5909) | function parseJSON(data3, format5) {
  function topojson (line 5919) | function topojson(data3, format5) {
  function formats (line 5943) | function formats(name4, reader) {
  function responseType (line 5951) | function responseType(type3) {
  function read (line 5955) | function read(data3, schema, timeParser, utcParser) {
  function parse (line 5964) | function parse(data3, types4, timeParser, utcParser) {
  function UniqueList (line 6005) | function UniqueList(idFunc) {
  function asyncCallback (line 6026) | async function asyncCallback(df, callback) {
  function isTuple (line 6035) | function isTuple(t4) {
  function tupleid (line 6038) | function tupleid(t4) {
  function setid (line 6041) | function setid(t4, id2) {
  function ingest$1 (line 6045) | function ingest$1(datum2) {
  function derive (line 6051) | function derive(t4) {
  function rederive (line 6054) | function rederive(t4, d2) {
  function replace (line 6058) | function replace(t4, d2) {
  function stableCompare (line 6061) | function stableCompare(cmp, f2) {
  function isChangeSet (line 6064) | function isChangeSet(v3) {
  function changeset (line 6067) | function changeset() {
  function Parameters (line 6185) | function Parameters() {
  method set (line 6203) | set(name4, index4, value3, force) {
  method modified (line 6227) | modified(name4, index4) {
  method clear (line 6246) | clear() {
  function Operator (line 6256) | function Operator(init2, update3, params2, react) {
  function flag (line 6268) | function flag(bit) {
  method targets (line 6282) | targets() {
  method set (line 6291) | set(value3) {
  method parameters (line 6332) | parameters(params2, react, initonly) {
  method marshall (line 6379) | marshall(stamp) {
  method detach (line 6405) | detach() {
  method evaluate (line 6431) | evaluate(pulse2) {
  method run (line 6452) | run(pulse2) {
  function add (line 6464) | function add(init2, update3, params2, react) {
  function connect (line 6485) | function connect(target2, sources) {
  function EventStream (line 6495) | function EventStream(filter3, apply3, receive) {
  function stream (line 6502) | function stream(filter3, apply3, receive) {
  method targets (line 6508) | targets() {
  method consume (line 6511) | consume(_) {
  method receive (line 6516) | receive(evt) {
  method filter (line 6526) | filter(filter3) {
  method apply (line 6531) | apply(apply3) {
  method merge (line 6536) | merge() {
  method throttle (line 6544) | throttle(pause) {
  method debounce (line 6556) | debounce(delay) {
  method between (line 6565) | between(a4, b3) {
  method detach (line 6571) | detach() {
  function events (line 6576) | function events(source4, type3, filter3, apply3) {
  function parse2 (line 6599) | function parse2(data3, format5) {
  function ingest (line 6603) | function ingest(target2, data3, format5) {
  function request (line 6607) | async function request(url, format5) {
  function preload (line 6630) | async function preload(target2, url, format5) {
  function loadPending (line 6638) | function loadPending(df) {
  function on (line 6653) | function on(source4, target2, update3, params2, options) {
  function onStream (line 6658) | function onStream(df, stream2, target2, update3, params2, options) {
  function onOperator (line 6676) | function onOperator(df, source4, target2, update3, params2, options) {
  function updater (line 6692) | function updater(target2, update3) {
  function rank (line 6702) | function rank(op) {
  function rerank (line 6705) | function rerank(op) {
  function Pulse (line 6729) | function Pulse(dataflow, stamp, encode2) {
  function materialize (line 6738) | function materialize(data3, filter3) {
  function filter (line 6743) | function filter(pulse2, flags) {
  function addFilter (line 6750) | function addFilter(a4, b3) {
  method fork (line 6813) | fork(flags) {
  method clone (line 6823) | clone() {
  method addAll (line 6841) | addAll() {
  method init (line 6866) | init(src, flags) {
  method runAfter (line 6908) | runAfter(func) {
  method changed (line 6918) | changed(flags) {
  method reflow (line 6929) | reflow(fork) {
  method clean (line 6942) | clean(value3) {
  method modifies (line 6956) | modifies(_) {
  method modified (line 6974) | modified(_, nomod) {
  method filter (line 6993) | filter(flags, filter3) {
  method materialize (line 7008) | materialize(flags) {
  method visit (line 7037) | visit(flags, visitor) {
  function MultiPulse (line 7059) | function MultiPulse(dataflow, stamp, pulses, encode2) {
  method fork (line 7087) | fork(flags) {
  method changed (line 7096) | changed(flags) {
  method modified (line 7099) | modified(_) {
  method filter (line 7103) | filter() {
  method materialize (line 7106) | materialize() {
  method visit (line 7109) | visit(flags, visitor) {
  function evaluate (line 7126) | async function evaluate(encode2, prerun, postrun) {
  function runAsync (line 7191) | async function runAsync(encode2, prerun, postrun) {
  function run (line 7197) | function run(encode2, prerun, postrun) {
  function runAfter (line 7200) | function runAfter(callback, enqueue2, priority) {
  function reentrant (line 7214) | function reentrant(df) {
  function enqueue (line 7218) | function enqueue(op, force) {
  function getPulse (line 7226) | function getPulse(op, encode2) {
  function singlePulse (line 7230) | function singlePulse(p2, s2) {
  function touch (line 7244) | function touch(op, options) {
  function update (line 7254) | function update(op, value3, options) {
  function pulse (line 7261) | function pulse(op, changeset2, options) {
  function Heap (line 7268) | function Heap(cmp) {
  function siftdown (line 7292) | function siftdown(array4, start, idx, cmp) {
  function siftup (line 7307) | function siftup(array4, idx, cmp) {
  function Dataflow (line 7322) | function Dataflow() {
  function logMethod (line 7338) | function logMethod(method2) {
  method stamp (line 7352) | stamp() {
  method loader (line 7367) | loader(_) {
  method locale (line 7384) | locale(_) {
  method logger (line 7400) | logger(logger3) {
  function Transform (line 7470) | function Transform(init2, params2) {
  method run (line 7482) | run(pulse2) {
  method evaluate (line 7505) | evaluate(pulse2) {
  method transform (line 7518) | transform() {
  function definition (line 7522) | function definition(type3) {
  function transform (line 7526) | function transform(type3) {
  function quantiles (line 7594) | function quantiles(array4, p2, f2) {
  function quartiles (line 7599) | function quartiles(array4, f2) {
  function estimateBandwidth (line 7602) | function estimateBandwidth(array4, f2) {
  function bin2 (line 7606) | function bin2(_) {
  function setRandom (line 7642) | function setRandom(r2) {
  function bootstrapCI (line 7645) | function bootstrapCI(array4, samples, alpha, f2) {
  function dotbin (line 7658) | function dotbin(array4, step, smooth, f2) {
  function smoothing (line 7676) | function smoothing(v3, thresh) {
  function lcg (line 7693) | function lcg(seed) {
  function integer (line 7699) | function integer(min4, max4) {
  function sampleNormal (line 7743) | function sampleNormal(mean2, stdev) {
  function densityNormal (line 7762) | function densityNormal(value3, mean2, stdev) {
  function cumulativeNormal (line 7767) | function cumulativeNormal(value3, mean2, stdev) {
  function quantileNormal (line 7804) | function quantileNormal(p2, mean2, stdev) {
  function erfinv (line 7808) | function erfinv(x5) {
  function gaussian (line 7880) | function gaussian(mean2, stdev) {
  function kde (line 7906) | function kde(support, bandwidth2) {
  function sampleLogNormal (line 7948) | function sampleLogNormal(mean2, stdev) {
  function densityLogNormal (line 7953) | function densityLogNormal(value3, mean2, stdev) {
  function cumulativeLogNormal (line 7960) | function cumulativeLogNormal(value3, mean2, stdev) {
  function quantileLogNormal (line 7963) | function quantileLogNormal(p2, mean2, stdev) {
  function lognormal (line 7966) | function lognormal(mean2, stdev) {
  function mixture (line 7992) | function mixture(dists, weights) {
  function sampleUniform (line 8057) | function sampleUniform(min4, max4) {
  function densityUniform (line 8064) | function densityUniform(value3, min4, max4) {
  function cumulativeUniform (line 8071) | function cumulativeUniform(value3, min4, max4) {
  function quantileUniform (line 8078) | function quantileUniform(p2, min4, max4) {
  function uniform (line 8085) | function uniform(min4, max4) {
  function constant2 (line 8115) | function constant2(data3, x5, y5) {
  function ols (line 8128) | function ols(uX, uY, uXY, uX2) {
  function points (line 8132) | function points(data3, x5, y5, sort3) {
  function visitPoints (line 8155) | function visitPoints(data3, x5, y5, callback) {
  function rSquared (line 8165) | function rSquared(data3, x5, y5, uY, predict) {
  function linear (line 8174) | function linear(data3, x5, y5) {
  function log2 (line 8190) | function log2(data3, x5, y5) {
  function exp2 (line 8207) | function exp2(data3, x5, y5) {
  function pow2 (line 8226) | function pow2(data3, x5, y5) {
  function quad (line 8245) | function quad(data3, x5, y5) {
  function poly (line 8268) | function poly(data3, x5, y5, order) {
  function uncenter (line 8301) | function uncenter(k2, a4, x5, y5) {
  function gaussianElimination (line 8317) | function gaussianElimination(matrix) {
  function loess (line 8349) | function loess(data3, x5, y5, bandwidth2) {
  function tricube (line 8382) | function tricube(x5) {
  function updateInterval (line 8385) | function updateInterval(xv, i2, interval3) {
  function output (line 8395) | function output(xv, yhat, ux, uy) {
  function sampleCurve (line 8413) | function sampleCurve(f2, extent2, minSteps, maxSteps) {
  function scaleY (line 8447) | function scaleY(init2, points2) {
  function angleDelta (line 8458) | function angleDelta(p2, q2, r2, sx, sy) {
  function multikey (line 8464) | function multikey(f2) {
  function groupkey (line 8474) | function groupkey(fields) {
  function measureName (line 8479) | function measureName(op, field3, as) {
  function measure (line 8653) | function measure(key2, value3) {
  function createMeasure (line 8663) | function createMeasure(op, param2, name4) {
  function compareIndex (line 8666) | function compareIndex(a4, b3) {
  function resolve (line 8669) | function resolve(agg) {
  function init (line 8681) | function init() {
  function add2 (line 8686) | function add2(v3, t4) {
  function rem (line 8695) | function rem(v3, t4) {
  function set2 (line 8704) | function set2(t4) {
  function compileMeasures (line 8708) | function compileMeasures(agg, field3) {
  function TupleStore (line 8724) | function TupleStore(key2) {
  function Aggregate (line 8823) | function Aggregate(params2) {
  method transform (line 8884) | transform(_, pulse2) {
  method cross (line 8907) | cross() {
  method init (line 8931) | init(_) {
  method cell (line 8988) | cell(key2, t4) {
  method newcell (line 9002) | newcell(key2, t4) {
  method newtuple (line 9023) | newtuple(t4, p2) {
  method clean (line 9030) | clean() {
  method add (line 9039) | add(t4) {
  method rem (line 9049) | rem(t4) {
  method celltuple (line 9059) | celltuple(cell2) {
  method changes (line 9075) | changes(out) {
  function Bin (line 9097) | function Bin(params2) {
  method transform (line 9165) | transform(_, pulse2) {
  method _bins (line 9181) | _bins(_) {
  function SortedList (line 9202) | function SortedList(idFunc, source4, input) {
  function Collect (line 9226) | function Collect(params2) {
  method transform (line 9240) | transform(_, pulse2) {
  function Compare (line 9251) | function Compare(params2) {
  function update$5 (line 9255) | function update$5(_) {
  function CountPattern (line 9258) | function CountPattern(params2) {
  function tokenize (line 9292) | function tokenize(text4, tcase, match3) {
  method transform (line 9304) | transform(_, pulse2) {
  method _parameterCheck (line 9320) | _parameterCheck(_, pulse2) {
  method _finish (line 9336) | _finish(pulse2, as) {
  function Cross (line 9359) | function Cross(params2) {
  method transform (line 9379) | transform(_, pulse2) {
  function cross (line 9393) | function cross(input, a4, b3, filter3) {
  function parse3 (line 9418) | function parse3(def2, data3) {
  function Density (line 9435) | function Density(params2) {
  method transform (line 9547) | transform(_, pulse2) {
  function source (line 9571) | function source(pulse2) {
  function fieldNames (line 9574) | function fieldNames(fields, as) {
  function partition$1 (line 9578) | function partition$1(data3, groupby, field3) {
  function DotBin (line 9599) | function DotBin(params2) {
  method transform (line 9630) | transform(_, pulse2) {
  function Expression (line 9653) | function Expression(params2) {
  function update$4 (line 9658) | function update$4(_) {
  function Extent (line 9662) | function Extent(params2) {
  method transform (line 9675) | transform(_, pulse2) {
  function Subflow (line 9698) | function Subflow(pulse2, parent) {
  method connect (line 9708) | connect(target2) {
  method add (line 9717) | add(t4) {
  method rem (line 9725) | rem(t4) {
  method mod (line 9733) | mod(t4) {
  method init (line 9741) | init(pulse2) {
  method evaluate (line 9749) | evaluate() {
  function Facet (line 9753) | function Facet(params2) {
  method activate (line 9765) | activate(flow) {
  method subflow (line 9769) | subflow(key2, flow, pulse2, parent) {
  method clean (line 9785) | clean() {
  method initTargets (line 9801) | initTargets(act) {
  method transform (line 9812) | transform(_, pulse2) {
  function Field (line 9865) | function Field(params2) {
  function update$3 (line 9869) | function update$3(_) {
  function Filter (line 9872) | function Filter(params2) {
  method transform (line 9887) | transform(_, pulse2) {
  function Flatten (line 9920) | function Flatten(params2) {
  method transform (line 9943) | transform(_, pulse2) {
  function Fold (line 9965) | function Fold(params2) {
  method transform (line 9987) | transform(_, pulse2) {
  function Formula (line 10002) | function Formula(params2) {
  method transform (line 10024) | transform(_, pulse2) {
  function Generate (line 10035) | function Generate(params2) {
  method transform (line 10039) | transform(_, pulse2) {
  function Impute (line 10065) | function Impute(params2) {
  function getValue (line 10098) | function getValue(_) {
  function getField (line 10109) | function getField(_) {
  method transform (line 10114) | transform(_, pulse2) {
  function partition (line 10138) | function partition(data3, groupby, key2, keyvals) {
  function JoinAggregate (line 10156) | function JoinAggregate(params2) {
  method transform (line 10189) | transform(_, pulse2) {
  method changes (line 10206) | changes() {
  function KDE (line 10220) | function KDE(params2) {
  method transform (line 10277) | transform(_, pulse2) {
  function Key (line 10307) | function Key(params2) {
  function update$2 (line 10311) | function update$2(_) {
  function Load (line 10314) | function Load(params2) {
  method transform (line 10319) | transform(_, pulse2) {
  function stop (line 10340) | function stop(_) {
  function output2 (line 10343) | function output2(op, pulse2, data3) {
  function Lookup (line 10352) | function Lookup(params2) {
  method transform (line 10391) | transform(_, pulse2) {
  function MultiExtent (line 10431) | function MultiExtent(params2) {
  function update$1 (line 10435) | function update$1(_) {
  function MultiValues (line 10448) | function MultiValues(params2) {
  function update2 (line 10452) | function update2(_) {
  function Params (line 10455) | function Params(params2) {
  method transform (line 10459) | transform(_, pulse2) {
  function Pivot (line 10465) | function Pivot(params2) {
  method transform (line 10502) | transform(_, pulse2) {
  function aggregateParams (line 10506) | function aggregateParams(_, pulse2) {
  function get (line 10518) | function get(k2, key2, value3, fields) {
  function pivotKeys (line 10521) | function pivotKeys(key2, limit, pulse2) {
  function PreFacet (line 10533) | function PreFacet(params2) {
  method transform (line 10537) | transform(_, pulse2) {
  function Project (line 10567) | function Project(params2) {
  method transform (line 10588) | transform(_, pulse2) {
  function project (line 10613) | function project(s2, t4, fields, as) {
  function Proxy2 (line 10619) | function Proxy2(params2) {
  method transform (line 10623) | transform(_, pulse2) {
  function Quantile (line 10628) | function Quantile(params2) {
  method transform (line 10662) | transform(_, pulse2) {
  function Relay (line 10686) | function Relay(params2) {
  method transform (line 10690) | transform(_, pulse2) {
  function Sample (line 10722) | function Sample(params2) {
  method transform (line 10736) | transform(_, pulse2) {
  function Sequence (line 10795) | function Sequence(params2) {
  method transform (line 10823) | transform(_, pulse2) {
  function Sieve (line 10836) | function Sieve(params2) {
  method transform (line 10841) | transform(_, pulse2) {
  function TimeUnit (line 10846) | function TimeUnit(params2) {
  method transform (line 10894) | transform(_, pulse2) {
  method _floor (line 10920) | _floor(_, pulse2) {
  function TupleIndex (line 10941) | function TupleIndex(params2) {
  method transform (line 10945) | transform(_, pulse2) {
  function Values (line 10962) | function Values(params2) {
  method transform (line 10966) | transform(_, pulse2) {
  function WindowOp (line 10973) | function WindowOp(op, field3, param2, as) {
  function find (line 11098) | function find(field3, data3, index4) {
  function WindowState (line 11106) | function WindowState(_) {
  function cell (line 11157) | function cell(measures, counts, countOnly) {
  function Window (line 11201) | function Window(params2) {
  method transform (line 11257) | transform(_, pulse2) {
  method group (line 11278) | group(key2) {
  function processPartition (line 11291) | function processPartition(list, state, cmp, _) {
  function setWindow (line 11308) | function setWindow(w3, f2, i2, n2) {
  function adjustRange (line 11315) | function adjustRange(w3, bisect2) {
  function constant_default (line 11333) | function constant_default(x5) {
  function acos (line 11351) | function acos(x5) {
  function asin (line 11354) | function asin(x5) {
  function append (line 11363) | function append(strings) {
  function appendRound (line 11369) | function appendRound(digits) {
  method constructor (line 11382) | constructor(digits) {
  method moveTo (line 11388) | moveTo(x5, y5) {
  method closePath (line 11391) | closePath() {
  method lineTo (line 11397) | lineTo(x5, y5) {
  method quadraticCurveTo (line 11400) | quadraticCurveTo(x12, y12, x5, y5) {
  method bezierCurveTo (line 11403) | bezierCurveTo(x12, y12, x22, y22, x5, y5) {
  method arcTo (line 11406) | arcTo(x12, y12, x22, y22, r2) {
  method arc (line 11423) | arc(x5, y5, r2, a0, a1, ccw) {
  method rect (line 11440) | rect(x5, y5, w3, h3) {
  method toString (line 11443) | toString() {
  function path (line 11447) | function path() {
  function withPath (line 11453) | function withPath(shape2) {
  function arcInnerRadius (line 11470) | function arcInnerRadius(d2) {
  function arcOuterRadius (line 11473) | function arcOuterRadius(d2) {
  function arcStartAngle (line 11476) | function arcStartAngle(d2) {
  function arcEndAngle (line 11479) | function arcEndAngle(d2) {
  function arcPadAngle (line 11482) | function arcPadAngle(d2) {
  function intersect (line 11485) | function intersect(x06, y06, x12, y12, x22, y22, x32, y32) {
  function cornerTangents (line 11491) | function cornerTangents(x06, y06, x12, y12, r1, rc, cw2) {
  function arc_default (line 11503) | function arc_default() {
  function array_default (line 11600) | function array_default(x5) {
  function Linear (line 11605) | function Linear(context3) {
  function linear_default (line 11638) | function linear_default(context3) {
  function x (line 11643) | function x(p2) {
  function y (line 11646) | function y(p2) {
  function line_default (line 11651) | function line_default(x5, y5) {
  function area_default (line 11686) | function area_default(x06, y06, y12) {
  method draw (line 11761) | draw(context3, size) {
  function Symbol2 (line 11769) | function Symbol2(type3, size) {
  function noop_default (line 11792) | function noop_default() {
  function point (line 11796) | function point(that, x5, y5) {
  function Basis (line 11806) | function Basis(context3) {
  function basis_default (line 11854) | function basis_default(context3) {
  function BasisClosed (line 11859) | function BasisClosed(context3) {
  function basisClosed_default (line 11914) | function basisClosed_default(context3) {
  function BasisOpen (line 11919) | function BasisOpen(context3) {
  function basisOpen_default (line 11962) | function basisOpen_default(context3) {
  function Bundle (line 11967) | function Bundle(context3, beta) {
  function bundle2 (line 11998) | function bundle2(context3) {
  function point2 (line 12008) | function point2(that, x5, y5) {
  function Cardinal (line 12018) | function Cardinal(context3, tension) {
  function cardinal (line 12068) | function cardinal(context3) {
  function CardinalClosed (line 12078) | function CardinalClosed(context3, tension) {
  function cardinal (line 12133) | function cardinal(context3) {
  function CardinalOpen (line 12143) | function CardinalOpen(context3, tension) {
  function cardinal (line 12187) | function cardinal(context3) {
  function point3 (line 12197) | function point3(that, x5, y5) {
  function CatmullRom (line 12211) | function CatmullRom(context3, alpha) {
  function catmullRom (line 12266) | function catmullRom(context3) {
  function CatmullRomClosed (line 12276) | function CatmullRomClosed(context3, alpha) {
  function catmullRom (line 12337) | function catmullRom(context3) {
  function CatmullRomOpen (line 12347) | function CatmullRomOpen(context3, alpha) {
  function catmullRom (line 12397) | function catmullRom(context3) {
  function LinearClosed (line 12407) | function LinearClosed(context3) {
  function linearClosed_default (line 12425) | function linearClosed_default(context3) {
  function sign (line 12430) | function sign(x5) {
  function slope3 (line 12433) | function slope3(that, x22, y22) {
  function slope2 (line 12437) | function slope2(that, t4) {
  function point4 (line 12441) | function point4(that, t04, t13) {
  function MonotoneX (line 12445) | function MonotoneX(context3) {
  function MonotoneY (line 12496) | function MonotoneY(context3) {
  function ReflectContext (line 12502) | function ReflectContext(context3) {
  function monotoneX (line 12519) | function monotoneX(context3) {
  function monotoneY (line 12522) | function monotoneY(context3) {
  function Natural (line 12527) | function Natural(context3) {
  function controlPoints (line 12563) | function controlPoints(x5) {
  function natural_default (line 12575) | function natural_default(context3) {
  function Step (line 12580) | function Step(context3, t4) {
  function step_default (line 12625) | function step_default(context3) {
  function stepBefore (line 12628) | function stepBefore(context3) {
  function stepAfter (line 12631) | function stepAfter(context3) {
  function domCanvas (line 12636) | function domCanvas(w3, h3) {
  function initRange (line 12650) | function initRange(domain4, range7) {
  function initInterpolator (line 12663) | function initInterpolator(domain4, interpolator) {
  function ordinal (line 12684) | function ordinal() {
  function define_default (line 12749) | function define_default(constructor, factory, prototype2) {
  function extend2 (line 12753) | function extend2(parent, definition3) {
  function Color (line 12760) | function Color() {
  method copy (line 12925) | copy(channels) {
  method displayable (line 12928) | displayable() {
  function color_formatHex (line 12939) | function color_formatHex() {
  function color_formatHex8 (line 12942) | function color_formatHex8() {
  function color_formatHsl (line 12945) | function color_formatHsl() {
  function color_formatRgb (line 12948) | function color_formatRgb() {
  function color (line 12951) | function color(format5) {
  function rgbn (line 12956) | function rgbn(n2) {
  function rgba (line 12959) | function rgba(r2, g2, b3, a4) {
  function rgbConvert (line 12963) | function rgbConvert(o2) {
  function rgb (line 12969) | function rgb(r2, g2, b3, opacity2) {
  function Rgb (line 12972) | function Rgb(r2, g2, b3, opacity2) {
  method brighter (line 12979) | brighter(k2) {
  method darker (line 12983) | darker(k2) {
  method rgb (line 12987) | rgb() {
  method clamp (line 12990) | clamp() {
  method displayable (line 12993) | displayable() {
  function rgb_formatHex (line 13003) | function rgb_formatHex() {
  function rgb_formatHex8 (line 13006) | function rgb_formatHex8() {
  function rgb_formatRgb (line 13009) | function rgb_formatRgb() {
  function clampa (line 13013) | function clampa(opacity2) {
  function clampi (line 13016) | function clampi(value3) {
  function hex (line 13019) | function hex(value3) {
  function hsla (line 13023) | function hsla(h3, s2, l2, a4) {
  function hslConvert (line 13029) | function hslConvert(o2) {
  function hsl (line 13047) | function hsl(h3, s2, l2, opacity2) {
  function Hsl (line 13050) | function Hsl(h3, s2, l2, opacity2) {
  method brighter (line 13057) | brighter(k2) {
  method darker (line 13061) | darker(k2) {
  method rgb (line 13065) | rgb() {
  method clamp (line 13074) | clamp() {
  method displayable (line 13077) | displayable() {
  method formatHsl (line 13080) | formatHsl() {
  function clamph (line 13085) | function clamph(value3) {
  function clampt (line 13089) | function clampt(value3) {
  function hsl2rgb (line 13092) | function hsl2rgb(h3, m1, m22) {
  function labConvert (line 13109) | function labConvert(o2) {
  function lab (line 13121) | function lab(l2, a4, b3, opacity2) {
  function Lab (line 13124) | function Lab(l2, a4, b3, opacity2) {
  method brighter (line 13131) | brighter(k2) {
  method darker (line 13134) | darker(k2) {
  method rgb (line 13137) | rgb() {
  function xyz2lab (line 13150) | function xyz2lab(t4) {
  function lab2xyz (line 13153) | function lab2xyz(t4) {
  function lrgb2rgb (line 13156) | function lrgb2rgb(x5) {
  function rgb2lrgb (line 13159) | function rgb2lrgb(x5) {
  function hclConvert (line 13162) | function hclConvert(o2) {
  function hcl (line 13169) | function hcl(h3, c4, l2, opacity2) {
  function Hcl (line 13172) | function Hcl(h3, c4, l2, opacity2) {
  function hcl2lab (line 13178) | function hcl2lab(o2) {
  method brighter (line 13184) | brighter(k2) {
  method darker (line 13187) | darker(k2) {
  method rgb (line 13190) | rgb() {
  function cubehelixConvert (line 13204) | function cubehelixConvert(o2) {
  function cubehelix (line 13210) | function cubehelix(h3, s2, l2, opacity2) {
  function Cubehelix (line 13213) | function Cubehelix(h3, s2, l2, opacity2) {
  method brighter (line 13220) | brighter(k2) {
  method darker (line 13224) | darker(k2) {
  method rgb (line 13228) | rgb() {
  function basis (line 13240) | function basis(t13, v0, v1, v22, v3) {
  function basis_default2 (line 13244) | function basis_default2(values4) {
  function basisClosed_default2 (line 13253) | function basisClosed_default2(values4) {
  function linear2 (line 13265) | function linear2(a4, d2) {
  function exponential (line 13270) | function exponential(a4, b3, y5) {
  function hue (line 13275) | function hue(a4, b3) {
  function gamma (line 13279) | function gamma(y5) {
  function nogamma (line 13284) | function nogamma(a4, b3) {
  function rgb2 (line 13292) | function rgb2(start, end) {
  function rgbSpline (line 13305) | function rgbSpline(spline) {
  function numberArray_default (line 13330) | function numberArray_default(a4, b3) {
  function isNumberArray (line 13338) | function isNumberArray(x5) {
  function array_default2 (line 13343) | function array_default2(a4, b3) {
  function genericArray (line 13346) | function genericArray(a4, b3) {
  function date_default (line 13357) | function date_default(a4, b3) {
  function number_default (line 13365) | function number_default(a4, b3) {
  function object_default (line 13372) | function object_default(a4, b3) {
  function zero3 (line 13392) | function zero3(b3) {
  function one2 (line 13397) | function one2(b3) {
  function string_default (line 13402) | function string_default(a4, b3) {
  function value_default (line 13432) | function value_default(a4, b3) {
  function discrete_default (line 13438) | function discrete_default(range7) {
  function hue_default (line 13446) | function hue_default(a4, b3) {
  function round_default (line 13455) | function round_default(a4, b3) {
  function decompose_default (line 13471) | function decompose_default(a4, b3, c4, d2, e4, f2) {
  function parseCss (line 13489) | function parseCss(value3) {
  function parseSvg (line 13493) | function parseSvg(value3) {
  function interpolateTransform (line 13503) | function interpolateTransform(parse7, pxComma, pxParen, degParen) {
  function cosh (line 13559) | function cosh(x5) {
  function sinh (line 13562) | function sinh(x5) {
  function tanh (line 13565) | function tanh(x5) {
  function zoom3 (line 13569) | function zoom3(p02, p1) {
  function hsl2 (line 13603) | function hsl2(hue2) {
  function lab2 (line 13619) | function lab2(start, end) {
  function hcl2 (line 13631) | function hcl2(hue2) {
  function cubehelix2 (line 13647) | function cubehelix2(hue2) {
  function piecewise (line 13668) | function piecewise(interpolate3, values4) {
  function quantize_default2 (line 13679) | function quantize_default2(interpolator, n2) {
  function constants (line 13686) | function constants(x5) {
  function number2 (line 13693) | function number2(x5) {
  function identity3 (line 13699) | function identity3(x5) {
  function normalize (line 13702) | function normalize(a4, b3) {
  function clamper (line 13707) | function clamper(a4, b3) {
  function bimap (line 13714) | function bimap(domain4, range7, interpolate3) {
  function polymap (line 13722) | function polymap(domain4, range7, interpolate3) {
  function copy (line 13737) | function copy(source4, target2) {
  function transformer (line 13740) | function transformer() {
  function continuous (line 13778) | function continuous() {
  function tickFormat (line 13783) | function tickFormat(start, stop2, count2, specifier) {
  function linearish (line 13810) | function linearish(scale7) {
  function linear3 (line 13855) | function linear3() {
  function identity4 (line 13865) | function identity4(domain4) {
  function nice (line 13885) | function nice(domain4, interval3) {
  function transformLog (line 13898) | function transformLog(x5) {
  function transformExp (line 13901) | function transformExp(x5) {
  function transformLogn (line 13904) | function transformLogn(x5) {
  function transformExpn (line 13907) | function transformExpn(x5) {
  function pow10 (line 13910) | function pow10(x5) {
  function powp (line 13913) | function powp(base) {
  function logp (line 13916) | function logp(base) {
  function reflect (line 13919) | function reflect(f2) {
  function loggish (line 13922) | function loggish(transform4) {
  function log3 (line 14003) | function log3() {
  function transformSymlog (line 14011) | function transformSymlog(c4) {
  function transformSymexp (line 14016) | function transformSymexp(c4) {
  function symlogish (line 14021) | function symlogish(transform4) {
  function symlog2 (line 14028) | function symlog2() {
  function transformPow (line 14037) | function transformPow(exponent) {
  function transformSqrt (line 14042) | function transformSqrt(x5) {
  function transformSquare (line 14045) | function transformSquare(x5) {
  function powish (line 14048) | function powish(transform4) {
  function pow3 (line 14058) | function pow3() {
  function sqrt2 (line 14066) | function sqrt2() {
  function quantile2 (line 14071) | function quantile2() {
  function quantize (line 14112) | function quantize() {
  function threshold (line 14146) | function threshold() {
  function date (line 14171) | function date(t4) {
  function number3 (line 14174) | function number3(t4) {
  function calendar (line 14177) | function calendar(ticks2, tickInterval, year, month, week2, day, hour, m...
  function time (line 14206) | function time() {
  function utcTime (line 14211) | function utcTime() {
  function transformer2 (line 14216) | function transformer2() {
  function copy2 (line 14246) | function copy2(source4, target2) {
  function sequential (line 14249) | function sequential() {
  function sequentialLog (line 14256) | function sequentialLog() {
  function sequentialSymlog (line 14263) | function sequentialSymlog() {
  function sequentialPow (line 14270) | function sequentialPow() {
  function sequentialSqrt (line 14277) | function sequentialSqrt() {
  function transformer3 (line 14282) | function transformer3() {
  function diverging (line 14312) | function diverging() {
  function divergingLog (line 14319) | function divergingLog() {
  function divergingSymlog (line 14326) | function divergingSymlog() {
  function divergingPow (line 14333) | function divergingPow() {
  function divergingSqrt (line 14340) | function divergingSqrt() {
  function colors_default (line 14345) | function colors_default(specifier) {
  function bandSpace (line 14382) | function bandSpace(count2, paddingInner2, paddingOuter2) {
  function invertRange (line 14408) | function invertRange(scale7) {
  function invertRangeExtent (line 14419) | function invertRangeExtent(scale7) {
  function band (line 14440) | function band() {
  function pointish (line 14558) | function pointish(scale7) {
  function point5 (line 14567) | function point5() {
  function numbers3 (line 14571) | function numbers3(_) {
  function scaleBinOrdinal (line 14575) | function scaleBinOrdinal() {
  function registerScale (line 14606) | function registerScale(scale7) {
  function isRegisteredScale (line 14610) | function isRegisteredScale(scale7) {
  function create (line 14613) | function create(type3, constructor, metadata2) {
  function scale (line 14625) | function scale(type3, scale7, metadata2) {
  function isValidScaleType (line 14659) | function isValidScaleType(type3) {
  function hasType (line 14662) | function hasType(key2, type3) {
  function isContinuous (line 14666) | function isContinuous(key2) {
  function isDiscrete (line 14669) | function isDiscrete(key2) {
  function isDiscretizing (line 14672) | function isDiscretizing(key2) {
  function isLogarithmic (line 14675) | function isLogarithmic(key2) {
  function isTemporal (line 14678) | function isTemporal(key2) {
  function isInterpolating (line 14681) | function isInterpolating(key2) {
  function isQuantile (line 14684) | function isQuantile(key2) {
  function interpolateRange (line 14688) | function interpolateRange(interpolator, range7) {
  function interpolateColors (line 14694) | function interpolateColors(colors2, type3, gamma2) {
  function quantizeInterpolator (line 14697) | function quantizeInterpolator(interpolator, count2) {
  function scaleFraction (line 14702) | function scaleFraction(scale$12, min4, max4) {
  function interpolate (line 14715) | function interpolate(type3, gamma2) {
  function method (line 14719) | function method(type3) {
  function colors (line 14794) | function colors(palette) {
  function apply (line 14802) | function apply(_, f2) {
  function scheme (line 14808) | function scheme(name4, scheme3) {
  function tickCount (line 14823) | function tickCount(scale7, count2, minStep) {
  function validTicks (line 14843) | function validTicks(scale7, ticks2, count2) {
  function tickValues (line 14865) | function tickValues(scale7, count2) {
  function tickFormat2 (line 14868) | function tickFormat2(locale4, scale7, count2, specifier, formatType, noS...
  function tickLog (line 14891) | function tickLog(scale7, count2, values4) {
  function labelValues (line 14909) | function labelValues(scale7, count2) {
  function thresholdFormat (line 14912) | function thresholdFormat(locale4, scale7, specifier) {
  function thresholdValues (line 14920) | function thresholdValues(thresholds) {
  function binValues (line 14925) | function binValues(bins2) {
  function labelFormat (line 14931) | function labelFormat(locale4, scale7, count2, type3, specifier, formatTy...
  function labelFraction (line 14943) | function labelFraction(scale7) {
  function format3 (line 14954) | function format3(locale4, scale7, specifier, formatType) {
  function domainCaption (line 14961) | function domainCaption(locale4, scale7, opt) {
  function resetSVGGradientId (line 14978) | function resetSVGGradientId() {
  function isGradient (line 14982) | function isGradient(value3) {
  function gradientRef (line 14985) | function gradientRef(g2, defs, base) {
  function get3 (line 15008) | function get3(val, def2) {
  function Gradient (line 15011) | function Gradient(p02, p1) {
  function curves (line 15097) | function curves(type3, orientation, tension) {
  function parse4 (line 15123) | function parse4(path3) {
  function parseParams (line 15148) | function parseParams(type3, paramCount, segment) {
  function segments (line 15175) | function segments(x5, y5, rx, ry, large, sweep, rotateX, ox, oy) {
  function bezier (line 15225) | function bezier(params2) {
  function scale$1 (line 15251) | function scale$1(current2, sX, sY) {
  function pathRender (line 15272) | function pathRender(context3, path3, l2, t4, sX, sY) {
  function drawArc (line 15443) | function drawArc(context3, x5, y5, coords) {
  function symbols2 (line 15585) | function symbols2(_) {
  function customSymbol (line 15589) | function customSymbol(path3) {
  function rectangleX (line 15601) | function rectangleX(d2) {
  function rectangleY (line 15604) | function rectangleY(d2) {
  function rectangleWidth (line 15607) | function rectangleWidth(d2) {
  function rectangleHeight (line 15610) | function rectangleHeight(d2) {
  function number4 (line 15613) | function number4(_) {
  function clamp (line 15616) | function clamp(value3, min4, max4) {
  function vg_rect (line 15619) | function vg_rect() {
  function vg_trail (line 15697) | function vg_trail() {
  function value$1 (line 15781) | function value$1(a4, b3) {
  function hasCornerRadius (line 15811) | function hasCornerRadius(item) {
  function arc$1 (line 15814) | function arc$1(context3, item) {
  function area$1 (line 15817) | function area$1(context3, items) {
  function line$1 (line 15821) | function line$1(context3, items) {
  function rectangle (line 15825) | function rectangle(context3, item, x5, y5) {
  function shape$1 (line 15828) | function shape$1(context3, item) {
  function symbol$1 (line 15831) | function symbol$1(context3, item) {
  function trail$1 (line 15834) | function trail$1(context3, items) {
  function resetSVGClipId (line 15838) | function resetSVGClipId() {
  function clip$1 (line 15841) | function clip$1(renderer, item, size) {
  function Bounds (line 15855) | function Bounds(b3) {
  method clone (line 15860) | clone() {
  method clear (line 15863) | clear() {
  method empty (line 15870) | empty() {
  method equals (line 15873) | equals(b3) {
  method set (line 15876) | set(x12, y12, x22, y22) {
  method add (line 15893) | add(x5, y5) {
  method expand (line 15900) | expand(d2) {
  method round (line 15907) | round() {
  method scale (line 15914) | scale(s2) {
  method translate (line 15921) | translate(dx, dy) {
  method rotate (line 15928) | rotate(angle2, x5, y5) {
  method rotatedPoints (line 15932) | rotatedPoints(angle2, x5, y5) {
  method union (line 15941) | union(b3) {
  method intersect (line 15948) | intersect(b3) {
  method encloses (line 15955) | encloses(b3) {
  method alignsWith (line 15958) | alignsWith(b3) {
  method intersects (line 15961) | intersects(b3) {
  method contains (line 15964) | contains(x5, y5) {
  method width (line 15967) | width() {
  method height (line 15970) | height() {
  function Item (line 15974) | function Item(mark) {
  function GroupItem (line 15978) | function GroupItem(mark) {
  method constructor (line 15984) | constructor(customLoader) {
  method pending (line 15988) | pending() {
  method sanitizeURL (line 15991) | sanitizeURL(uri) {
  method loadImage (line 16004) | loadImage(uri) {
  method ready (line 16031) | ready() {
  function increment (line 16044) | function increment(loader2) {
  function decrement (line 16047) | function decrement(loader2) {
  function boundStroke (line 16050) | function boundStroke(bounds2, item, miter) {
  function miterAdjustment (line 16057) | function miterAdjustment(item, strokeWidth) {
  function boundContext (line 16077) | function boundContext(_, deg) {
  method beginPath (line 16091) | beginPath() {
  method closePath (line 16093) | closePath() {
  method rect (line 16097) | rect(x5, y5, w3, h3) {
  method quadraticCurveTo (line 16108) | quadraticCurveTo(x12, y12, x22, y22) {
  method bezierCurveTo (line 16114) | bezierCurveTo(x12, y12, x22, y22, x32, y32) {
  method arc (line 16120) | arc(cx, cy, r2, sa2, ea3, ccw) {
  function quadExtrema (line 16156) | function quadExtrema(x06, x12, x22, cb) {
  function cubicExtrema (line 16160) | function cubicExtrema(x06, x12, x22, x32, cb) {
  function cubic (line 16176) | function cubic(t4, x06, x12, x22, x32) {
  function intersectPath (line 16182) | function intersectPath(draw3) {
  function intersectPoint (line 16203) | function intersectPoint(item, box) {
  function intersectRect (line 16206) | function intersectRect(item, box) {
  function intersectRule (line 16210) | function intersectRule(item, box) {
  function intersectBoxLine (line 16214) | function intersectBoxLine(box, x5, y5, u5, v3) {
  function blend (line 16251) | function blend(context3, item) {
  function value (line 16254) | function value(value3, dflt) {
  function addStops (line 16257) | function addStops(gradient4, stops) {
  function gradient (line 16264) | function gradient(context3, spec, bounds2) {
  function color2 (line 16283) | function color2(context3, item, value3) {
  function fill (line 16286) | function fill(context3, item, opacity2) {
  function stroke (line 16297) | function stroke(context3, item, opacity2) {
  function compare2 (line 16317) | function compare2(a4, b3) {
  function zorder (line 16320) | function zorder(scene) {
  function visit (line 16331) | function visit(scene, visitor) {
  function pickVisit (line 16345) | function pickVisit(scene, visitor) {
  function drawAll (line 16362) | function drawAll(path3) {
  function drawOne (line 16371) | function drawOne(path3) {
  function drawPath (line 16378) | function drawPath(path3, context3, item, items) {
  function pick$1 (line 16390) | function pick$1(test2) {
  function hitPath (line 16402) | function hitPath(path3, filled) {
  function pickPath (line 16414) | function pickPath(path3) {
  function translate (line 16417) | function translate(x5, y5) {
  function rotate (line 16420) | function rotate(a4) {
  function scale2 (line 16423) | function scale2(scaleX, scaleY2) {
  function translateItem (line 16426) | function translateItem(item) {
  function rotateItem (line 16429) | function rotateItem(item) {
  function transformItem (line 16432) | function transformItem(item) {
  function markItemPath (line 16435) | function markItemPath(type3, shape2, isect) {
  function pickArea (line 16465) | function pickArea(a4, p2) {
  function pickLine (line 16477) | function pickLine(a4, p2) {
  function pickTrail (line 16488) | function pickTrail(a4, p2) {
  function markMultiItemPath (line 16500) | function markMultiItemPath(type3, shape2, tip) {
  function clip (line 16541) | function clip(context3, scene) {
  function clipGroup (line 16552) | function clipGroup(context3, group2) {
  function offset$1 (line 16557) | function offset$1(item) {
  function attr$5 (line 16561) | function attr$5(emit2, item) {
  function emitRectangle (line 16564) | function emitRectangle(emit2, item) {
  function background (line 16568) | function background(emit2, item) {
  function foreground (line 16573) | function foreground(emit2, item) {
  function content (line 16582) | function content(emit2, item, renderer) {
  function bound$5 (line 16586) | function bound$5(bounds2, group2) {
  function rectanglePath (line 16599) | function rectanglePath(context3, group2, x5, y5) {
  function draw$4 (line 16607) | function draw$4(context3, scene, bounds2, markTypes) {
  function pick (line 16640) | function pick(context3, scene, x5, y5, gx, gy) {
  function pickMark (line 16674) | function pickMark(mark, x5, y5) {
  function getImage (line 16695) | function getImage(item, renderer) {
  function imageWidth (line 16710) | function imageWidth(item, image3) {
  function imageHeight (line 16713) | function imageHeight(item, image3) {
  function imageXOffset (line 16716) | function imageXOffset(align2, w3) {
  function imageYOffset (line 16719) | function imageYOffset(baseline3, h3) {
  function attr$4 (line 16722) | function attr$4(emit2, item, renderer) {
  function bound$4 (line 16730) | function bound$4(bounds2, item) {
  function draw$3 (line 16734) | function draw$3(context3, scene, bounds2) {
  function attr$3 (line 16780) | function attr$3(emit2, item) {
  function path$1 (line 16788) | function path$1(context3, item) {
  function bound$3 (line 16805) | function bound$3(bounds2, item) {
  function attr$2 (line 16818) | function attr$2(emit2, item) {
  function bound$2 (line 16821) | function bound$2(bounds2, item) {
  function draw$2 (line 16825) | function draw$2(context3, item) {
  function attr$1 (line 16839) | function attr$1(emit2, item) {
  function bound$1 (line 16844) | function bound$1(bounds2, item) {
  function path2 (line 16848) | function path2(context3, item, opacity2) {
  function draw$1 (line 16862) | function draw$1(context3, scene, bounds2) {
  function hit$1 (line 16872) | function hit$1(context3, item, x5, y5) {
  function useCanvas (line 16897) | function useCanvas(use) {
  function estimateWidth (line 16900) | function estimateWidth(item, text4) {
  function _estimateWidth (line 16903) | function _estimateWidth(text4, currentFontHeight) {
  function measureWidth (line 16906) | function measureWidth(item, text4) {
  function _measureWidth (line 16909) | function _measureWidth(text4, currentFont) {
  function fontSize (line 16919) | function fontSize(item) {
  function lineHeight (line 16922) | function lineHeight(item) {
  function lineArray (line 16925) | function lineArray(_) {
  function textLines (line 16928) | function textLines(item) {
  function multiLineOffset (line 16931) | function multiLineOffset(item) {
  function textValue (line 16935) | function textValue(item, line4) {
  function widthGetter (line 16939) | function widthGetter(item) {
  function truncate2 (line 16950) | function truncate2(item, text4) {
  function fontFamily (line 16971) | function fontFamily(item, quote) {
  function font (line 16975) | function font(item, quote) {
  function offset2 (line 16978) | function offset2(item) {
  function anchorPoint (line 16988) | function anchorPoint(item) {
  function attr (line 16999) | function attr(emit2, item) {
  function bound (line 17010) | function bound(bounds2, item, mode) {
  function draw (line 17031) | function draw(context3, scene, bounds2) {
  function hit (line 17074) | function hit(context3, item, x5, y5, gx, gy) {
  function intersectText (line 17080) | function intersectText(item, box) {
  function boundItem (line 17109) | function boundItem(item, func, opt) {
  function boundMark (line 17117) | function boundMark(mark, bounds2, opt) {
  function sceneToJSON (line 17225) | function sceneToJSON(scene, indent) {
  function sceneFromJSON (line 17228) | function sceneFromJSON(json2) {
  function initialize (line 17232) | function initialize(scene) {
  method constructor (line 17246) | constructor(scene) {
  method toJSON (line 17258) | toJSON(indent) {
  method mark (line 17261) | mark(markdef, group2, index4) {
  function createMark (line 17269) | function createMark(def2, group2) {
  function domCreate (line 17289) | function domCreate(doc, tag, ns) {
  function domFind (line 17295) | function domFind(el, tag) {
  function domChild (line 17302) | function domChild(el, index4, tag, ns) {
  function domClear (line 17311) | function domClear(el, index4) {
  function cssClass (line 17316) | function cssClass(mark) {
  function point6 (line 17319) | function point6(event2, el) {
  function resolveItem (line 17323) | function resolveItem(item, event2, el, origin) {
  method constructor (line 17347) | constructor(customLoader, customTooltip) {
  method initialize (line 17362) | initialize(el, origin, obj) {
  method element (line 17371) | element() {
  method canvas (line 17379) | canvas() {
  method origin (line 17385) | origin(origin) {
  method scene (line 17396) | scene(scene) {
  method on (line 17404) | on() {
  method off (line 17409) | off() {
  method _handlerIndex (line 17418) | _handlerIndex(h3, type3, handler) {
  method handlers (line 17434) | handlers(type3) {
  method eventName (line 17451) | eventName(name4) {
  method handleHref (line 17461) | handleHref(event2, item, href2) {
  method handleTooltip (line 17478) | handleTooltip(event2, item, show) {
  method getItemBoundingClientRect (line 17493) | getItemBoundingClientRect(item) {
  function defaultTooltip (line 17514) | function defaultTooltip(handler, event2, item, value3) {
  method constructor (line 17525) | constructor(loader2) {
  method initialize (line 17541) | initialize(el, width2, height2, origin, scaleFactor) {
  method element (line 17549) | element() {
  method canvas (line 17557) | canvas() {
  method background (line 17563) | background(bgcolor) {
  method resize (line 17578) | resize(width2, height2, origin, scaleFactor) {
  method dirty (line 17591) | dirty() {
  method render (line 17605) | render(scene, markTypes) {
  method _render (line 17621) | _render() {
  method renderAsync (line 17633) | renderAsync(scene, markTypes) {
  method _load (line 17645) | _load(method2, uri) {
  method sanitizeURL (line 17663) | sanitizeURL(uri) {
  method loadImage (line 17673) | loadImage(uri) {
  method constructor (line 17705) | constructor(loader2, tooltip2) {
  method initialize (line 17716) | initialize(el, origin, obj) {
  method canvas (line 17722) | canvas() {
  method context (line 17726) | context() {
  method DOMMouseScroll (line 17730) | DOMMouseScroll(evt) {
  method pointerdown (line 17733) | pointerdown(evt) {
  method mousedown (line 17737) | mousedown(evt) {
  method click (line 17741) | click(evt) {
  method touchstart (line 17747) | touchstart(evt) {
  method touchmove (line 17755) | touchmove(evt) {
  method touchend (line 17758) | touchend(evt) {
  method fire (line 17763) | fire(type3, evt, touch2) {
  method on (line 17778) | on(type3, handler) {
  method off (line 17790) | off(type3, handler) {
  method pickEvent (line 17797) | pickEvent(evt) {
  method pick (line 17804) | pick(scene, x5, y5, gx, gy) {
  function eventListenerCheck (line 17810) | function eventListenerCheck(handler, type3) {
  function addEventListener (line 17813) | function addEventListener(handler, type3) {
  function fireAll (line 17820) | function fireAll(handler, types4, event2) {
  function move (line 17823) | function move(moveEvents, overEvents, outEvents) {
  function inactive (line 17838) | function inactive(types4) {
  function devicePixelRatio (line 17844) | function devicePixelRatio() {
  function resize (line 17847) | function resize(canvas, width2, height2, origin, scaleFactor, opt) {
  method constructor (line 17863) | constructor(loader2) {
  method initialize (line 17870) | initialize(el, width2, height2, origin, scaleFactor, options) {
  method resize (line 17879) | resize(width2, height2, origin, scaleFactor) {
  method canvas (line 17892) | canvas() {
  method context (line 17895) | context() {
  method dirty (line 17898) | dirty(item) {
  method _render (line 17907) | _render(scene, markTypes) {
  method draw (line 17917) | draw(ctx, scene, bounds2, markTypes) {
  method clear (line 17926) | clear(x5, y5, w3, h3) {
  function clipToBounds (line 17938) | function clipToBounds(g2, b3, origin) {
  method constructor (line 17950) | constructor(loader2, tooltip2) {
  method initialize (line 17960) | initialize(el, origin, obj) {
  method canvas (line 17975) | canvas() {
  method on (line 17979) | on(type3, handler) {
  method off (line 17995) | off(type3, handler) {
  function ariaItemAttributes (line 18047) | function ariaItemAttributes(emit2, item) {
  function ariaMarkAttributes (line 18061) | function ariaMarkAttributes(mark) {
  function ariaMark (line 18066) | function ariaMark(mark) {
  function ariaGuide (line 18071) | function ariaGuide(mark, opt) {
  function titleCaption (line 18079) | function titleCaption(item) {
  function axisCaption (line 18082) | function axisCaption(item) {
  function legendCaption (line 18086) | function legendCaption(item) {
  function extractTitle (line 18090) | function extractTitle(item) {
  function channelCaption (line 18097) | function channelCaption(props) {
  function capitalize (line 18101) | function capitalize(s2) {
  function markup (line 18106) | function markup() {
  function _serialize (line 18146) | function _serialize(m4, node) {
  method constructor (line 18186) | constructor(loader2) {
  method initialize (line 18205) | initialize(el, width2, height2, origin, scaleFactor) {
  method background (line 18225) | background(bgcolor) {
  method resize (line 18241) | resize(width2, height2, origin, scaleFactor) {
  method canvas (line 18258) | canvas() {
  method svg (line 18265) | svg() {
  method _render (line 18291) | _render(scene, markTypes) {
  method dirty (line 18307) | dirty(item) {
  method isDirty (line 18317) | isDirty(item) {
  method _dirtyCheck (line 18324) | _dirtyCheck() {
  method mark (line 18377) | mark(el, scene, prev, markTypes) {
  method _update (line 18418) | _update(mdef, el, item) {
  method style (line 18432) | style(el, item) {
  method defs (line 18457) | defs() {
  method _clearDefs (line 18475) | _clearDefs() {
  function dirtyParents (line 18481) | function dirtyParents(item, id2) {
  function updateGradient (line 18489) | function updateGradient(el, grad, index4) {
  function updateClipping (line 18534) | function updateClipping(el, clip3, index4) {
  function recurse (line 18553) | function recurse(renderer, el, group2, markTypes) {
  function bind (line 18562) | function bind(item, el, sibling, tag, svg) {
  function siblingCheck (line 18594) | function siblingCheck(node, sibling) {
  method group (line 18600) | group(mdef, el, item) {
  method image (line 18629) | image(mdef, el, item) {
  method text (line 18637) | text(mdef, el, item) {
  function emit (line 18673) | function emit(name4, value3, ns) {
  function setStyle (line 18682) | function setStyle(el, name4, value3) {
  function setAttributes (line 18692) | function setAttributes(el, attrs) {
  function setAttribute (line 18697) | function setAttribute(el, name4, value3) {
  function setAttributeNS (line 18704) | function setAttributeNS(el, name4, value3, ns) {
  function href (line 18711) | function href() {
  method constructor (line 18716) | constructor(loader2) {
  method svg (line 18728) | svg() {
  method _render (line 18735) | _render(scene) {
  method mark (line 18765) | mark(m4, scene) {
  method href (line 18822) | href(item) {
  method attr (line 18845) | attr(scene, item, attrs, tag) {
  method defs (line 18865) | defs(m4) {
  function style (line 18933) | function style(s2, item, scene, tag, defs) {
  function setHybridRendererOptions (line 18984) | function setHybridRendererOptions(options) {
  method constructor (line 18990) | constructor(loader2) {
  method initialize (line 19006) | initialize(el, width2, height2, origin, scaleFactor) {
  method dirty (line 19030) | dirty(item) {
  method _render (line 19044) | _render(scene, markTypes) {
  method resize (line 19060) | resize(width2, height2, origin, scaleFactor) {
  method background (line 19066) | background(bgcolor) {
  method constructor (line 19076) | constructor(loader2, tooltip2) {
  method initialize (line 19079) | initialize(el, origin, obj) {
  function renderModule (line 19113) | function renderModule(name4, _) {
  function intersect2 (line 19122) | function intersect2(scene, bounds2, filter3) {
  function intersectMark (line 19126) | function intersectMark(mark, box, filter3, hits) {
  function visitMark (line 19143) | function visitMark(mark, box, filter3) {
  function intersectGroup (line 19146) | function intersectGroup(group2, box, filter3, hits) {
  function intersectItem (line 19161) | function intersectItem(item, box, test2) {
  function boundClip (line 19166) | function boundClip(mark) {
  function sceneEqual (line 19176) | function sceneEqual(a4, b3, key2) {
  function pathEqual (line 19179) | function pathEqual(a4, b3) {
  function objectEqual (line 19182) | function objectEqual(a4, b3) {
  function resetSVGDefIds (line 19196) | function resetSVGDefIds() {
  function Bound (line 19239) | function Bound(params2) {
  method transform (line 19243) | transform(_, pulse2) {
  function boundItem2 (line 19281) | function boundItem2(item, bound2, opt) {
  function Identifier (line 19285) | function Identifier(params2) {
  method transform (line 19300) | transform(_, pulse2) {
  function getCounter (line 19308) | function getCounter(view) {
  function Mark (line 19311) | function Mark(params2) {
  method transform (line 19315) | transform(_, pulse2) {
  function lookup$1 (line 19338) | function lookup$1(_) {
  function Overlap (line 19342) | function Overlap(params2) {
  method transform (line 19378) | transform(_, pulse2) {
  function Render (line 19418) | function Render(params2) {
  method transform (line 19422) | transform(_, pulse2) {
  function set3 (line 19432) | function set3(item, property2, value3) {
  function isYAxis (line 19435) | function isYAxis(mark) {
  function axisIndices (line 19439) | function axisIndices(datum2) {
  function axisLayout (line 19450) | function axisLayout(view, axis, width2, height2) {
  function axisTitleLayout (line 19498) | function axisTitleLayout(view, title2, offset4, pad4, dl, isYAxis2, sign...
  function gridLayoutGroups (line 19512) | function gridLayoutGroups(group2) {
  function bboxFlush (line 19557) | function bboxFlush(item) {
  function bboxFull (line 19560) | function bboxFull(item) {
  function get4 (line 19564) | function get4(opt, key2, d2) {
  function offsetValue (line 19568) | function offsetValue(v3) {
  function gridLayout (line 19571) | function gridLayout(view, groups, opt) {
  function trellisLayout (line 19700) | function trellisLayout(view, group2, opt) {
  function boundFlush (line 19735) | function boundFlush(item, field3) {
  function boundFull (line 19738) | function boundFull(item, field3) {
  function layoutHeaders (line 19741) | function layoutHeaders(view, headers, groups, ncols, limit, offset4, agg...
  function layoutTitle (line 19776) | function layoutTitle(view, g2, offset4, isX2, bounds2, band2) {
  function lookup2 (line 19787) | function lookup2(config, orient2) {
  function offsets (line 19791) | function offsets(legends, value3) {
  function legendParams (line 19798) | function legendParams(g2, orient2, config, xb, yb, w3, h3) {
  function legendLayout (line 19870) | function legendLayout(view, legend) {
  function legendBounds (line 19895) | function legendBounds(item, b3) {
  function legendGroupLayout (line 19901) | function legendGroupLayout(view, item, entry2) {
  function legendTitleOffset (line 19940) | function legendTitleOffset(item, entry2, title2, anchor, y5, lr, noBar) {
  function translate2 (line 19944) | function translate2(view, item, dx, dy) {
  function legendEntryLayout (line 19951) | function legendEntryLayout(entries3) {
  function titleLayout (line 19961) | function titleLayout(view, mark, width2, height2, viewBounds2) {
  function ViewLayout (line 20025) | function ViewLayout(params2) {
  method transform (line 20029) | transform(_, pulse2) {
  function shouldReflow (line 20038) | function shouldReflow(group2) {
  function layoutGroup (line 20041) | function layoutGroup(view, group2, _) {
  function viewSizeLayout (line 20113) | function viewSizeLayout(view, group2, viewBounds2, _) {
  function AxisTicks (line 20157) | function AxisTicks(params2) {
  method transform (line 20161) | transform(_, pulse2) {
  function DataJoin (line 20187) | function DataJoin(params2) {
  function defaultItemCreate (line 20190) | function defaultItemCreate() {
  function newMap (line 20193) | function newMap(key2) {
  method transform (line 20199) | transform(_, pulse2) {
  function Encode (line 20251) | function Encode(params2) {
  method transform (line 20255) | transform(_, pulse2) {
  function LegendEntries (line 20304) | function LegendEntries(params2) {
  method transform (line 20308) | transform(_, pulse2) {
  function LinkPath (line 20379) | function LinkPath(params2) {
  method transform (line 20423) | transform(_, pulse2) {
  function Pie (line 20478) | function Pie(params2) {
  method transform (line 20510) | transform(_, pulse2) {
  function includeZero (line 20526) | function includeZero(scale7) {
  function includePad (line 20530) | function includePad(type3) {
  function Scale (line 20534) | function Scale(params2) {
  method transform (line 20539) | transform(_, pulse2) {
  function scaleKey (line 20552) | function scaleKey(_) {
  function isContinuousColor (line 20561) | function isContinuousColor(_) {
  function configureDomain (line 20565) | function configureDomain(scale7, _, df) {
  function rawDomain (line 20597) | function rawDomain(scale7, raw, df) {
  function padDomain (line 20605) | function padDomain(type3, domain4, range7, pad4, exponent, constant3) {
  function domainCheck (line 20612) | function domainCheck(type3, domain4, df) {
  function configureBins (line 20621) | function configureBins(scale7, _, count2) {
  function configureRange (line 20646) | function configureRange(scale7, _, count2) {
  function configureRangeStep (line 20672) | function configureRangeStep(type3, _, count2) {
  function configureScheme (line 20679) | function configureScheme(type3, _, count2) {
  function adjustScheme (line 20691) | function adjustScheme(scheme3, extent2, reverse3) {
  function flip (line 20694) | function flip(array4, reverse3) {
  function SortItems (line 20697) | function SortItems(params2) {
  method transform (line 20701) | transform(_, pulse2) {
  function Stack (line 20712) | function Stack(params2) {
  method transform (line 20744) | transform(_, pulse2) {
  function stackCenter (line 20753) | function stackCenter(group2, max4, field3, y06, y12) {
  function stackNormalize (line 20761) | function stackNormalize(group2, max4, field3, y06, y12) {
  function stackZero (line 20769) | function stackZero(group2, max4, field3, y06, y12) {
  function partition2 (line 20783) | function partition2(data3, groupby, sort3, field3) {
  function acos2 (line 20851) | function acos2(x5) {
  function asin2 (line 20854) | function asin2(x5) {
  function noop2 (line 20859) | function noop2() {
  function streamGeometry (line 20863) | function streamGeometry(geometry, stream2) {
  function streamLine (line 20908) | function streamLine(coordinates, stream2, closed) {
  function streamPolygon (line 20914) | function streamPolygon(coordinates, stream2) {
  function stream_default (line 20920) | function stream_default(object2, stream2) {
  function areaRingStart (line 20954) | function areaRingStart() {
  function areaRingEnd (line 20957) | function areaRingEnd() {
  function areaPointFirst (line 20960) | function areaPointFirst(lambda, phi2) {
  function areaPoint (line 20966) | function areaPoint(lambda, phi2) {
  function area_default2 (line 20973) | function area_default2(object2) {
  function spherical (line 20980) | function spherical(cartesian2) {
  function cartesian (line 20983) | function cartesian(spherical2) {
  function cartesianDot (line 20987) | function cartesianDot(a4, b3) {
  function cartesianCross (line 20990) | function cartesianCross(a4, b3) {
  function cartesianAddInPlace (line 20993) | function cartesianAddInPlace(a4, b3) {
  function cartesianScale (line 20996) | function cartesianScale(vector, k2) {
  function cartesianNormalizeInPlace (line 20999) | function cartesianNormalizeInPlace(d2) {
  function boundsPoint (line 21041) | function boundsPoint(lambda, phi2) {
  function linePoint (line 21046) | function linePoint(lambda, phi2) {
  function boundsLineStart (line 21088) | function boundsLineStart() {
  function boundsLineEnd (line 21091) | function boundsLineEnd() {
  function boundsRingPoint (line 21096) | function boundsRingPoint(lambda, phi2) {
  function boundsRingStart (line 21106) | function boundsRingStart() {
  function boundsRingEnd (line 21109) | function boundsRingEnd() {
  function angle (line 21116) | function angle(lambda03, lambda12) {
  function rangeCompare (line 21119) | function rangeCompare(a4, b3) {
  function rangeContains (line 21122) | function rangeContains(range7, x5) {
  function bounds_default (line 21125) | function bounds_default(feature2) {
  function centroidPoint (line 21181) | function centroidPoint(lambda, phi2) {
  function centroidPointCartesian (line 21186) | function centroidPointCartesian(x5, y5, z) {
  function centroidLineStart (line 21192) | function centroidLineStart() {
  function centroidLinePointFirst (line 21195) | function centroidLinePointFirst(lambda, phi2) {
  function centroidLinePoint (line 21204) | function centroidLinePoint(lambda, phi2) {
  function centroidLineEnd (line 21213) | function centroidLineEnd() {
  function centroidRingStart (line 21216) | function centroidRingStart() {
  function centroidRingEnd (line 21219) | function centroidRingEnd() {
  function centroidRingPointFirst (line 21223) | function centroidRingPointFirst(lambda, phi2) {
  function centroidRingPoint (line 21233) | function centroidRingPoint(lambda, phi2) {
  function centroid_default (line 21245) | function centroid_default(object2) {
  function compose_default (line 21262) | function compose_default(a4, b3) {
  function rotationIdentity (line 21273) | function rotationIdentity(lambda, phi2) {
  function rotateRadians (line 21278) | function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
  function forwardRotationLambda (line 21281) | function forwardRotationLambda(deltaLambda) {
  function rotationLambda (line 21288) | function rotationLambda(deltaLambda) {
  function rotationPhiGamma (line 21293) | function rotationPhiGamma(deltaPhi, deltaGamma) {
  function rotation_default (line 21311) | function rotation_default(rotate2) {
  function circleStream (line 21325) | function circleStream(stream2, radius2, delta, direction, t04, t13) {
  function circleRadius (line 21341) | function circleRadius(cosRadius, point9) {
  function buffer_default (line 21349) | function buffer_default() {
  function pointEqual_default (line 21372) | function pointEqual_default(a4, b3) {
  function Intersection (line 21377) | function Intersection(point9, points2, other, entry2) {
  function rejoin_default (line 21385) | function rejoin_default(segments2, compareIntersection2, startInside, in...
  function link (line 21442) | function link(array4) {
  function longitude (line 21455) | function longitude(point9) {
  function polygonContains_default (line 21458) | function polygonContains_default(polygon, point9) {
  function clip_default (line 21486) | function clip_default(pointVisible, clipLine, interpolate3, start) {
  function validSegment (line 21572) | function validSegment(segment) {
  function compareIntersection (line 21575) | function compareIntersection(a4, b3) {
  function clipAntimeridianLine (line 21588) | function clipAntimeridianLine(stream2) {
  function clipAntimeridianIntersect (line 21627) | function clipAntimeridianIntersect(lambda03, phi02, lambda12, phi12) {
  function clipAntimeridianInterpolate (line 21631) | function clipAntimeridianInterpolate(from, to, direction, stream2) {
  function circle_default2 (line 21656) | function circle_default2(radius2) {
  function line_default2 (line 21758) | function line_default2(a4, b3, x06, y06, x12, y12) {
  function clipRectangle (line 21808) | function clipRectangle(x06, y06, x12, y12) {
  function graticuleX (line 21929) | function graticuleX(y06, y12, dy) {
  function graticuleY (line 21937) | function graticuleY(x06, x12, dx) {
  function graticule (line 21945) | function graticule() {
  function areaRingStart2 (line 22049) | function areaRingStart2() {
  function areaPointFirst2 (line 22052) | function areaPointFirst2(x5, y5) {
  function areaPoint2 (line 22056) | function areaPoint2(x5, y5) {
  function areaRingEnd2 (line 22060) | function areaRingEnd2() {
  function boundsPoint2 (line 22082) | function boundsPoint2(x5, y5) {
  function centroidPoint2 (line 22123) | function centroidPoint2(x5, y5) {
  function centroidLineStart2 (line 22128) | function centroidLineStart2() {
  function centroidPointFirstLine (line 22131) | function centroidPointFirstLine(x5, y5) {
  function centroidPointLine (line 22135) | function centroidPointLine(x5, y5) {
  function centroidLineEnd2 (line 22142) | function centroidLineEnd2() {
  function centroidRingStart2 (line 22145) | function centroidRingStart2() {
  function centroidRingEnd2 (line 22148) | function centroidRingEnd2() {
  function centroidPointFirstRing (line 22151) | function centroidPointFirstRing(x5, y5) {
  function centroidPointRing (line 22155) | function centroidPointRing(x5, y5) {
  function PathContext (line 22169) | function PathContext(context3) {
  function lengthPointFirst (line 22239) | function lengthPointFirst(x5, y5) {
  function lengthPoint (line 22243) | function lengthPoint(x5, y5) {
  method constructor (line 22256) | constructor(digits) {
  method pointRadius (line 22261) | pointRadius(_) {
  method polygonStart (line 22265) | polygonStart() {
  method polygonEnd (line 22268) | polygonEnd() {
  method lineStart (line 22271) | lineStart() {
  method lineEnd (line 22274) | lineEnd() {
  method point (line 22278) | point(x5, y5) {
  method result (line 22306) | result() {
  function append2 (line 22312) | function append2(strings) {
  function appendRound2 (line 22319) | function appendRound2(digits) {
  function path_default (line 22338) | function path_default(projection3, context3) {
  function transformer4 (line 22394) | function transformer4(methods2) {
  function TransformStream2 (line 22402) | function TransformStream2() {
  function fit (line 22427) | function fit(projection3, fitBounds, object2) {
  function fitExtent (line 22436) | function fitExtent(projection3, extent2, object2) {
  function fitSize (line 22442) | function fitSize(projection3, size, object2) {
  function fitWidth (line 22445) | function fitWidth(projection3, width2, object2) {
  function fitHeight (line 22451) | function fitHeight(projection3, height2, object2) {
  function resample_default (line 22461) | function resample_default(project3, delta2) {
  function resampleNone (line 22464) | function resampleNone(project3) {
  function resample (line 22472) | function resample(project3, delta2) {
  function transformRotate (line 22541) | function transformRotate(rotate2) {
  function scaleTranslate (line 22549) | function scaleTranslate(k2, dx, dy, sx, sy) {
  function scaleTranslateRotate (line 22560) | function scaleTranslateRotate(k2, dx, dy, sx, sy, alpha) {
  function projection (line 22573) | function projection(project3) {
  function projectionMutator (line 22578) | function projectionMutator(projectAt) {
  function conicProjection (line 22658) | function conicProjection(projectAt) {
  function cylindricalEqualAreaRaw (line 22667) | function cylindricalEqualAreaRaw(phi02) {
  function conicEqualAreaRaw (line 22679) | function conicEqualAreaRaw(y06, y12) {
  function conicEqualArea_default (line 22695) | function conicEqualArea_default() {
  function albers_default (line 22700) | function albers_default() {
  function multiplex (line 22705) | function multiplex(streams) {
  function albersUsa_default (line 22734) | function albersUsa_default() {
  function azimuthalRaw (line 22787) | function azimuthalRaw(scale7) {
  function azimuthalInvert (line 22797) | function azimuthalInvert(angle2) {
  function azimuthalEqualArea_default (line 22814) | function azimuthalEqualArea_default() {
  function azimuthalEquidistant_default (line 22825) | function azimuthalEquidistant_default() {
  function mercatorRaw (line 22830) | function mercatorRaw(lambda, phi2) {
  function mercator_default (line 22836) | function mercator_default() {
  function mercatorProjection (line 22839) | function mercatorProjection(project3) {
  function tany (line 22861) | function tany(y5) {
  function conicConformalRaw (line 22864) | function conicConformalRaw(y06, y12) {
  function conicConformal_default (line 22884) | function conicConformal_default() {
  function equirectangularRaw (line 22889) | function equirectangularRaw(lambda, phi2) {
  function equirectangular_default (line 22893) | function equirectangular_default() {
  function conicEquidistantRaw (line 22898) | function conicEquidistantRaw(y06, y12) {
  function conicEquidistant_default (line 22913) | function conicEquidistant_default() {
  function equalEarthRaw (line 22924) | function equalEarthRaw(lambda, phi2) {
  function equalEarth_default (line 22944) | function equalEarth_default() {
  function gnomonicRaw (line 22949) | function gnomonicRaw(x5, y5) {
  function gnomonic_default (line 22954) | function gnomonic_default() {
  function identity_default4 (line 22959) | function identity_default4() {
  function naturalEarth1Raw (line 23030) | function naturalEarth1Raw(lambda, phi2) {
  function naturalEarth1_default (line 23048) | function naturalEarth1_default() {
  function orthographicRaw (line 23053) | function orthographicRaw(x5, y5) {
  function orthographic_default (line 23057) | function orthographic_default() {
  function stereographicRaw (line 23062) | function stereographicRaw(x5, y5) {
  function stereographic_default (line 23069) | function stereographic_default() {
  function transverseMercatorRaw (line 23074) | function transverseMercatorRaw(lambda, phi2) {
  function transverseMercator_default (line 23080) | function transverseMercator_default() {
  function asin3 (line 23104) | function asin3(x5) {
  function sqrt4 (line 23107) | function sqrt4(x5) {
  function mollweideBromleyTheta (line 23112) | function mollweideBromleyTheta(cp, phi2) {
  function mollweideBromleyRaw (line 23119) | function mollweideBromleyRaw(cx, cy, cp) {
  function mollweide_default (line 23129) | function mollweide_default() {
  function create2 (line 23158) | function create2(type3, constructor) {
  function projection2 (line 23174) | function projection2(type3, proj) {
  function getProjectionPath (line 23186) | function getProjectionPath(proj) {
  function noop3 (line 23214) | function noop3() {
  function contours (line 23217) | function contours() {
  function area2 (line 23350) | function area2(ring) {
  function contains (line 23355) | function contains(ring, hole) {
  function ringContains (line 23360) | function ringContains(ring, point9) {
  function segmentContains (line 23369) | function segmentContains(a4, b3, c4) {
  function collinear (line 23373) | function collinear(a4, b3, c4) {
  function within (line 23376) | function within(p2, q2, r2) {
  function quantize2 (line 23379) | function quantize2(k2, nice3, zero6) {
  function Isocontour (line 23385) | function Isocontour(params2) {
  method transform (line 23437) | transform(_, pulse2) {
  function levels (line 23457) | function levels(values4, f2, _) {
  function transformPaths (line 23461) | function transformPaths(paths, grid, datum2, _) {
  function transform2 (line 23469) | function transform2(grid, sx, sy, tx, ty) {
  function radius (line 23487) | function radius(bw, data3, f2) {
  function number5 (line 23491) | function number5(_) {
  function density2D (line 23494) | function density2D() {
  function blurX (line 23566) | function blurX(n2, m4, source4, target2, r2) {
  function blurY (line 23582) | function blurY(n2, m4, source4, target2, r2) {
  function KDE2D (line 23598) | function KDE2D(params2) {
  function params (line 23646) | function params(obj, _) {
  method transform (line 23651) | transform(_, pulse2) {
  function partition3 (line 23666) | function partition3(data3, groupby) {
  function Contour (line 23685) | function Contour(params2) {
  method transform (line 23736) | transform(_, pulse2) {
  function GeoJSON (line 23759) | function GeoJSON(params2) {
  method transform (line 23776) | transform(_, pulse2) {
  function GeoPath (line 23808) | function GeoPath(params2) {
  method transform (line 23833) | transform(_, pulse2) {
  function initPath (line 23847) | function initPath(path3, pointRadius) {
  function GeoPoint (line 23855) | function GeoPoint(params2) {
  method transform (line 23882) | transform(_, pulse2) {
  function GeoShape (line 23903) | function GeoShape(params2) {
  method transform (line 23930) | transform(_, pulse2) {
  function shapeGenerator (line 23941) | function shapeGenerator(path3, field3, pointRadius) {
  function Graticule (line 23953) | function Graticule(params2) {
  method transform (line 24017) | transform(_, pulse2) {
  function Heatmap (line 24036) | function Heatmap(params2) {
  method transform (line 24067) | transform(_, pulse2) {
  function color_ (line 24086) | function color_(color5, _) {
  function opacity_ (line 24096) | function opacity_(opacity2, _) {
  function dependency (line 24109) | function dependency(f2) {
  function toCanvas (line 24114) | function toCanvas(grid, obj, color5, opacity2) {
  function Projection (line 24131) | function Projection(params2) {
  method transform (line 24136) | transform(_, pulse2) {
  function fit2 (line 24153) | function fit2(proj, _) {
  function create3 (line 24157) | function create3(type3) {
  function set4 (line 24162) | function set4(proj, key2, value3) {
  function collectGeoJSON (line 24165) | function collectGeoJSON(data3) {
  function featurize (line 24172) | function featurize(f2) {
  function center_default (line 24186) | function center_default(x5, y5) {
  function add_default (line 24215) | function add_default(d2) {
  function add4 (line 24219) | function add4(tree, x5, y5, d2) {
  function addAll (line 24242) | function addAll(data3) {
  function cover_default (line 24262) | function cover_default(x5, y5) {
  function data_default (line 24298) | function data_default() {
  function extent_default (line 24309) | function extent_default(_) {
  function quad_default (line 24314) | function quad_default(node, x06, y06, x12, y12) {
  function find_default (line 24323) | function find_default(x5, y5, radius2) {
  function remove_default (line 24361) | function remove_default(d2) {
  function removeAll (line 24385) | function removeAll(data3) {
  function root_default (line 24391) | function root_default() {
  function size_default (line 24396) | function size_default() {
  function visit_default (line 24407) | function visit_default(callback) {
  function visitAfter_default (line 24423) | function visitAfter_default(callback) {
  function defaultX (line 24444) | function defaultX(d2) {
  function x_default (line 24447) | function x_default(_) {
  function defaultY (line 24452) | function defaultY(d2) {
  function y_default (line 24455) | function y_default(_) {
  function quadtree (line 24460) | function quadtree(nodes, x5, y5) {
  function Quadtree (line 24464) | function Quadtree(x5, y5, x06, y06, x12, y12) {
  function leaf_copy (line 24473) | function leaf_copy(leaf) {
  function constant_default3 (line 24510) | function constant_default3(x5) {
  function jiggle_default (line 24517) | function jiggle_default(random2) {
  function x3 (line 24522) | function x3(d2) {
  function y3 (line 24525) | function y3(d2) {
  function collide_default (line 24528) | function collide_default(radius2) {
  function index (line 24595) | function index(d2) {
  function find2 (line 24598) | function find2(nodeById, nodeId) {
  function link_default (line 24603) | function link_default(links) {
  function dispatch (line 24679) | function dispatch() {
  function Dispatch (line 24686) | function Dispatch(_) {
  function parseTypenames (line 24689) | function parseTypenames(typenames, types4) {
  function get5 (line 24727) | function get5(type3, name4) {
  function set5 (line 24734) | function set5(type3, name4, callback) {
  function now (line 24760) | function now() {
  function clearNow (line 24763) | function clearNow() {
  function Timer (line 24766) | function Timer() {
  function timer (line 24791) | function timer(callback, delay, time3) {
  function timerFlush (line 24796) | function timerFlush() {
  function wake (line 24806) | function wake() {
  function poke (line 24817) | function poke() {
  function nap (line 24821) | function nap() {
  function sleep (line 24835) | function sleep(time3) {
  function interval_default (line 24849) | function interval_default(callback, delay, time3) {
  function lcg_default (line 24869) | function lcg_default() {
  function x4 (line 24875) | function x4(d2) {
  function y4 (line 24878) | function y4(d2) {
  function simulation_default (line 24883) | function simulation_default(nodes) {
  function manyBody_default (line 24984) | function manyBody_default() {
  function x_default2 (line 25063) | function x_default2(x5) {
  function y_default2 (line 25094) | function y_default2(y5) {
  function Force (line 25137) | function Force(params2) {
  method transform (line 25286) | transform(_, pulse2) {
  method finish (line 25316) | finish(_, pulse2) {
  function rerun (line 25333) | function rerun(df, op) {
  function simulation (line 25336) | function simulation(nodes, _) {
  function setup (line 25344) | function setup(sim, _, init2, pulse2) {
  function modified (line 25361) | function modified(f2, pulse2) {
  function getForce (line 25368) | function getForce(_) {
  function setForceParam (line 25379) | function setForceParam(f2, v3, _) {
  function defaultSeparation (line 25396) | function defaultSeparation(a4, b3) {
  function meanX (line 25399) | function meanX(children4) {
  function meanXReduce (line 25402) | function meanXReduce(x5, c4) {
  function maxY (line 25405) | function maxY(children4) {
  function maxYReduce (line 25408) | function maxYReduce(y5, c4) {
  function leafLeft (line 25411) | function leafLeft(node) {
  function leafRight (line 25416) | function leafRight(node) {
  function cluster_default (line 25421) | function cluster_default() {
  function count (line 25458) | function count(node) {
  function count_default (line 25464) | function count_default() {
  function each_default (line 25469) | function each_default(callback, that) {
  function eachBefore_default (line 25478) | function eachBefore_default(callback, that) {
  function eachAfter_default (line 25492) | function eachAfter_default(callback, that) {
  function find_default2 (line 25509) | function find_default2(callback, that) {
  function sum_default (line 25519) | function sum_default(value3) {
  function sort_default (line 25528) | function sort_default(compare4) {
  function path_default2 (line 25537) | function path_default2(end) {
  function leastCommonAncestor (line 25550) | function leastCommonAncestor(a4, b3) {
  function ancestors_default (line 25564) | function ancestors_default() {
  function descendants_default (line 25573) | function descendants_default() {
  function leaves_default (line 25578) | function leaves_default() {
  function links_default (line 25589) | function links_default() {
  function hierarchy (line 25616) | function hierarchy(data3, children4) {
  function node_copy (line 25636) | function node_copy() {
  function objectChildren (line 25639) | function objectChildren(d2) {
  function mapChildren (line 25642) | function mapChildren(d2) {
  function copyData (line 25645) | function copyData(node) {
  function computeHeight (line 25649) | function computeHeight(node) {
  function Node (line 25655) | function Node(data3) {
  function optional (line 25679) | function optional(f2) {
  function required (line 25682) | function required(f2) {
  function constantZero (line 25688) | function constantZero() {
  function constant_default4 (line 25691) | function constant_default4(x5) {
  function lcg_default2 (line 25701) | function lcg_default2() {
  function array_default3 (line 25707) | function array_default3(x5) {
  function shuffle (line 25710) | function shuffle(array4, random2) {
  function packEncloseRandom (line 25722) | function packEncloseRandom(circles, random2) {
  function extendBasis (line 25731) | function extendBasis(B3, p2) {
  function enclosesNot (line 25748) | function enclosesNot(a4, b3) {
  function enclosesWeak (line 25752) | function enclosesWeak(a4, b3) {
  function enclosesWeakAll (line 25756) | function enclosesWeakAll(a4, B3) {
  function encloseBasis (line 25764) | function encloseBasis(B3) {
  function encloseBasis1 (line 25774) | function encloseBasis1(a4) {
  function encloseBasis2 (line 25781) | function encloseBasis2(a4, b3) {
  function encloseBasis3 (line 25789) | function encloseBasis3(a4, b3, c4) {
  function place (line 25799) | function place(b3, a4, c4) {
  function intersects (line 25820) | function intersects(a4, b3) {
  function score (line 25824) | function score(node) {
  function Node2 (line 25828) | function Node2(circle2) {
  function packSiblingsRandom (line 25833) | function packSiblingsRandom(circles, random2) {
  function defaultRadius (line 25880) | function defaultRadius(d2) {
  function pack_default (line 25883) | function pack_default() {
  function radiusLeaf (line 25906) | function radiusLeaf(radius2) {
  function packChildrenRandom (line 25913) | function packChildrenRandom(padding3, k2, random2) {
  function translateChild (line 25924) | function translateChild(k2) {
  function round_default2 (line 25936) | function round_default2(node) {
  function dice_default (line 25944) | function dice_default(parent, x06, y06, x12, y12) {
  function partition_default (line 25953) | function partition_default() {
  function defaultId (line 25994) | function defaultId(d2) {
  function defaultParentId (line 25997) | function defaultParentId(d2) {
  function stratify_default (line 26000) | function stratify_default() {
  function normalize2 (line 26074) | function normalize2(path3) {
  function parentof (line 26080) | function parentof(path3) {
  function slash (line 26086) | function slash(path3, i2) {
  function defaultSeparation2 (line 26096) | function defaultSeparation2(a4, b3) {
  function nextLeft (line 26099) | function nextLeft(v3) {
  function nextRight (line 26103) | function nextRight(v3) {
  function moveSubtree (line 26107) | function moveSubtree(wm, wp, shift) {
  function executeShifts (line 26115) | function executeShifts(v3) {
  function nextAncestor (line 26124) | function nextAncestor(vim, v3, ancestor) {
  function TreeNode (line 26127) | function TreeNode(node, i2) {
  function treeRoot (line 26141) | function treeRoot(root) {
  function tree_default (line 26155) | function tree_default() {
  function slice_default (line 26244) | function slice_default(parent, x06, y06, x12, y12) {
  function squarifyRatio (line 26254) | function squarifyRatio(ratio, parent, x06, y06, x12, y12) {
  function squarify (line 26285) | function squarify(parent, x06, y06, x12, y12) {
  function treemap_default (line 26295) | function treemap_default() {
  function binary_default (line 26359) | function binary_default(parent, x06, y06, x12, y12) {
  function sliceDice_default (line 26393) | function sliceDice_default(parent, x06, y06, x12, y12) {
  function resquarify (line 26399) | function resquarify(parent, x06, y06, x12, y12) {
  function lookup3 (line 26421) | function lookup3(tree, key2, filter3) {
  function Nest (line 26430) | function Nest(params2) {
  method transform (line 26450) | transform(_, pulse2) {
  function nest (line 26484) | function nest() {
  function HierarchyLayout (line 26521) | function HierarchyLayout(params2) {
  method transform (line 26526) | transform(_, pulse2) {
  function setParams (line 26547) | function setParams(layout, params2, _) {
  function setFields (line 26553) | function setFields(node, fields, as) {
  function Pack (line 26561) | function Pack(params2) {
  function Partition (line 26603) | function Partition(params2) {
  function Stratify (line 26644) | function Stratify(params2) {
  method transform (line 26663) | transform(_, pulse2) {
  function Tree (line 26682) | function Tree(params2) {
  method layout (line 26728) | layout(method2) {
  function TreeLinks (line 26736) | function TreeLinks(params2) {
  method transform (line 26749) | transform(_, pulse2) {
  function Treemap (line 26785) | function Treemap(params2) {
  method layout (line 26859) | layout() {
  function baseBitmaps (line 26881) | function baseBitmaps($2, data3) {
  function markBitmaps (line 26886) | function markBitmaps($2, baseMark, avoidMarks, labelInside, isGroupArea) {
  function getBuffer (line 26911) | function getBuffer(context3, width2, height2) {
  function draw2 (line 26914) | function draw2(context3, items, interior) {
  function prepare (line 26927) | function prepare(source4) {
  function Bitmap (line 26950) | function Bitmap(w3, h3) {
  function scaler (line 27028) | function scaler(width2, height2, padding3) {
  function placeAreaLabelNaive (line 27038) | function placeAreaLabelNaive($2, bitmaps, avoidBaseMark, markIndex) {
  function outOfBounds (line 27078) | function outOfBounds(x5, y5, textWidth, textHeight, width2, height2) {
  function collision (line 27082) | function collision($2, x5, y5, textHeight, textWidth, h3, bm0, bm1) {
  function placeAreaLabelReducedSearch (line 27086) | function placeAreaLabelReducedSearch($2, bitmaps, avoidBaseMark, markInd...
  function placeAreaLabelFloodFill (line 27171) | function placeAreaLabelFloodFill($2, bitmaps, avoidBaseMark, markIndex) {
  function placeMarkLabel (line 27238) | function placeMarkLabel($2, bitmaps, anchors, offsets2) {
  function test (line 27283) | function test(_x1, _x22, _y1, _y22, bm0, bm1, x12, x22, y12, y22, bounda...
  function labelLayout (line 27308) | function labelLayout(texts, size, compare4, offset4, anchor, avoidMarks,...
  function getOffsets (line 27345) | function getOffsets(_, count2) {
  function getAnchors (line 27351) | function getAnchors(_, count2) {
  function markType (line 27357) | function markType(item) {
  function markBoundary (line 27360) | function markBoundary(marktype, grouptype, lineAnchor, markIndex) {
  function Label (line 27383) | function Label(params2) {
  method transform (line 27445) | transform(_, pulse2) {
  function partition4 (line 27474) | function partition4(data3, groupby) {
  function Loess (line 27495) | function Loess(params2) {
  method transform (line 27526) | transform(_, pulse2) {
  function Regression (line 27557) | function Regression(params2) {
  method transform (line 27602) | transform(_, pulse2) {
  function sum2 (line 27663) | function sum2(elen, e4, flen, f2, h3) {
  function estimate (line 27734) | function estimate(elen, e4) {
  function vec (line 27739) | function vec(n2) {
  function orient2dadapt (line 27752) | function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {
  function orient2d (line 27899) | function orient2d(ax, ay, bx, by, cx, cy) {
  method from (line 28022) | static from(points2, getX = defaultGetX, getY = defaultGetY) {
  method constructor (line 28032) | constructor(coords) {
  method update (line 28048) | update() {
  method _hashKey (line 28208) | _hashKey(x5, y5) {
  method _legalize (line 28211) | _legalize(a4) {
  method _link (line 28269) | _link(a4, b3) {
  method _addTriangle (line 28274) | _addTriangle(i0, i1, i2, a4, b3, c4) {
  function pseudoAngle (line 28286) | function pseudoAngle(dx, dy) {
  function dist (line 28290) | function dist(ax, ay, bx, by) {
  function inCircle (line 28295) | function inCircle(ax, ay, bx, by, cx, cy, px2, py2) {
  function circumradius (line 28307) | function circumradius(ax, ay, bx, by, cx, cy) {
  function circumcenter (line 28319) | function circumcenter(ax, ay, bx, by, cx, cy) {
  function quicksort (line 28331) | function quicksort(ids, dists, left, right) {
  function swap2 (line 28371) | function swap2(arr, i2, j2) {
  function defaultGetX (line 28376) | function defaultGetX(p2) {
  function defaultGetY (line 28379) | function defaultGetY(p2) {
  method constructor (line 28386) | constructor() {
  method moveTo (line 28391) | moveTo(x5, y5) {
  method closePath (line 28394) | closePath() {
  method lineTo (line 28400) | lineTo(x5, y5) {
  method arc (line 28403) | arc(x5, y5, r2) {
  method rect (line 28413) | rect(x5, y5, w3, h3) {
  method value (line 28416) | value() {
  method constructor (line 28423) | constructor() {
  method moveTo (line 28426) | moveTo(x5, y5) {
  method closePath (line 28429) | closePath() {
  method lineTo (line 28432) | lineTo(x5, y5) {
  method value (line 28435) | value() {
  method constructor (line 28442) | constructor(delaunay, [xmin, ymin, xmax, ymax] = [0, 0, 960, 500]) {
  method update (line 28451) | update() {
  method _init (line 28456) | _init() {
  method render (line 28507) | render(context3) {
  method renderBounds (line 28534) | renderBounds(context3) {
  method renderCell (line 28539) | renderCell(i2, context3) {
  method cellPolygons (line 28553) | *cellPolygons() {
  method cellPolygon (line 28560) | cellPolygon(i2) {
  method _renderSegment (line 28565) | _renderSegment(x06, y06, x12, y12, context3) {
  method contains (line 28577) | contains(i2, x5, y5) {
  method neighbors (line 28581) | *neighbors(i2) {
  method _cell (line 28595) | _cell(i2) {
  method _clip (line 28610) | _clip(i2) {
  method _clipFinite (line 28620) | _clipFinite(i2, points2) {
  method _clipSegment (line 28660) | _clipSegment(x06, y06, x12, y12, c0, c1) {
  method _clipInfinite (line 28675) | _clipInfinite(i2, points2, vx0, vy0, vxn, vyn) {
  method _edge (line 28689) | _edge(i2, e0, e1, P, j2) {
  method _project (line 28731) | _project(x06, y06, vx, vy) {
  method _edgecode (line 28749) | _edgecode(x5, y5) {
  method _regioncode (line 28752) | _regioncode(x5, y5) {
  method _simplify (line 28755) | _simplify(P) {
  function pointX (line 28772) | function pointX(p2) {
  function pointY (line 28775) | function pointY(p2) {
  function collinear2 (line 28778) | function collinear2(d2) {
  function jitter (line 28786) | function jitter(x5, y5, r2) {
  method from (line 28790) | static from(points2, fx = pointX, fy = pointY, that) {
  method constructor (line 28793) | constructor(points2) {
  method update (line 28800) | update() {
  method _init (line 28805) | _init() {
  method voronoi (line 28843) | voronoi(bounds2) {
  method neighbors (line 28846) | *neighbors(i2) {
  method find (line 28869) | find(x5, y5, i2 = 0) {
  method _step (line 28876) | _step(i2, x5, y5) {
  method render (line 28900) | render(context3) {
  method renderPoints (line 28914) | renderPoints(context3, r2) {
  method renderHull (line 28926) | renderHull(context3) {
  method hullPolygon (line 28938) | hullPolygon() {
  method renderTriangle (line 28943) | renderTriangle(i2, context3) {
  method trianglePolygons (line 28955) | *trianglePolygons() {
  method trianglePolygon (line 28961) | trianglePolygon(i2) {
  function flatArray (line 28967) | function flatArray(points2, fx, fy, that) {
  function Voronoi2 (line 28987) | function Voronoi2(params2) {
  method transform (line 29027) | transform(_, pulse2) {
  function toPathString (line 29040) | function toPathString(p2) {
  function isPoint (line 29046) | function isPoint(p2) {
  function cloud (line 29058) | function cloud() {
  function cloudSprite (line 29229) | function cloudSprite(contextAndRatio, d2, data3, di) {
  function cloudCollide (line 29304) | function cloudCollide(tag, board, sw) {
  function cloudBounds (line 29316) | function cloudBounds(bounds2, d2) {
  function collideRects (line 29323) | function collideRects(a4, b3) {
  function archimedeanSpiral (line 29326) | function archimedeanSpiral(size) {
  function rectangularSpiral (line 29332) | function rectangularSpiral(size) {
  function zeroArray (line 29353) | function zeroArray(n2) {
  function functor (line 29358) | function functor(d2) {
  function Wordcloud (line 29369) | function Wordcloud(params2) {
  method transform (line 29432) | transform(_, pulse2) {
  function Bitmaps (line 29480) | function Bitmaps() {
  function lengthen (line 29536) | function lengthen(array4, length3, copy4) {
  function array2 (line 29542) | function array2(n2, m4, array4) {
  function Dimension (line 29547) | function Dimension(index4, i2, query) {
  function SortedIndex (line 29565) | function SortedIndex() {
  function sort (line 29632) | function sort(values4, index4) {
  function merge3 (line 29639) | function merge3(base, value0, index0, n0, value1, index1, n1, value3, in...
  function CrossFilter (line 29659) | function CrossFilter(params2) {
  method transform (line 29685) | transform(_, pulse2) {
  method init (line 29693) | init(_, pulse2) {
  method reinit (line 29703) | reinit(_, pulse2) {
  method eval (line 29742) | eval(_, pulse2) {
  method insert (line 29763) | insert(_, pulse2, output3) {
  method modify (line 29779) | modify(pulse2, output3) {
  method remove (line 29787) | remove(_, pulse2, output3) {
  method reindex (line 29804) | reindex(pulse2, num, map4) {
  method update (line 29811) | update(_, pulse2, output3) {
  method incrementAll (line 29834) | incrementAll(dim, query, stamp, out) {
  method incrementOne (line 29881) | incrementOne(dim, query, add6, rem2) {
  function ResolveFilter (line 29913) | function ResolveFilter(params2) {
  method transform (line 29932) | transform(_, pulse2) {
  function ASTNode (line 29967) | function ASTNode(type3) {
  function children2 (line 29977) | function children2(node) {
  function assert (line 30052) | function assert(condition, message) {
  function isDecimalDigit (line 30057) | function isDecimalDigit(ch2) {
  function isHexDigit (line 30060) | function isHexDigit(ch2) {
  function isOctalDigit (line 30063) | function isOctalDigit(ch2) {
  function isWhiteSpace (line 30066) | function isWhiteSpace(ch2) {
  function isLineTerminator (line 30069) | function isLineTerminator(ch2) {
  function isIdentifierStart (line 30072) | function isIdentifierStart(ch2) {
  function isIdentifierPart (line 30079) | function isIdentifierPart(ch2) {
  function skipComment (line 30131) | function skipComment() {
  function scanHexEscape (line 30141) | function scanHexEscape(prefix) {
  function scanUnicodeCodePointEscape (line 30154) | function scanUnicodeCodePointEscape() {
  function getEscapedIdentifier (line 30178) | function getEscapedIdentifier() {
  function getIdentifier (line 30215) | function getIdentifier() {
  function scanIdentifier (line 30232) | function scanIdentifier() {
  function scanPunctuator (line 30254) | function scanPunctuator() {
  function scanHexLiteral (line 30378) | function scanHexLiteral(start) {
  function scanOctalLiteral (line 30399) | function scanOctalLiteral(start) {
  function scanNumericLiteral (line 30418) | function scanNumericLiteral() {
  function scanStringLiteral (line 30475) | function scanStringLiteral() {
  function testRegExp (line 30558) | function testRegExp(pattern, flags) {
  function scanRegExpBody (line 30579) | function scanRegExpBody() {
  function scanRegExpFlags (line 30619) | function scanRegExpFlags() {
  function scanRegExp (line 30644) | function scanRegExp() {
  function isIdentifierName (line 30663) | function isIdentifierName(token) {
  function advance (line 30666) | function advance() {
  function lex (line 30696) | function lex() {
  function peek2 (line 30703) | function peek2() {
  function finishArrayExpression (line 30708) | function finishArrayExpression(elements) {
  function finishBinaryExpression (line 30713) | function finishBinaryExpression(operator2, left, right) {
  function finishCallExpression (line 30720) | function finishCallExpression(callee, args) {
  function finishConditionalExpression (line 30726) | function finishConditionalExpression(test2, consequent, alternate) {
  function finishIdentifier (line 30733) | function finishIdentifier(name4) {
  function finishLiteral (line 30738) | function finishLiteral(token) {
  function finishMemberExpression (line 30750) | function finishMemberExpression(accessor2, object2, property2) {
  function finishObjectExpression (line 30758) | function finishObjectExpression(properties) {
  function finishProperty (line 30763) | function finishProperty(kind, key2, value3) {
  function finishUnaryExpression (line 30770) | function finishUnaryExpression(operator2, argument) {
  function throwError (line 30777) | function throwError(token, messageFormat) {
  function throwUnexpected (line 30787) | function throwUnexpected(token) {
  function expect (line 30805) | function expect(value3) {
  function match (line 30811) | function match(value3) {
  function matchKeyword (line 30814) | function matchKeyword(keyword) {
  function parseArrayInitialiser (line 30817) | function parseArrayInitialiser() {
  function parseObjectPropertyKey (line 30835) | function parseObjectPropertyKey() {
  function parseObjectProperty (line 30846) | function parseObjectProperty() {
  function parseObjectInitialiser (line 30865) | function parseObjectInitialiser() {
  function parseGroupExpression (line 30890) | function parseGroupExpression() {
  function parsePrimaryExpression (line 30899) | function parsePrimaryExpression() {
  function parseArguments (line 30937) | function parseArguments() {
  function parseNonComputedProperty (line 30952) | function parseNonComputedProperty() {
  function parseNonComputedMember (line 30960) | function parseNonComputedMember() {
  function parseComputedMember (line 30964) | function parseComputedMember() {
  function parseLeftHandSideExpressionAllowCall (line 30970) | function parseLeftHandSideExpressionAllowCall() {
  function parsePostfixExpression (line 30989) | function parsePostfixExpression() {
  function parseUnaryExpression (line 30998) | function parseUnaryExpression() {
  function binaryPrecedence (line 31015) | function binaryPrecedence(token) {
  function parseBinaryExpression (line 31067) | function parseBinaryExpression() {
  function parseConditionalExpression (line 31107) | function parseConditionalExpression() {
  function parseExpression (line 31119) | function parseExpression() {
  function parser (line 31126) | function parser(code) {
  function Functions (line 31151) | function Functions(codegen2) {
  function stripQuotes (line 31240) | function stripQuotes(s2) {
  function codegen (line 31244) | function codegen(opt) {
  function getter2 (line 31319) | function getter2(f2) {
  function testPoint (line 31346) | function testPoint(datum2, entry2) {
  function selectionTest (line 31384) | function selectionTest(name4, datum2, op) {
  function selectionIdTest (line 31406) | function selectionIdTest(name4, datum2, op) {
  function selectionTuples (line 31416) | function selectionTuples(array4, base) {
  function selectionResolve (line 31423) | function selectionResolve(name4, op, isMulti, vl5) {
  function selectionVisitor (line 31519) | function selectionVisitor(name4, args, scope, params2) {
  function data (line 31531) | function data(name4) {
  function indata (line 31535) | function indata(name4, field3, value3) {
  function setdata (line 31539) | function setdata(name4, tuples) {
  function encode (line 31544) | function encode(item, name4, retval) {
  function time2 (line 31561) | function time2(month, day, specifier) {
  function monthFormat (line 31568) | function monthFormat(month) {
  function monthAbbrevFormat (line 31571) | function monthAbbrevFormat(month) {
  function dayFormat (line 31574) | function dayFormat(day) {
  function dayAbbrevFormat (line 31577) | function dayAbbrevFormat(day) {
  function dataVisitor (line 31584) | function dataVisitor(name4, args, scope, params2) {
  function indataVisitor (line 31596) | function indataVisitor(name4, args, scope, params2) {
  function scaleVisitor (line 31604) | function scaleVisitor(name4, args, scope, params2) {
  function addScaleDependency (line 31613) | function addScaleDependency(scope, params2, name4) {
  function getScale (line 31622) | function getScale(nameOrFunction, ctx) {
  function internalScaleFunctions (line 31631) | function internalScaleFunctions(codegen2, fnctx, visitors) {
  function geoMethod (line 31643) | function geoMethod(methodName, globalMethod) {
  function geoScale (line 31656) | function geoScale(projection3, group2) {
  function inScope (line 31660) | function inScope(item) {
  function log5 (line 31672) | function log5(df, method2, args) {
  function warn (line 31680) | function warn() {
  function info (line 31683) | function info() {
  function debug (line 31686) | function debug() {
  function channel_luminance_value (line 31689) | function channel_luminance_value(channelValue) {
  function luminance (line 31696) | function luminance(color5) {
  function contrast (line 31700) | function contrast(color1, color22) {
  function merge4 (line 31704) | function merge4() {
  function equal (line 31709) | function equal(a4, b3) {
  function equalArray (line 31712) | function equalArray(a4, b3) {
  function equalObject (line 31718) | function equalObject(a4, b3) {
  function removePredicate (line 31724) | function removePredicate(props) {
  function modify (line 31727) | function modify(name4, insert2, remove2, toggle2, modify2, values4) {
  function pinchDistance (line 31763) | function pinchDistance(event2) {
  function pinchAngle (line 31767) | function pinchAngle(event2) {
  function pluck (line 31772) | function pluck(data3, name4) {
  function array3 (line 31776) | function array3(seq) {
  function sequence2 (line 31779) | function sequence2(seq) {
  function join2 (line 31782) | function join2(seq) {
  function indexof (line 31788) | function indexof(seq) {
  function lastindexof (line 31794) | function lastindexof(seq) {
  function slice3 (line 31800) | function slice3(seq) {
  function replace2 (line 31806) | function replace2(str, pattern, repl) {
  function reverse (line 31811) | function reverse(seq) {
  function sort2 (line 31814) | function sort2(seq) {
  function bandspace (line 31817) | function bandspace(count2, paddingInner2, paddingOuter2) {
  function bandwidth (line 31820) | function bandwidth(name4, group2) {
  function copy3 (line 31824) | function copy3(name4, group2) {
  function domain (line 31828) | function domain(name4, group2) {
  function invert (line 31832) | function invert(name4, range7, group2) {
  function range3 (line 31836) | function range3(name4, group2) {
  function scale4 (line 31840) | function scale4(name4, value3, group2) {
  function scaleGradient (line 31844) | function scaleGradient(scale7, p02, p1, count2, group2) {
  function geoShape (line 31861) | function geoShape(projection3, geojson, group2) {
  function pathShape (line 31867) | function pathShape(path3) {
  function treeNodes (line 31874) | function treeNodes(name4, context3) {
  function treePath (line 31878) | function treePath(name4, source4, target2) {
  function treeAncestors (line 31882) | function treeAncestors(name4, node) {
  function screen (line 31887) | function screen() {
  function windowSize (line 31891) | function windowSize() {
  function containerSize (line 31895) | function containerSize() {
  function intersect4 (line 31899) | function intersect4(b3, opt, group2) {
  function filter2 (line 31904) | function filter2(opt) {
  function lassoAppend (line 31912) | function lassoAppend(lasso, x5, y5) {
  function lassoPath (line 31918) | function lassoPath(lasso) {
  function intersectLasso (line 31924) | function intersectLasso(markname, pixelLasso, unit2) {
  function pointInPolygon (line 31941) | function pointInPolygon(testx, testy, polygon) {
  method random (line 31953) | random() {
  method isDefined (line 31972) | isDefined(_) {
  method isValid (line 31980) | isValid(_) {
  method toDate (line 31984) | toDate(_) {
  method extent (line 32036) | extent(_) {
  function buildFunctions (line 32079) | function buildFunctions(codegen2) {
  function expressionFunction (line 32088) | function expressionFunction(name4, fn, visitor) {
  function parser2 (line 32117) | function parser2(expr2, scope) {
  function parse5 (line 32150) | function parse5(spec) {
  function adjustSpatial (line 32169) | function adjustSpatial(encode2, marktype) {
  function canonicalType (line 32200) | function canonicalType(type3) {
  function isOperator (line 32203) | function isOperator(type3) {
  function isCollect (line 32206) | function isCollect(type3) {
  function expression (line 32209) | function expression(ctx, args, code) {
  function _compare (line 32216) | function _compare(u5, v3, lt, gt) {
  method get (line 32263) | get(path3) {
  method comparator (line 32269) | comparator(fields, orders) {
  function parseOperator (line 32289) | function parseOperator(spec) {
  function parseOperatorParameters (line 32297) | function parseOperatorParameters(spec) {
  function parseParameters (line 32305) | function parseParameters(spec, params2) {
  function parseParameter (line 32314) | function parseParameter(spec, ctx, params2) {
  function getOperator (line 32352) | function getOperator(_, ctx) {
  function getExpression (line 32355) | function getExpression(_, ctx, params2) {
  function getKey (line 32362) | function getKey(_, ctx) {
  function getField2 (line 32366) | function getField2(_, ctx) {
  function getCompare (line 32371) | function getCompare(_, ctx) {
  function getEncode (line 32375) | function getEncode(_, ctx) {
  function getContext (line 32384) | function getContext(_, ctx) {
  function getSubflow (line 32387) | function getSubflow(_, ctx) {
  function getTupleId (line 32396) | function getTupleId() {
  function parseStream (line 32399) | function parseStream(spec) {
  function parseUpdate (line 32426) | function parseUpdate(spec) {
  function getState (line 32441) | function getState(options) {
  function setState (line 32466) | function setState(state) {
  function context2 (line 32479) | function context2(df, transforms2, functions, expr2) {
  function Context (line 32482) | function Context(df, transforms2, functions, expr2) {
  function Subcontext (line 32496) | function Subcontext(ctx) {
  method fork (line 32512) | fork() {
  method detach (line 32517) | detach(ctx) {
  method get (line 32524) | get(id2) {
  method set (line 32527) | set(id2, node) {
  method add (line 32530) | add(spec, op) {
  method resolve (line 32571) | resolve() {
  method operator (line 32576) | operator(spec, update3) {
  method transform (line 32579) | transform(spec, type3) {
  method stream (line 32582) | stream(spec, stream2) {
  method update (line 32585) | update(spec, stream2, target2, update3, params2) {
  method operatorExpression (line 32589) | operatorExpression(expr2) {
  method parameterExpression (line 32592) | parameterExpression(expr2) {
  method eventExpression (line 32595) | eventExpression(expr2) {
  method handlerExpression (line 32598) | handlerExpression(expr2) {
  method encodeExpression (line 32601) | encodeExpression(encode2) {
  function initializeAria (line 32617) | function initializeAria(view) {
  function ariaLabel (line 32625) | function ariaLabel(el, desc) {
  function background2 (line 32628) | function background2(view) {
  function cursor (line 32638) | function cursor(view) {
  function setCursor (line 32662) | function setCursor(view, cursor3) {
  function dataref (line 32668) | function dataref(view, name4) {
  function data2 (line 32675) | function data2(name4, values4) {
  function change (line 32678) | function change(name4, changes) {
  function insert (line 32686) | function insert(name4, _) {
  function remove (line 32689) | function remove(name4, _) {
  function width (line 32692) | function width(view) {
  function height (line 32696) | function height(view) {
  function offset3 (line 32700) | function offset3(view) {
  function resizeRenderer (line 32704) | function resizeRenderer(view) {
  function eventExtend (line 32717) | function eventExtend(view, event2, item) {
  function extension (line 32731) | function extension(view, item, point9) {
  function initializeEventConfig (line 32769) | function initializeEventConfig(config) {
  function trackEventListener (line 32782) | function trackEventListener(view, sources, type3, handler) {
  function prevent (line 32789) | function prevent(view, type3) {
  function permit (line 32793) | function permit(view, key2, type3) {
  function events2 (line 32801) | function events2(source4, type3, filter3) {
  function itemFilter (line 32839) | function itemFilter(event2) {
  function markTarget (line 32842) | function markTarget(event2) {
  function invoke (line 32845) | function invoke(name4) {
  function hover (line 32850) | function hover(hoverSet, leaveSet) {
  function finalize (line 32857) | function finalize() {
  function element2 (line 32882) | function element2(tag, attr2, text4) {
  function bind2 (line 32891) | function bind2(view, el, binding) {
  function target (line 32923) | function target(bind3, node, param2, view) {
  function event (line 32934) | function event(type3) {
  function generate (line 32939) | function generate(bind3, el, param2, view) {
  function form (line 32966) | function form(bind3, el, param2, value3) {
  function checkbox (line 32980) | function checkbox(bind3, el, param2, value3) {
  function select (line 32992) | function select(bind3, el, param2, value3) {
  function radio (line 33017) | function radio(bind3, el, param2, value3) {
  function range4 (line 33043) | function range4(bind3, el, param2, value3) {
  function valuesEqual (line 33069) | function valuesEqual(a4, b3) {
  function initializeRenderer (line 33072) | function initializeRenderer(view, r2, el, constructor, scaleFactor, opt) {
  function trap (line 33076) | function trap(view, fn) {
  function initializeHandler (line 33085) | function initializeHandler(view, prevHandler, el, constructor) {
  function initialize2 (line 33094) | function initialize2(el, elBind) {
  function lookup4 (line 33118) | function lookup4(view, el, clear2) {
  function padding (line 33148) | function padding(_) {
  function renderHeadless (line 33156) | async function renderHeadless(view, type3, scaleFactor, opt) {
  function renderToImageURL (line 33162) | async function renderToImageURL(type3, scaleFactor) {
  function toBlobURL (line 33169) | function toBlobURL(data3, mime) {
  function renderToCanvas (line 33175) | async function renderToCanvas(scaleFactor, opt) {
  function renderToSVG (line 33179) | async function renderToSVG(scaleFactor) {
  function runtime (line 33183) | function runtime(view, spec, expr2) {
  function scale5 (line 33186) | function scale5(name4) {
  function viewWidth (line 33199) | function viewWidth(view, width2) {
  function viewHeight (line 33203) | function viewHeight(view, height2) {
  function initializeResize (line 33207) | function initializeResize(view) {
  function resizeView (line 33233) | function resizeView(viewWidth2, viewHeight2, width2, height2, origin, au...
  function getState2 (line 33263) | function getState2(options) {
  function dataTest (line 33270) | function dataTest(name4, data3) {
  function signalTest (line 33273) | function signalTest(name4, op) {
  function setState2 (line 33276) | function setState2(state) {
  function timer2 (line 33285) | function timer2(callback, delay) {
  function defaultTooltip2 (line 33294) | function defaultTooltip2(handler, event2, item, value3) {
  function formatTooltip (line 33298) | function formatTooltip(value3) {
  function formatObject (line 33301) | function formatObject(obj) {
  function formatArray (line 33307) | function formatArray(value3) {
  function formatValue2 (line 33310) | function formatValue2(value3) {
  function watchPixelRatio (line 33313) | function watchPixelRatio() {
  function View (line 33333) | function View(spec, options) {
  function lookupSignal (line 33384) | function lookupSignal(view, name4) {
  function findOperatorHandler (line 33387) | function findOperatorHandler(op, handler) {
  function addOperatorListener (line 33391) | function addOperatorListener(view, name4, op, handler) {
  function removeOperatorListener (line 33400) | function removeOperatorListener(view, op, handler) {
  method evaluate (line 33407) | async evaluate(encode2, prerun, postrun) {
  method dirty (line 33426) | dirty(item) {
  method description (line 33431) | description(text4) {
  method container (line 33439) | container() {
  method scenegraph (line 33442) | scenegraph() {
  method origin (line 33445) | origin() {
  method signal (line 33448) | signal(name4, value3, options) {
  method width (line 33452) | width(_) {
  method height (line 33455) | height(_) {
  method padding (line 33458) | padding(_) {
  method autosize (line 33461) | autosize(_) {
  method background (line 33464) | background(_) {
  method renderer (line 33467) | renderer(type3) {
  method tooltip (line 33476) | tooltip(handler) {
  method loader (line 33484) | loader(loader2) {
  method resize (line 33492) | resize() {
  method _resetRenderer (line 33496) | _resetRenderer() {
  method addEventListener (line 33505) | addEventListener(type3, handler, options) {
  method removeEventListener (line 33514) | removeEventListener(type3, handler) {
  method addResizeListener (line 33526) | addResizeListener(handler) {
  method removeResizeListener (line 33533) | removeResizeListener(handler) {
  method addSignalListener (line 33540) | addSignalListener(name4, handler) {
  method removeSignalListener (line 33543) | removeSignalListener(name4, handler) {
  method addDataListener (line 33546) | addDataListener(name4, handler) {
  method removeDataListener (line 33549) | removeDataListener(name4, handler) {
  method globalCursor (line 33552) | globalCursor(_) {
  method preventDefault (line 33564) | preventDefault(_) {
  function eventSelector (line 33624) | function eventSelector(selector, source4, marks) {
  function isMarkType (line 33629) | function isMarkType(type3) {
  function find3 (line 33632) | function find3(s2, i2, endChar, pushChar, popChar) {
  function parseMerge (line 33643) | function parseMerge(s2) {
  function parseSelector (line 33656) | function parseSelector(s2) {
  function parseBetween (line 33659) | function parseBetween(s2) {
  function parseStream2 (line 33686) | function parseStream2(s2) {
  function parseThrottle (line 33751) | function parseThrottle(s2) {
  function parseAutosize (line 33762) | function parseAutosize(spec) {
  function parsePadding (line 33774) | function parsePadding(spec) {
  function addEncode (line 33785) | function addEncode(object2, name4, value3, set7) {
  function addEncoders (line 33800) | function addEncoders(object2, enter, update3) {
  function extendEncode (line 33808) | function extendEncode(encode2, extra, skip) {
  function has2 (line 33815) | function has2(key2, encode2) {
  function applyDefaults (line 33837) | function applyDefaults(encode2, type3, role, style2, config) {
  function applyDefault (line 33873) | function applyDefault(defaults2, key2, value3) {
  function entry$1 (line 33881) | function entry$1(enc) {
  function color3 (line 33907) | function color3(enc) {
  function gradient2 (line 33910) | function gradient2(enc) {
  function property (line 33916) | function property(property2) {
  function field2 (line 33919) | function field2(ref2) {
  function resolveField (line 33924) | function resolveField(ref2) {
  function scale6 (line 33952) | function scale6(enc, value3) {
  function rule2 (line 33968) | function rule2(enc) {
  function parseEncode (line 33979) | function parseEncode(encode2, type3, role, style2, scope, params2) {
  function parseBlock (line 33991) | function parseBlock(block, marktype, params2, scope) {
  function expr (line 34007) | function expr(enc) {
  function parse$1 (line 34010) | function parse$1(code, scope, params2, fields) {
  function outerError (line 34018) | function outerError(prefix, name4) {
  function parseSignal (line 34021) | function parseSignal(signal, scope) {
  function Entry (line 34034) | function Entry(type3, value3, params2, parent) {
  function entry (line 34041) | function entry(type3, value3, params2, parent) {
  function operator (line 34044) | function operator(value3, params2) {
  function ref (line 34047) | function ref(op) {
  function fieldRef$1 (line 34054) | function fieldRef$1(field3, name4) {
  function compareRef (line 34063) | function compareRef(fields, orders) {
  function keyRef (line 34069) | function keyRef(fields, flat) {
  function sortKey (line 34078) | function sortKey(sort3) {
  function aggrField (line 34081) | function aggrField(op, field3) {
  function isSignal (line 34086) | function isSignal(_) {
  function isExpr$1 (line 34089) | function isExpr$1(_) {
  function hasSignal (line 34092) | function hasSignal(_) {
  function value2 (line 34099) | function value2(specValue, defaultValue) {
  function deref (line 34102) | function deref(v3) {
  function parseStream3 (line 34106) | function parseStream3(stream2, scope) {
  function eventSource (line 34110) | function eventSource(source4) {
  function mergeStream (line 34113) | function mergeStream(stream2, scope) {
  function nestedStream (line 34119) | function nestedStream(stream2, scope) {
  function eventStream (line 34125) | function eventStream(stream2, scope) {
  function streamParameters (line 34141) | function streamParameters(entry2, stream2, scope) {
  function filterMark (line 34170) | function filterMark(type3, name4, role) {
  function parseUpdate2 (line 34181) | function parseUpdate2(spec, scope, target2) {
  function streamSource (line 34218) | function streamSource(stream2, scope) {
  function mergeSources (line 34223) | function mergeSources(sources) {
  function parseSignalUpdates (line 34228) | function parseSignalUpdates(signal, scope) {
  function initScale (line 34283) | function initScale(spec, scope) {
  function parseScale (line 34293) | function parseScale(spec, scope) {
  function parseLiteral (line 34314) | function parseLiteral(v3, scope) {
  function parseArray (line 34317) | function parseArray(v3, scope) {
  function dataLookupError (line 34320) | function dataLookupError(name4) {
  function parseScaleDomain (line 34323) | function parseScaleDomain(domain4, spec, scope) {
  function explicitDomain (line 34332) | function explicitDomain(domain4, spec, scope) {
  function singularDomain (line 34335) | function singularDomain(domain4, spec, scope) {
  function multipleDomain (line 34340) | function multipleDomain(domain4, spec, scope) {
  function fieldRef (line 34351) | function fieldRef(data3, scope) {
  function ordinalMultipleDomain (line 34367) | function ordinalMultipleDomain(domain4, scope, fields) {
  function parseSort (line 34397) | function parseSort(sort3, multidomain) {
  function quantileMultipleDomain (line 34414) | function quantileMultipleDomain(domain4, scope, fields) {
  function numericMultipleDomain (line 34424) | function numericMultipleDomain(domain4, scope, fields) {
  function parseScaleBins (line 34434) | function parseScaleBins(v3, scope) {
  function parseScaleNice (line 34437) | function parseScaleNice(nice3, scope) {
  function parseScaleInterpolate (line 34443) | function parseScaleInterpolate(interpolate3, params2) {
  function parseScaleRange (line 34449) | function parseScaleRange(spec, scope, params2) {
  function parseProjection (line 34488) | function parseProjection(proj, scope) {
  function parseParameter$1 (line 34501) | function parseParameter$1(_, name4, scope) {
  function guideGroup (line 34550) | function guideGroup(mark) {
  function lookup5 (line 34555) | function lookup5(spec, config) {
  function getEncoding (line 34563) | function getEncoding(name4, encode2) {
  function getStyle (line 34567) | function getStyle(name4, scope, style2) {
  function anchorExpr (line 34571) | function anchorExpr(s2, e4, m4) {
  function tickBand (line 34575) | function tickBand(_) {
  function extendOffset (line 34607) | function extendOffset(value3, offset4) {
  function guideMark (line 34615) | function guideMark(mark, extras) {
  function legendGradient (line 34626) | function legendGradient(spec, scale7, config, userEncode) {
  function legendGradientDiscrete (line 34673) | function legendGradientDiscrete(spec, scale7, config, userEncode, dataRe...
  function legendGradientLabels (line 34720) | function legendGradientLabels(spec, config, userEncode, dataRef) {
  function legendSymbolGroups (line 34787) | function legendSymbolGroups(spec, config, userEncode, dataRef, columns2) {
  function legendSymbolLayout (line 34944) | function legendSymbolLayout(spec, config) {
  function legendTitle (line 34969) | function legendTitle(spec, config, userEncode, dataRef) {
  function clip2 (line 35029) | function clip2(clip3, scope) {
  function param (line 35042) | function param(value3) {
  function getRole (line 35045) | function getRole(spec) {
  function definition2 (line 35049) | function definition2(spec) {
  function interactive (line 35059) | function interactive(spec, scope) {
  function parseTransform (line 35062) | function parseTransform(spec, scope) {
  function parseParameters2 (line 35070) | function parseParameters2(def2, spec, scope) {
  function parseParameter2 (line 35078) | function parseParameter2(def2, spec, scope) {
  function parameterValue (line 35094) | function parameterValue(def2, value3, scope) {
  function parseIndexParameter (line 35103) | function parseIndexParameter(def2, spec, scope) {
  function parseSubParameters (line 35109) | function parseSubParameters(def2, spec, scope) {
  function parseSubParameter (line 35120) | function parseSubParameter(def2, value3, scope) {
  function parseData$1 (line 35143) | function parseData$1(from, group2, scope) {
  function getDataRef (line 35175) | function getDataRef(from, scope) {
  function DataScope (line 35178) | function DataScope(scope, input, output3, values4, aggr) {
  function fieldKey (line 35200) | function fieldKey(field3) {
  function addSortField (line 35203) | function addSortField(scope, p2, sort3) {
  function cache (line 35221) | function cache(scope, ds, name4, optype, field3, counts, index4) {
  method countsRef (line 35246) | countsRef(scope, field3, sort3) {
  method tuplesRef (line 35273) | tuplesRef() {
  method extentRef (line 35276) | extentRef(scope, field3) {
  method domainRef (line 35279) | domainRef(scope, field3) {
  method valuesRef (line 35282) | valuesRef(scope, field3, sort3) {
  method lookupRef (line 35285) | lookupRef(scope, field3) {
  method indataRef (line 35288) | indataRef(scope, field3) {
  function parseFacet (line 35292) | function parseFacet(spec, scope, group2) {
  function parseSubflow (line 35324) | function parseSubflow(spec, scope, input) {
  function parseTrigger (line 35334) | function parseTrigger(spec, scope, name4) {
  function parseMark (line 35341) | function parseMark(spec, scope) {
  function parseOverlap (line 35438) | function parseOverlap(overlap, source4, scope) {
  function parseLegend (line 35458) | function parseLegend(spec, scope) {
  function legendType (line 35525) | function legendType(spec, scaleType2) {
  function scaleCount (line 35532) | function scaleCount(spec) {
  function buildLegendEncode (line 35535) | function buildLegendEncode(_, spec, config) {
  function sizeExpression (line 35558) | function sizeExpression(spec, scope, marks) {
  function getChannel (line 35562) | function getChannel(name4, spec, marks) {
  function getFontSize (line 35565) | function getFontSize(encode2, scope, style2) {
  function parseTitle (line 35569) | function parseTitle(spec, scope) {
  function titleEncode (line 35592) | function titleEncode(spec) {
  function groupEncode (line 35600) | function groupEncode(_, userEncode) {
  function buildTitle (line 35621) | function buildTitle(spec, _, userEncode, dataRef) {
  function buildSubTitle (line 35671) | function buildSubTitle(spec, _, userEncode, dataRef) {
  function parseData (line 35721) | function parseData(data3, scope) {
  function analyze (line 35735) | function analyze(data3, scope, ops2) {
  function collect (line 35788) | function collect(values4) {
  function load2 (line 35795) | function load2(scope, data3) {
  function fallback (line 35856) | function fallback(prop, config, axisConfig2, style2) {
  function keys2 (line 35886) | function keys2(objects) {
  function axisConfig (line 35894) | function axisConfig(spec, scope) {
  function axisDomain (line 35913) | function axisDomain(spec, config, userEncode, dataRef) {
  function position (line 35948) | function position(spec, pos) {
  function axisGrid (line 35954) | function axisGrid(spec, config, userEncode, dataRef, band2) {
  function offsetValue2 (line 36021) | function offsetValue2(offset4, sign3) {
  function axisTicks (line 36043) | function axisTicks(spec, config, userEncode, dataRef, size, band2) {
  function flushExpr (line 36089) | function flushExpr(scale7, threshold2, a4, b3, c4) {
  function axisLabels (line 36094) | function axisLabels(spec, config, userEncode, dataRef, size, band2) {
  function axisTitle (line 36184) | function axisTitle(spec, config, userEncode, dataRef) {
  function autoLayout (line 36241) | function autoLayout(_, orient2, encode2, userEncode) {
  function parseAxis (line 36246) | function parseAxis(spec, scope) {
  function buildAxisEncode (line 36298) | function buildAxisEncode(_, spec) {
  function parseScope (line 36320) | function parseScope(spec, scope, preprocessed) {
  function parseView (line 36353) | function parseView(spec, scope) {
  function signalObject (line 36390) | function signalObject(name4, value3) {
  function collectSignals (line 36399) | function collectSignals(spec, config) {
  function Scope (line 36416) | function Scope(config, options) {
  function Subscope (line 36439) | function Subscope(scope) {
  method parse (line 36461) | parse(spec) {
  method fork (line 36464) | fork() {
  method isSubscope (line 36467) | isSubscope() {
  method toRuntime (line 36470) | toRuntime() {
  method id (line 36482) | id() {
  method add (line 36485) | add(op) {
  method proxy (line 36496) | proxy(op) {
  method addStream (line 36502) | addStream(stream2) {
  method addUpdate (line 36507) | addUpdate(update3) {
  method finish (line 36512) | finish() {
  method pushState (line 36541) | pushState(encode2, parent, lookup6) {
  method popState (line 36549) | popState() {
  method parent (line 36555) | parent() {
  method encode (line 36558) | encode() {
  method lookup (line 36561) | lookup() {
  method markpath (line 36564) | markpath() {
  method fieldRef (line 36569) | fieldRef(field3, name4) {
  method compareRef (line 36585) | compareRef(cmp) {
  method keyRef (line 36594) | keyRef(fields, flat) {
  method sortRef (line 36604) | sortRef(sort3) {
  method event (line 36613) | event(source4, type3) {
  method hasOwnSignal (line 36627) | hasOwnSignal(name4) {
  method addSignal (line 36630) | addSignal(name4, value3) {
  method getSignal (line 36637) | getSignal(name4) {
  method signalRef (line 36643) | signalRef(s2) {
  method parseLambdas (line 36651) | parseLambdas() {
  method property (line 36659) | property(spec) {
  method objectProperty (line 36662) | objectProperty(spec) {
  method exprRef (line 36665) | exprRef(code, name4) {
  method addBinding (line 36672) | addBinding(name4, bind3) {
  method addScaleProj (line 36681) | addScaleProj(name4, transform4) {
  method addScale (line 36687) | addScale(name4, params2) {
  method addProjection (line 36690) | addProjection(name4, params2) {
  method getScale (line 36693) | getScale(name4) {
  method scaleRef (line 36699) | scaleRef(name4) {
  method scaleType (line 36702) | scaleType(name4) {
  method projectionRef (line 36705) | projectionRef(name4) {
  method projectionType (line 36708) | projectionType(name4) {
  method addData (line 36712) | addData(name4, dataScope) {
  method getData (line 36718) | getData(name4) {
  method addDataPipeline (line 36724) | addDataPipeline(name4, entries3) {
  function propertyLambda (line 36731) | function propertyLambda(spec) {
  function arrayLambda (line 36734) | function arrayLambda(array4) {
  function objectLambda (line 36743) | function objectLambda(obj) {
  function defaults (line 36751) | function defaults() {
  function parse6 (line 36967) | function parse6(spec, config, options) {
  function adjustSpatial2 (line 36980) | function adjustSpatial2(item, encode2, swap3) {
  function interpret (line 37189) | function interpret(ast, fn, params2, datum2, event2, item) {
  method operator (line 37206) | operator(ctx, expr2) {
  method parameter (line 37213) | parameter(ctx, expr2) {
  method event (line 37220) | event(ctx, expr2) {
  method handler (line 37227) | handler(ctx, expr2) {
  method encode (line 37237) | encode(ctx, encode2) {
  function isLogicalOr (line 37457) | function isLogicalOr(op) {
  function isLogicalAnd (line 37460) | function isLogicalAnd(op) {
  function isLogicalNot (line 37463) | function isLogicalNot(op) {
  function forEachLeaf (line 37466) | function forEachLeaf(op, fn) {
  function normalizeLogicalComposition (line 37481) | function normalizeLogicalComposition(op, normalizer) {
  function never (line 37495) | function never(message) {
  function pick2 (line 37498) | function pick2(obj, props) {
  function omit (line 37507) | function omit(obj, props) {
  function hash (line 37517) | function hash(a4) {
  function isNullOrFalse (line 37533) | function isNullOrFalse(x5) {
  function contains2 (line 37536) | function contains2(array4, item) {
  function some (line 37539) | function some(arr, f2) {
  function every (line 37548) | function every(arr, f2) {
  function mergeDeep (line 37557) | function mergeDeep(dest, ...src) {
  function deepMerge_ (line 37563) | function deepMerge_(dest, src) {
  function unique (line 37568) | function unique(values4, f2) {
  function isEqual (line 37582) | function isEqual(dict, other) {
  function setEqual (line 37595) | function setEqual(a4, b3) {
  function hasIntersection (line 37606) | function hasIntersection(a4, b3) {
  function prefixGenerator (line 37614) | function prefixGenerator(a4) {
  function fieldIntersection (line 37626) | function fieldIntersection(a4, b3) {
  function isEmpty (line 37632) | function isEmpty(obj) {
  function isBoolean3 (line 37638) | function isBoolean3(b3) {
  function varName (line 37641) | function varName(s2) {
  function logicalExpr (line 37645) | function logicalExpr(op, cb) {
  function deleteNestedProperty (line 37656) | function deleteNestedProperty(obj, orderedProps) {
  function titleCase (line 37666) | function titleCase(s2) {
  function accessPathWithDatum (line 37669) | function accessPathWithDatum(path3, datum2 = "datum") {
  function flatAccessWithDatum (line 37678) | function flatAccessWithDatum(path3, datum2 = "datum") {
  function accessWithDatumToUnescapedPath (line 37681) | function accessWithDatumToUnescapedPath(unescapedPath) {
  function escapePathAccess (line 37685) | function escapePathAccess(string) {
  function replacePathInField (line 37688) | function replacePathInField(path3) {
  function replaceAll (line 37691) | function replaceAll(string, find4, replacement) {
  function removePathFromField (line 37694) | function removePathFromField(path3) {
  function accessPathDepth (line 37697) | function accessPathDepth(path3) {
  function getFirstDefined (line 37703) | function getFirstDefined(...args) {
  function uniqueId (line 37707) | function uniqueId(prefix) {
  function resetIdCounter (line 37711) | function resetIdCounter() {
  function internalField (line 37714) | function internalField(name4) {
  function isInternalField (line 37717) | function isInternalField(name4) {
  function normalizeAngle (line 37720) | function normalizeAngle(angle2) {
  function isNumeric (line 37726) | function isNumeric(value3) {
  function deepEqual (line 37733) | function deepEqual(a4, b3) {
  function stringify2 (line 37800) | function stringify2(data3) {
  function hasProperty (line 37843) | function hasProperty(obj, key2) {
  function isPolarPositionChannel (line 37897) | function isPolarPositionChannel(c4) {
  function getPositionChannelFromLatLong (line 37906) | function getPositionChannelFromLatLong(channel) {
  function isGeoPositionChannel (line 37918) | function isGeoPositionChannel(c4) {
  function isColorChannel (line 37953) | function isColorChannel(channel) {
  function isSingleDefUnitChannel (line 37971) | function isSingleDefUnitChannel(str) {
  function isChannel (line 37974) | function isChannel(str) {
  function isSecondaryRangeChannel (line 37978) | function isSecondaryRangeChannel(c4) {
  function getMainRangeChannel (line 37982) | function getMainRangeChannel(channel) {
  function getVgPositionChannel (line 37999) | function getVgPositionChannel(channel) {
  function getSecondaryRangeChannel (line 38014) | function getSecondaryRangeChannel(channel) {
  function getSizeChannel (line 38031) | function getSizeChannel(channel) {
  function getOffsetChannel (line 38042) | function getOffsetChannel(channel) {
  function getOffsetScaleChannel (line 38063) | function getOffsetScaleChannel(channel) {
  function getMainChannelFromOffsetChannel (line 38072) | function getMainChannelFromOffsetChannel(channel) {
  function isXorY (line 38107) | function isXorY(channel) {
  function getPositionScaleChannel (line 38115) | function getPositionScaleChannel(sizeType) {
  function isXorYOffset (line 38120) | function isXorYOffset(channel) {
  function isTime (line 38127) | function isTime(channel) {
  function isNonPositionScaleChannel (line 38146) | function isNonPositionScaleChannel(channel) {
  function supportLegend (line 38149) | function supportLegend(channel) {
  function isScaleChannel (line 38174) | function isScaleChannel(channel) {
  function supportMark (line 38177) | function supportMark(channel, mark) {
  function getSupportedMark (line 38198) | function getSupportedMark(channel) {
  function rangeType (line 38286) | function rangeType(channel) {
  function isArgminDef (line 38369) | function isArgminDef(a4) {
  function isArgmaxDef (line 38372) | function isArgmaxDef(a4) {
  function isAggregateOp (line 38375) | function isAggregateOp(a4) {
  function isCountingAggregateOp (line 38384) | function isCountingAggregateOp(aggregate) {
  function isMinMaxOp (line 38387) | function isMinMaxOp(aggregate) {
  function binToString (line 38408) | function binToString(bin3) {
  function isBinning (line 38414) | function isBinning(bin3) {
  function isBinned (line 38417) | function isBinned(bin3) {
  function isBinParams (line 38420) | function isBinParams(bin3) {
  function isParameterExtent (line 38423) | function isParameterExtent(extent2) {
  function autoMaxBins (line 38426) | function autoMaxBins(channel) {
  function isExprRef (line 38452) | function isExprRef(o2) {
  function replaceExprRef (line 38455) | function replaceExprRef(index4, { level } = { level: 0 }) {
  function extractTitleConfig (line 38465) | function extractTitleConfig(titleConfig) {
  function isText (line 38511) | function isText(v3) {
  function isSignalRef (line 38516) | function isSignalRef(o2) {
  function isVgRangeStep (line 38519) | function isVgRangeStep(range7) {
  function isDataRefUnionedDomain (line 38522) | function isDataRefUnionedDomain(domain4) {
  function isFieldRefUnionDomain (line 38528) | function isFieldRefUnionDomain(domain4) {
  function isDataRefDomain (line 38534) | function isDataRefDomain(domain4) {
  function signalOrValueRefWithCondition (line 38632) | function signalOrValueRefWithCondition(val) {
  function signalRefOrValue (line 38639) | function signalRefOrValue(value3) {
  function conditionalSignalRefOrValue (line 38646) | function conditionalSignalRefOrValue(value3) {
  function signalOrValueRef (line 38653) | function signalOrValueRef(value3) {
  function exprFromSignalRefOrValue (line 38663) | function exprFromSignalRefOrValue(ref2) {
  function exprFromValueRefOrSignalRef (line 38669) | function exprFromValueRefOrSignalRef(ref2) {
  function signalOrStringValue (line 38675) | function signalOrStringValue(v3) {
  function applyMarkConfig (line 38681) | function applyMarkConfig(e4, model, propsList) {
  function getStyles (line 38690) | function getStyles(mark) {
  function getMarkPropOrConfig (line 38693) | function getMarkPropOrConfig(channel, mark, config, opt = {}) {
  function getMarkConfig (line 38704) | function getMarkConfig(channel, mark, config, { vgChannel } = {}) {
  function getMarkStyleConfig (line 38720) | function getMarkStyleConfig(prop, mark, styleConfigIndex) {
  function getStyleConfig (line 38723) | function getStyleConfig(p2, styles, styleConfigIndex) {
  function sortParams (line 38734) | function sortParams(orderDef, fieldRefOption) {
  function mergeTitleFieldDefs (line 38741) | function mergeTitleFieldDefs(f1, f2) {
  function mergeTitle (line 38753) | function mergeTitle(title1, title2) {
  function mergeTitleComponent (line 38762) | function mergeTitleComponent(v1, v22) {
  function invalidSpec (line 38884) | function invalidSpec(spec) {
  function containerSizeNonSingle (line 38888) | function containerSizeNonSingle(name4) {
  function containerSizeNotCompatibleWithAutosize (line 38892) | function containerSizeNotCompatibleWithAutosize(name4) {
  function droppingFit (line 38897) | function droppingFit(channel) {
  function unknownField (line 38900) | function unknownField(channel) {
  function cannotProjectOnChannelWithoutField (line 38903) | function cannotProjectOnChannelWithoutField(channel) {
  function cannotProjectAggregate (line 38906) | function cannotProjectAggregate(channel, aggregate) {
  function nearestNotSupportForContinuous (line 38909) | function nearestNotSupportForContinuous(mark) {
  function selectionNotSupported (line 38912) | function selectionNotSupported(mark) {
  function selectionNotFound (line 38915) | function selectionNotFound(name4) {
  function cannotLookupVariableParameter (line 38921) | function cannotLookupVariableParameter(name4) {
  function noSameUnitLookup (line 38924) | function noSameUnitLookup(name4) {
  function noSuchRepeatedValue (line 38929) | function noSuchRepeatedValue(field3) {
  function columnsNotSupportByRowCol (line 38932) | function columnsNotSupportByRowCol(type3) {
  function selectionAsScaleDomainWithoutField (line 38937) | function selectionAsScaleDomainWithoutField(field3) {
  function selectionAsScaleDomainWrongEncodings (line 38940) | function selectionAsScaleDomainWrongEncodings(encodings, encoding, exten...
  function unrecognizedParse (line 38944) | function unrecognizedParse(p2) {
  function differentParse (line 38947) | function differentParse(field3, local, ancestor) {
  function invalidTransformIgnored (line 38951) | function invalidTransformIgnored(transform4) {
  function customFormatTypeNotAllowed (line 38955) | function customFormatTypeNotAllowed(channel) {
  function projectionOverridden (line 38958) | function projectionOverridden(opt) {
  function offsetNestedInsideContinuousPositionScaleDropped (line 38963) | function offsetNestedInsideContinuousPositionScaleDropped(mainChannel) {
  function primitiveChannelDef (line 38966) | function primitiveChannelDef(channel, type3, value3) {
  function invalidFieldType (line 38969) | function invalidFieldType(type3) {
  function invalidFieldTypeForCountAggregate (line 38972) | function invalidFieldTypeForCountAggregate(type3, aggregate) {
  function invalidAggregate (line 38975) | function invalidAggregate(aggregate) {
  function missingFieldType (line 38978) | function missingFieldType(channel, newType) {
  function droppingColor (line 38981) | function droppingColor(type3, opt) {
  function relativeBandSizeNotSupported (line 38985) | function relativeBandSizeNotSupported(sizeChannel) {
  function emptyFieldDef (line 38988) | function emptyFieldDef(fieldDef, channel) {
  function incompatibleChannel (line 38992) | function incompatibleChannel(channel, markOrFacet, when) {
  function offsetEncodingScaleIgnored (line 38995) | function offsetEncodingScaleIgnored(channel) {
  function invalidEncodingChannel (line 38998) | function invalidEncodingChannel(channel) {
  function channelShouldBeDiscrete (line 39001) | function channelShouldBeDiscrete(channel) {
  function channelShouldBeDiscreteOrDiscretizing (line 39004) | function channelShouldBeDiscreteOrDiscretizing(channel) {
  function facetChannelDropped (line 39007) | function facetChannelDropped(channels) {
  function discreteChannelCannotEncode (line 39010) | function discreteChannelCannotEncode(channel, type3) {
  function rangeMarkAlignmentCannotBeExpression (line 39013) | function rangeMarkAlignmentCannotBeExpression(align2) {
  function lineWithRange (line 39016) | function lineWithRange(hasX2, hasY2) {
  function orientOverridden (line 39020) | function orientOverridden(original, actual) {
  function cannotUseScalePropertyWithNonColor (line 39024) | function cannotUseScalePropertyWithNonColor(prop) {
  function cannotUseRelativeBandSizeWithNonBandScale (line 39027) | function cannotUseRelativeBandSizeWithNonBandScale(scaleType2) {
  function unaggregateDomainHasNoEffectForRawField (line 39030) | function unaggregateDomainHasNoEffectForRawField(fieldDef) {
  function unaggregateDomainWithNonSharedDomainOp (line 39033) | function unaggregateDomainWithNonSharedDomainOp(aggregate) {
  function unaggregatedDomainWithLogScale (line 39036) | function unaggregatedDomainWithLogScale(fieldDef) {
  function cannotApplySizeToNonOrientedMark (line 39039) | function cannotApplySizeToNonOrientedMark(mark) {
  function scaleTypeNotWorkWithChannel (line 39042) | function scaleTypeNotWorkWithChannel(channel, scaleType2, defaultScaleTy...
  function scaleTypeNotWorkWithFieldDef (line 39045) | function scaleTypeNotWorkWithFieldDef(scaleType2, defaultScaleType) {
  function scalePropertyNotWorkWithScaleType (line 39048) | function scalePropertyNotWorkWithScaleType(scaleType2, propName, channel) {
  function scaleTypeNotWorkWithMark (line 39051) | function scaleTypeNotWorkWithMark(mark, scaleType2) {
  function stepDropped (line 39054) | function stepDropped(channel) {
  function mergeConflictingProperty (line 39057) | function mergeConflictingProperty(property2, propertyOf, v1, v22) {
  function mergeConflictingDomainProperty (line 39060) | function mergeConflictingDomainProperty(property2, propertyOf, v1, v22) {
  function independentScaleMeansIndependentGuide (line 39063) | function independentScaleMeansIndependentGuide(channel) {
  function domainSortDropped (line 39066) | function domainSortDropped(sort3) {
  function cannotStackRangedMark (line 39074) | function cannotStackRangedMark(channel) {
  function stackNonLinearScale (line 39077) | function stackNonLinearScale(scaleType2) {
  function stackNonSummativeAggregate (line 39080) | function stackNonSummativeAggregate(aggregate) {
  function invalidTimeUnit (line 39083) | function invalidTimeUnit(unitName2, value3) {
  function droppedDay (line 39086) | function droppedDay(d2) {
  function errorBarCenterAndExtentAreNotNeeded (line 39089) | function errorBarCenterAndExtentAreNotNeeded(center, extent2) {
  function errorBarCenterIsUsedWithWrongExtent (line 39092) | function errorBarCenterIsUsedWithWrongExtent(center, extent2, mark) {
  function errorBarContinuousAxisHasCustomizedAggregate (line 39095) | function errorBarContinuousAxisHasCustomizedAggregate(aggregate, composi...
  function errorBand1DNotSupport (line 39098) | function errorBand1DNotSupport(property2) {
  function channelRequiredForBinned (line 39101) | function channelRequiredForBinned(channel) {
  function channelShouldNotBeUsedForBinned (line 39104) | function channelShouldNotBeUsedForBinned(channel) {
  function domainRequiredForThresholdScale (line 39107) | function domainRequiredForThresholdScale(channel) {
  function set6 (line 39116) | function set6(newLogger) {
  function reset2 (line 39120) | function reset2() {
  function error2 (line 39124) | function error2(...args) {
  function warn2 (line 39127) | function warn2(...args) {
  function debug2 (line 39130) | function debug2(...args) {
  function isDateTime (line 39135) | function isDateTime(o2) {
  function normalizeQuarter (line 39162) | function normalizeQuarter(q2) {
  function normalizeMonth (line 39175) | function normalizeMonth(m4) {
  function normalizeDay (line 39195) | function normalizeDay(d2) {
  function dateTimeParts (line 39215) | function dateTimeParts(d2, normalize4) {
  function dateTimeToExpr (line 39252) | function dateTimeToExpr(d2) {
  function dateTimeExprToExpr (line 39261) | function dateTimeExprToExpr(d2) {
  function dateTimeToTimestamp (line 39270) | function dateTimeToTimestamp(d2) {
  function isLocalSingleTimeUnit (line 39294) | function isLocalSingleTimeUnit(timeUnit) {
  function isBinnedTimeUnit (line 39333) | function isBinnedTimeUnit(timeUnit) {
  function isBinnedTimeUnitString (line 39339) | function isBinnedTimeUnitString(timeUnit) {
  function isUTCTimeUnit (line 39342) | function isUTCTimeUnit(t4) {
  function getLocalTimeUnitFromUTCTimeUnit (line 39345) | function getLocalTimeUnitFromUTCTimeUnit(t4) {
  function getTimeUnitParts (line 39352) | function getTimeUnitParts(timeUnit) {
  function getSmallestTimeUnitPart (line 39355) | function getSmallestTimeUnitPart(timeUnit) {
  function containsTimeUnit (line 39359) | function containsTimeUnit(fullTimeUnit, timeUnit) {
  function fieldExpr (line 39375) | function fieldExpr(fullTimeUnit, field3, { end } = { end: false }) {
  function timeUnitSpecifierExpression (line 39398) | function timeUnitSpecifierExpression(timeUnit) {
  function formatExpression (line 39405) | function formatExpression(timeUnit, field3, isUTCScale) {
  function normalizeTimeUnit (line 39413) | function normalizeTimeUnit(timeUnit) {
  function timeUnitToString (line 39441) | function timeUnitToString(tu) {
  function durationExpr (line 39449) | function durationExpr(timeUnit, wrap2 = (x5) => x5) {
  function isDatePart (line 39481) | function isDatePart(timeUnit) {
  function getDateTimePartAndStep (line 39484) | function getDateTimePartAndStep(timeUnit, step = 1) {
  function isSelectionPredicate (line 39500) | function isSelectionPredicate(predicate) {
  function isFieldEqualPredicate (line 39503) | function isFieldEqualPredicate(predicate) {
  function isFieldLTPredicate (line 39506) | function isFieldLTPredicate(predicate) {
  function isFieldLTEPredicate (line 39509) | function isFieldLTEPredicate(predicate) {
  function isFieldGTPredicate (line 39512) | function isFieldGTPredicate(predicate) {
  function isFieldGTEPredicate (line 39515) | function isFieldGTEPredicate(predicate) {
  function isFieldRangePredicate (line 39518) | function isFieldRangePredicate(predicate) {
  function isFieldOneOfPredicate (line 39528) | function isFieldOneOfPredicate(predicate) {
  function isFieldValidPredicate (line 39531) | function isFieldValidPredicate(predicate) {
  function isFieldPredicate (line 39534) | function isFieldPredicate(predicate) {
  function predicateValueExpr (line 39537) | function predicateValueExpr(v3, timeUnit) {
  function predicateValuesExpr (line 39540) | function predicateValuesExpr(vals2, timeUnit) {
  function fieldFilterExpression (line 39543) | function fieldFilterExpression(predicate, useInRange = true) {
  function fieldValidPredicate (line 39590) | function fieldValidPredicate(fieldExpr2, valid = true) {
  function normalizePredicate (line 39597) | function normalizePredicate(f2) {
  function isContinuous2 (line 39615) | function isContinuous2(type3) {
  function isDiscrete2 (line 39618) | function isDiscrete2(type3) {
  function getFullName (line 39627) | function getFullName(type3) {
  function scaleCompatible (line 39693) | function scaleCompatible(scaleType1, scaleType2) {
  function scaleTypePrecedence (line 39721) | function scaleTypePrecedence(scaleType2) {
  function isQuantitative (line 39736) | function isQuantitative(type3) {
  function hasDiscreteDomain (line 39756) | function hasDiscreteDomain(type3) {
  function hasContinuousDomain (line 39759) | function hasContinuousDomain(type3) {
  function isContinuousToContinuous (line 39762) | function isContinuousToContinuous(type3) {
  function isContinuousToDiscrete (line 39765) | function isContinuousToDiscrete(type3) {
  function isExtendedScheme (line 39791) | function isExtendedScheme(scheme3) {
  function isParameterDomain (line 39794) | function isParameterDomain(domain4) {
  function isDomainUnionWith (line 39797) | function isDomainUnionWith(domain4) {
  function isFieldRange (line 39800) | function isFieldRange(range7) {
  function scaleTypeSupportProperty (line 39837) | function scaleTypeSupportProperty(scaleType2, propName) {
  function channelScalePropertyIncompatability (line 39888) | function channelScalePropertyIncompatability(channel, propName) {
  function scaleTypeSupportDataType (line 39921) | function scaleTypeSupportDataType(specifiedType, fieldDefType) {
  function channelSupportScaleType (line 39931) | function channelSupportScaleType(channel, scaleType2, hasNestedOffsetSca...
  function isScaleInvalidDataIncludeAsValue (line 39972) | function isScaleInvalidDataIncludeAsValue(invalidDataMode) {
  function isPathMark (line 40007) | function isPathMark(m4) {
  function isRectBasedMark (line 40010) | function isRectBasedMark(m4) {
  function isMarkDef (line 40021) | function isMarkDef(mark) {
  function isRelativeBandSize (line 40082) | function isRelativeBandSize(o2) {
  function getMarkType (line 40104) | function getMarkType(m4) {
  function normalizeInvalidDataMode (line 40109) | function normalizeInvalidDataMode(mode, { isPath }) {
  function getScaleInvalidDataMode (line 40119) | function getScaleInvalidDataMode({ markDef, config, scaleChannel, scaleT...
  function shouldBreakPath (line 40132) | function shouldBreakPath(mode) {
  function scaledZeroOrMinOrMax (line 40137) | function scaledZeroOrMinOrMax({ scaleName, scale: scale7, mode }) {
  function getConditionalValueRefForIncludingInvalidValue (line 40159) | function getConditionalValueRefForIncludingInvalidValue({ scaleChannel, ...
  function refForInvalidValues (line 40179) | function refForInvalidValues(includeAs, scale7, scaleName) {
  function midPointRefWithPositionInvalidTest (line 40192) | function midPointRefWithPositionInvalidTest(params2) {
  function datumDefToExpr (line 40206) | function datumDefToExpr(datumDef) {
  function valueRefForFieldOrDatumDef (line 40213) | function valueRefForFieldOrDatumDef(fieldDef, scaleName, opt, encode2) {
  function interpolatedSignalRef (line 40243) | function interpolatedSignalRef({ scaleName, fieldOrDatumDef, fieldOrDatu...
  function binSizeExpr (line 40261) | function binSizeExpr({ scaleName, fieldDef }) {
  function midPoint (line 40266) | function midPoint({ channel, channelDef, channel2Def, markDef, config, s...
  function widthHeightValueOrSignalRef (line 40332) | function widthHeightValueOrSignalRef(channel, value3) {
  function isCustomFormatType (line 40342) | function isCustomFormatType(formatType) {
  function customFormatExpr (line 40345) | function customFormatExpr(formatType, field3, format5) {
  function formatSignalRef (line 40349) | function formatSignalRef({ fieldOrDatumDef, format: format5, formatType,...
  function fieldToFormat (line 40416) | function fieldToFormat(fieldOrDatumDef, expr2, normalizeStack) {
  function formatCustomType (line 40430) | function formatCustomType({ fieldOrDatumDef, format: format5, formatType...
  function guideFormat (line 40441) | function guideFormat(fieldOrDatumDef, type3, format5, formatType, config...
  function guideFormatType (line 40470) | function guideFormatType(formatType, fieldOrDatumDef, scaleType2) {
  function numberFormat (line 40479) | function numberFormat({ type: type3, specifiedFormat, config, normalizeS...
  function timeFormat3 (line 40488) | function timeFormat3({ specifiedFormat, timeUnit, config, omitTimeFormat...
  function formatExpr (line 40499) | function formatExpr(field3, format5) {
  function binNumberFormatExpr (line 40502) | function binNumberFormatExpr(field3, format5, formatType, config) {
  function binFormatExpression (line 40508) | function binFormatExpression(startField, endField, format5, formatType, ...
  function timeFormatExpression (line 40516) | function timeFormatExpression({ field: field3, timeUnit, format: format5...
  function isSortByChannel (line 40544) | function isSortByChannel(c4) {
  function isSortByEncoding (line 40547) | function isSortByEncoding(sort3) {
  function isSortField (line 40550) | function isSortField(sort3) {
  function isSortArray (line 40553) | function isSortArray(sort3) {
  function isFacetMapping (line 40558) | function isFacetMapping(f2) {
  function isFacetFieldDef (line 40561) | function isFacetFieldDef(channelDef) {
  function isFacetSpec (line 40564) | function isFacetSpec(spec) {
  function isConditionalParameter (line 40569) | function isConditionalParameter(c4) {
  function isRepeatRef (line 40572) | function isRepeatRef(field3) {
  function toFieldDefBase (line 40575) | function toFieldDefBase(fieldDef) {
  function isSortableFieldDef (line 40584) | function isSortableFieldDef(fieldDef) {
  function getBandPosition (line 40587) | function getBandPosition({ fieldDef, fieldDef2, markDef: mark, config }) {
  function getBandSize (line 40601) | function getBandSize({ channel, fieldDef, fieldDef2, markDef: mark, conf...
  function hasBandEnd (line 40629) | function hasBandEnd(fieldDef, fieldDef2, markDef, config) {
  function isOrderOnlyDef (line 40635) | function isOrderOnlyDef(orderDef) {
  function isConditionalDef (line 40638) | function isConditionalDef(channelDef) {
  function hasConditionalFieldDef (line 40641) | function hasConditionalFieldDef(channelDef) {
  function hasConditionalFieldOrDatumDef (line 40645) | function hasConditionalFieldOrDatumDef(channelDef) {
  function hasConditionalValueDef (line 40649) | function hasConditionalValueDef(channelDef) {
  function isFieldDef (line 40653) | function isFieldDef(channelDef) {
  function channelDefType (line 40656) | function channelDefType(channelDef) {
  function isDatumDef (line 40659) | function isDatumDef(channelDef) {
  function isContinuousFieldOrDatumDef (line 40662) | function isContinuousFieldOrDatumDef(cd2) {
  function isUnbinnedQuantitativeFieldOrDatumDef (line 40665) | function isUnbinnedQuantitativeFieldOrDatumDef(cd2) {
  function isNumericDataDef (line 40668) | function isNumericDataDef(cd2) {
  function isFieldOrDatumDef (line 40671) | function isFieldOrDatumDef(channelDef) {
  function isTypedFieldDef (line 40674) | function isTypedFieldDef(channelDef) {
  function isValueDef (line 40677) | function isValueDef(channelDef) {
  function isScaleFieldDef (line 40680) | function isScaleFieldDef(channelDef) {
  function isPositionFieldOrDatumDef (line 40683) | function isPositionFieldOrDatumDef(channelDef) {
  function isMarkPropFieldOrDatumDef (line 40686) | function isMarkPropFieldOrDatumDef(channelDef) {
  function isStringFieldOrDatumDef (line 40689) | function isStringFieldOrDatumDef(channelDef) {
  function toStringFieldDef (line 40692) | function toStringFieldDef(fieldDef) {
  function isOpFieldDef (line 40695) | function isOpFieldDef(fieldDef) {
  function vgField (line 40698) | function vgField(fieldDef, opt = {}) {
  function isDiscrete3 (line 40749) | function isDiscrete3(def2) {
  function isDiscretizing2 (line 40762) | function isDiscretizing2(def2) {
  function isCount (line 40765) | function isCount(fieldDef) {
  function verbalTitleFormatter (line 40768) | function verbalTitleFormatter(fieldDef, config) {
  function functionalTitleFormatter (line 40790) | function functionalTitleFormatter(fieldDef) {
  function setTitleFormatter (line 40812) | function setTitleFormatter(formatter) {
  function resetTitleFormatter (line 40815) | function resetTitleFormatter() {
  function title (line 40818) | function title(fieldOrDatumDef, config, { allowDisabling, includeDefault...
  function getGuide (line 40831) | function getGuide(fieldDef) {
  function defaultTitle (line 40841) | function defaultTitle(fieldDef, config) {
  function getFormatMixins (line 40844) | function getFormatMixins(fieldDef) {
  function defaultType (line 40854) | function defaultType(fieldDef, channel) {
  function getFieldDef (line 40889) | function getFieldDef(channelDef) {
  function getFieldOrDatumDef (line 40897) | function getFieldOrDatumDef(channelDef) {
  function initChannelDef (line 40905) | function initChannelDef(channelDef, channel, config, opt = {}) {
  function initFieldOrDatumDef (line 40922) | function initFieldOrDatumDef(fd, channel, config, opt) {
  function initDatumDef (line 40944) | function initDatumDef(datumDef) {
  function initFieldDef (line 40953) | function initFieldDef(fd, channel, { compositeMark = false } = {}) {
  function normalizeBin (line 41028) | function normalizeBin(bin3, channel) {
  function channelCompatibility (line 41042) | function channelCompatibility(fieldDef, channel) {
  function isFieldOrDatumDefForTimeFormat (line 41126) | function isFieldOrDatumDefForTimeFormat(fieldOrDatumDef) {
  function isTemporalFieldDef (line 41130) | function isTemporalFieldDef(def2) {
  function valueExpr (line 41133) | function valueExpr(v3, { timeUnit, type: type3, wrapTime, undefinedIfExp...
  function valueArray (line 41159) | function valueArray(fieldOrDatumDef, values4) {
  function binRequiresRange (line 41174) | function binRequiresRange(fieldDef, channel) {
  function isConditionalAxisValue (line 41262) | function isConditionalAxisValue(v3) {
  function isAxisProperty (line 41437) | function isAxisProperty(prop) {
  function isUnitSpec (line 41468) | function isUnitSpec(spec) {
  method constructor (line 41474) | constructor(name4, run2) {
  method hasMatchingType (line 41478) | hasMatchingType(spec) {
  function channelHasField (line 41487) | function channelHasField(encoding, channel) {
  function channelHasFieldOrDatum (line 41498) | function channelHasFieldOrDatum(encoding, channel) {
  function channelHasNestedOffsetScale (line 41509) | function channelHasNestedOffsetScale(encoding, channel) {
  function isAggregate (line 41519) | function isAggregate(encoding) {
  function extractTransformsFromEncoding (line 41533) | function extractTransformsFromEncoding(oldEncoding, config) {
  function markChannelCompatible (line 41635) | function markChannelCompatible(encoding, channel, mark) {
  function initEncoding (line 41649) | function initEncoding(encoding, mark, filled, config) {
  function normalizeEncoding (line 41722) | function normalizeEncoding(encoding, config) {
  function fieldDefs (line 41730) | function fieldDefs(encoding) {
  function forEach (line 41747) | function forEach(mapping, f2, thisArg) {
  function reduce (line 41762) | function reduce(mapping, f2, init2, thisArg) {
  function pathGroupingFields (line 41777) | function pathGroupingFields(mark, encoding) {
  function filterTooltipWithAggregatedField (line 41851) | function filterTooltipWithAggregatedField(oldEncoding) {
  function getCompositeMarkTooltip (line 41887) | function getCompositeMarkTooltip(tooltipSummary, continuousAxisChannelDe...
  function getTitle (line 41908) | function getTitle(continuousAxisChannelDef) {
  function makeCompositeAggregatePartFactory (line 41912) | function makeCompositeAggregatePartFactory(compositeMarkDef, continuousA...
  function partLayerMixins (line 41938) | function partLayerMixins(markDef, part, compositeMarkConfig, partBaseSpe...
  function compositeMarkContinuousAxis (line 41959) | function compositeMarkContinuousAxis(spec, orient2, compositeMark) {
  function filterAggregateFromChannelDef (line 41974) | function filterAggregateFromChannelDef(continuousAxisChannelDef, composi...
  function compositeMarkOrient (line 41985) | function compositeMarkOrient(spec, compositeMark) {
  function getBoxPlotType (line 42020) | function getBoxPlotType(extent2) {
  function normalizeBoxPlot (line 42026) | function normalizeBoxPlot(spec, { config }) {
  function boxParamsQuartiles (line 42232) | function boxParamsQuartiles(continousAxisField) {
  function boxParams (line 42247) | function boxParams(spec, extent2, config) {
  function normalizeErrorBar (line 42319) | function normalizeErrorBar(spec, { config }) {
  function errorBarOrientAndInputType (line 42367) | function errorBarOrientAndInputType(spec, compositeMark) {
  function errorBarIsInputTypeRaw (line 42430) | function errorBarIsInputTypeRaw(encoding) {
  function errorBarIsInputTypeAggregatedUpperLower (line 42433) | function errorBarIsInputTypeAggregatedUpperLower(encoding) {
  function errorBarIsInputTypeAggregatedError (line 42436) | function errorBarIsInputTypeAggregatedError(encoding) {
  function errorBarParams (line 42439) | function errorBarPara
Condensed preview — 396 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,016K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 83,
    "preview": "# These are supported funding model platforms\n\ngithub: [emeryberger, plasma-umass]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 888,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/workflows/blacken.yml",
    "chars": 541,
    "preview": "name: Format code\n\non:\n  push:\n    branches: [ master ]\n\njobs:\n  format:\n    runs-on: ubuntu-latest\n    steps:\n      - u"
  },
  {
    "path": ".github/workflows/build-and-upload.yml",
    "chars": 6947,
    "preview": "# https://docs.github.com/en/actions/guides/building-and-testing-python#publishing-to-package-registries\n\n# When execute"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "chars": 917,
    "preview": "name: \"CodeQL\"\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    branches: [ \"master\" ]\n  schedule:\n    - cron"
  },
  {
    "path": ".github/workflows/run-linters.yml",
    "chars": 1781,
    "preview": "name: linters\n\non:\n  push:\n    branches: [ master ]\n\n  pull_request:\n    branches: [ master ]\n\n  workflow_dispatch:\n\n\njo"
  },
  {
    "path": ".github/workflows/test-smoketests.yml",
    "chars": 3329,
    "preview": "name: smoketests\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  workflow_dispatch: # m"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 1971,
    "preview": "name: tests\n\non:\n  push:\n    branches: [ master ]\n\n  pull_request:\n    branches: [ master ]\n\n  workflow_dispatch:\n\n\njobs"
  },
  {
    "path": ".gitignore",
    "chars": 2477,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 1033,
    "preview": "# Read the Docs configuration file for Sphinx projects\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html f"
  },
  {
    "path": ".vscode/c_cpp_properties.json",
    "chars": 735,
    "preview": "{\n    \"configurations\": [\n        {\n            \"name\": \"Mac\",\n            \"includePath\": [\n                \"${workspace"
  },
  {
    "path": "CITATION.cff",
    "chars": 1097,
    "preview": "cff-version: 1.0.0\nmessage: \"If you use or refer to Scalene, please cite it as below.\"\nauthors:\n- family-names: \"Berger\""
  },
  {
    "path": "CLAUDE.md",
    "chars": 23404,
    "preview": "# Scalene Development Guide\n\n## Project Overview\n\nScalene is a high-performance CPU, GPU, and memory profiler for Python"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 8231,
    "preview": "cmake_minimum_required(VERSION 3.15)\nproject(scalene VERSION 1.0 LANGUAGES C CXX)\n\nset(CMAKE_CXX_STANDARD 20)\nset(CMAKE_"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3354,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "GNUmakefile",
    "chars": 3152,
    "preview": "LIBNAME = scalene\nPYTHON = python3\nPYTHON_SOURCES = scalene/[a-z]*.py\nJS_SOURCES = scalene/scalene-gui/*.js\nC_SOURCES = "
  },
  {
    "path": "LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "MANIFEST.in",
    "chars": 122,
    "preview": "graft vendor/Heap-Layers\nprune vendor/Heap-Layers/.git\ngraft vendor/printf\nprune vendor/printf/.git\nexclude scalene/old/"
  },
  {
    "path": "Makefile",
    "chars": 1409,
    "preview": "LIBNAME = scalene\nPYTHON = python3\nPYTHON_SOURCES = scalene/[a-z]*.py\nC_SOURCES = src/source/get_line_atomic.cpp src/inc"
  },
  {
    "path": "Pipfile",
    "chars": 213,
    "preview": "[[source]]\nname = \"pypi\"\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\n\n[dev-packages]\nnumpy = \"*\"\npyperf = \"*\"\npyte"
  },
  {
    "path": "README.md",
    "chars": 25561,
    "preview": "![scalene](https://github.com/plasma-umass/scalene/raw/master/docs/scalene-icon-white.png)\n\n# Scalene: a Python CPU+GPU+"
  },
  {
    "path": "Scalene-Agents.md",
    "chars": 3156,
    "preview": "# Scalene Profiling Guide\n\n## Basic Usage\n\n```bash\npython3 -m scalene --cli --json --outfile profile.json script.py\n```\n"
  },
  {
    "path": "Scalene-Debugging.md",
    "chars": 2393,
    "preview": "# Debugging Patterns for Scalene\n\n## Signal Handler Debugging\n\nThe CPU signal handler (`cpu_signal_handler`) receives `t"
  },
  {
    "path": "Scalene-GUI.md",
    "chars": 2606,
    "preview": "# GUI Development Patterns\n\n## Adding a New Column\n\n1. **`gui-elements.ts`**: Add chart function (e.g., `makeAwaitPie`) "
  },
  {
    "path": "agents/windows-memory-profiling-port.md",
    "chars": 20387,
    "preview": "# Windows Memory Profiling Port - Progress and Plans\n\n## Overview\n\nPorting Scalene's memory profiling from Linux/macOS t"
  },
  {
    "path": "benchmarks/bench_torch_memory.py",
    "chars": 1907,
    "preview": "\"\"\"Torch-heavy workload that exposes profiler memory explosion (#991).\n\nRun under Scalene to observe memory behaviour:\n\n"
  },
  {
    "path": "benchmarks/benchmark.py",
    "chars": 8296,
    "preview": "import os\nimport sys\nimport re\nimport subprocess\nimport traceback\nimport statistics\n\npython = \"python3\"\nprogname = os.pa"
  },
  {
    "path": "benchmarks/julia1_nopil.py",
    "chars": 2802,
    "preview": "import sys\n\n# Disable the @profile decorator if none has been declared.\n\ntry:\n    # Python 2\n    import __builtin__ as b"
  },
  {
    "path": "benchmarks/measure_profiler_memory.py",
    "chars": 7128,
    "preview": "\"\"\"Measure Scalene's peak RSS while profiling a torch-heavy workload.\n\nUsage\n-----\n    # On the current branch (should b"
  },
  {
    "path": "benchmarks/new_benchmark.py",
    "chars": 4781,
    "preview": "import json\nimport subprocess\nimport re\nimport statistics\nfrom glob import glob\nfrom collections import defaultdict\nimpo"
  },
  {
    "path": "benchmarks/pystone.py",
    "chars": 7457,
    "preview": "#! /usr/bin/env python3\n\n\"\"\"\n\"PYSTONE\" Benchmark Program\n\nVersion:        Python/1.1 (corresponds to C/1.1 plus 2 Pyston"
  },
  {
    "path": "demo_torch_jit.py",
    "chars": 980,
    "preview": "\"\"\"Test script to verify PyTorch JIT profiling works with Scalene.\"\"\"\n\nimport torch\n\n@torch.jit.script\ndef compute_inten"
  },
  {
    "path": "docs/scalene-demo.ipynb",
    "chars": 26305,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"id\": \"verbal-arrival\",\n   \"metadata\": {},\n   \"out"
  },
  {
    "path": "index.rst",
    "chars": 25173,
    "preview": ".. figure::\n   https://github.com/plasma-umass/scalene/raw/master/docs/scalene-icon-white.png\n   :alt: scalene\n\n   scale"
  },
  {
    "path": "mypy.ini",
    "chars": 1093,
    "preview": "[mypy]\nscripts_are_modules = True\nshow_traceback = True\nplugins = pydantic.mypy\n\n# Options to make the checking stricter"
  },
  {
    "path": "pyproject.toml",
    "chars": 2819,
    "preview": "[project]\nname = \"scalene\"\ndescription = \"Scalene: A high-resolution, low-overhead CPU, GPU, and memory profiler for Pyt"
  },
  {
    "path": "pyrightconfig.json",
    "chars": 149,
    "preview": "{\n    \"include\": [\"scalene\"],\n    \"useLibraryCodeForTypes\": true,\n    \"reportInvalidStringEscapeSequence\": false,\n    \"t"
  },
  {
    "path": "pytest.ini",
    "chars": 38,
    "preview": "[tool:pytest]\nnorecursedirs = tests/*\n"
  },
  {
    "path": "refactoring_todo.md",
    "chars": 2038,
    "preview": "# Scalene Profiler Refactoring Plan\n\n## Goal\nRefactor `scalene/scalene_profiler.py` into multiple files with clear separ"
  },
  {
    "path": "requirements.txt",
    "chars": 475,
    "preview": "astunparse>=1.6.3; python_version < '3.9'\ncloudpickle>=2.2.1\nCython>=0.29.28\nipython>=8.10\nJinja2>=3.0.3\nlxml>=5.1.0\npac"
  },
  {
    "path": "ruff.toml",
    "chars": 226,
    "preview": "line-length = 88\nindent-width = 4\nexclude = [\"test\", \"tests\", \"node_modules\", \"benchmarks\"]\n\n[lint]\nselect = [\"E\", \"F\", "
  },
  {
    "path": "scalene/README.md",
    "chars": 2536,
    "preview": "### Helper functions:\n\n* `adaptive.py`:\n  `Adaptive` maintains samples used for memory footprint sparklines.\n  \n* `profi"
  },
  {
    "path": "scalene/__init__.py",
    "chars": 171,
    "preview": "# Work around this bug: https://github.com/NVIDIA/cuda-python/issues/29\nimport os\n\nos.environ[\"LC_ALL\"] = \"POSIX\"\n\n# Jup"
  },
  {
    "path": "scalene/__main__.py",
    "chars": 383,
    "preview": "import sys\nimport traceback\n\n\ndef main() -> None:\n    try:\n        from scalene import scalene_profiler\n\n        scalene"
  },
  {
    "path": "scalene/adaptive.py",
    "chars": 1573,
    "preview": "from typing import List\n\n\nclass Adaptive:\n    \"\"\"Implements sampling to achieve the effect of a uniform random sample.\"\""
  },
  {
    "path": "scalene/find_browser.py",
    "chars": 1236,
    "preview": "import webbrowser\nfrom typing import Optional\n\n\ndef find_browser(browserClass: Optional[str] = None) -> Optional[str]:\n "
  },
  {
    "path": "scalene/get_module_details.py",
    "chars": 3360,
    "preview": "import importlib.util\nimport sys\nfrom importlib.abc import SourceLoader\nfrom importlib.machinery import ModuleSpec\nfrom "
  },
  {
    "path": "scalene/launchbrowser.py",
    "chars": 5515,
    "preview": "import http.server\nimport os\nimport pathlib\nimport platform\nimport shutil\nimport socket\nimport socketserver\nimport sys\ni"
  },
  {
    "path": "scalene/merge_scalene_neuron_profiles.py",
    "chars": 14789,
    "preview": "#!/usr/bin/env python3\nimport bisect\nimport json\nimport sys\nfrom pathlib import Path\nfrom typing import List, Optional, "
  },
  {
    "path": "scalene/profile.py",
    "chars": 1071,
    "preview": "import argparse\nimport sys\nfrom textwrap import dedent\n\nusage = dedent(\"\"\"Turn Scalene profiling on or off for a specifi"
  },
  {
    "path": "scalene/redirect_python.py",
    "chars": 2018,
    "preview": "import os\nimport pathlib\nimport stat\nimport sys\n\n\ndef redirect_python(preface: str, cmdline: str, python_alias_dir: path"
  },
  {
    "path": "scalene/replacement_asyncio.py",
    "chars": 1053,
    "preview": "\"\"\"Scalene replacement for asyncio event loop instrumentation.\n\nFollows the existing replacement_*.py pattern using @Sca"
  },
  {
    "path": "scalene/replacement_exec.py",
    "chars": 7862,
    "preview": "\"\"\"Replacement for exec/eval/compile to track dynamically executed code.\n\nThis module intercepts exec(), eval(), and com"
  },
  {
    "path": "scalene/replacement_exit.py",
    "chars": 434,
    "preview": "import os\nimport sys\n\nfrom scalene.scalene_profiler import Scalene\n\n\n@Scalene.shim\ndef replacement_exit(scalene: Scalene"
  },
  {
    "path": "scalene/replacement_fork.py",
    "chars": 578,
    "preview": "import os\n\nfrom scalene.scalene_profiler import Scalene\n\n\n@Scalene.shim\ndef replacement_fork(scalene: Scalene) -> None:\n"
  },
  {
    "path": "scalene/replacement_get_context.py",
    "chars": 445,
    "preview": "import multiprocessing\nfrom typing import Any\n\nfrom scalene.scalene_profiler import Scalene\n\n\n@Scalene.shim\ndef replacem"
  },
  {
    "path": "scalene/replacement_lock.py",
    "chars": 2117,
    "preview": "import contextlib\nimport sys\nimport threading\nimport time\nfrom typing import Any\n\nfrom scalene.scalene_profiler import S"
  },
  {
    "path": "scalene/replacement_mp_lock.py",
    "chars": 641,
    "preview": "import multiprocessing.synchronize\n\n# import _multiprocessing\n# The _multiprocessing module is entirely undocumented-- t"
  },
  {
    "path": "scalene/replacement_pjoin.py",
    "chars": 1906,
    "preview": "import multiprocessing\nimport os\nimport sys\nimport threading\nimport time\n\nfrom scalene.scalene_profiler import Scalene\n\n"
  },
  {
    "path": "scalene/replacement_poll_selector.py",
    "chars": 1386,
    "preview": "import selectors\nimport sys\nimport threading\nimport time\nfrom typing import List, Optional, Tuple\n\nfrom scalene.scalene_"
  },
  {
    "path": "scalene/replacement_sem_lock.py",
    "chars": 2128,
    "preview": "import multiprocessing.context\nimport multiprocessing.synchronize\nimport random\nimport sys\nimport threading\nfrom typing "
  },
  {
    "path": "scalene/replacement_signal_fns.py",
    "chars": 9517,
    "preview": "import os\nimport signal\nimport sys\nfrom typing import Any, Dict, Optional, Set, Tuple\n\nfrom scalene.scalene_profiler imp"
  },
  {
    "path": "scalene/replacement_thread_join.py",
    "chars": 1066,
    "preview": "import sys\nimport threading\nimport time\nfrom typing import Optional\n\nfrom scalene.scalene_profiler import Scalene\n\n\n@Sca"
  },
  {
    "path": "scalene/runningstats.py",
    "chars": 1529,
    "preview": "# Simplified running statistics - only computes mean and peak\n# (variance/skewness/kurtosis removed as they were unused)"
  },
  {
    "path": "scalene/scalene-gui/README.md",
    "chars": 1008,
    "preview": "This repository holds the [Scalene](https://github.com/plasma-umass/scalene) GUI.\n\n[![Scalene web GUI](https://raw.githu"
  },
  {
    "path": "scalene/scalene-gui/TODO-TypeScript.md",
    "chars": 3845,
    "preview": "# TypeScript Conversion Plan for Scalene GUI\n\n## Overview\n\nConverting the Scalene GUI JavaScript files to TypeScript for"
  },
  {
    "path": "scalene/scalene-gui/amazon.ts",
    "chars": 3153,
    "preview": "import {\n  BedrockRuntimeClient,\n  InvokeModelCommand,\n} from \"@aws-sdk/client-bedrock-runtime\";\n\ninterface AnthropicRes"
  },
  {
    "path": "scalene/scalene-gui/anthropic.ts",
    "chars": 2738,
    "preview": "interface AnthropicErrorResponse {\n  error?: {\n    type?: string;\n    message?: string;\n  };\n}\n\ninterface AnthropicConte"
  },
  {
    "path": "scalene/scalene-gui/azure.ts",
    "chars": 2178,
    "preview": "interface AzureOpenAIChoice {\n  message: {\n    content: string;\n  };\n}\n\ninterface AzureOpenAIResponse {\n  error?: {\n    "
  },
  {
    "path": "scalene/scalene-gui/example-profile.js",
    "chars": 346707,
    "preview": "const example_profile = {\n  elapsed_time_sec: 12.696948051452637,\n  memory: true,\n  files: {\n    \"./test/testme.py\": {\n "
  },
  {
    "path": "scalene/scalene-gui/gemini.ts",
    "chars": 4751,
    "preview": "interface GeminiErrorResponse {\n  error?: {\n    code?: number;\n    message?: string;\n    status?: string;\n  };\n}\n\ninterf"
  },
  {
    "path": "scalene/scalene-gui/gui-elements.ts",
    "chars": 21891,
    "preview": "import { memory_consumed_str, time_consumed_str } from \"./utils\";\n\nexport const Lightning = \"&#9889;\"; // lightning bolt"
  },
  {
    "path": "scalene/scalene-gui/index.html",
    "chars": 5913,
    "preview": "<html>\n  <head>\n    <title>Scalene</title>\n    <link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n    <!-- Latest "
  },
  {
    "path": "scalene/scalene-gui/index.html.template",
    "chars": 22846,
    "preview": "{# index.html.template #}\n<!DOCTYPE html>\n<html>\n  <head>\n<!--    <meta http-equiv=\"Content-Security-Policy\" content=\"sc"
  },
  {
    "path": "scalene/scalene-gui/list-amazon-models.py",
    "chars": 247,
    "preview": "import boto3\n\nclient = boto3.client(\"bedrock\")\nresponse = client.list_foundation_models()\nfor model_summary in response["
  },
  {
    "path": "scalene/scalene-gui/ollama.ts",
    "chars": 2747,
    "preview": "interface OllamaModel {\n  name: string;\n}\n\ninterface OllamaTagsResponse {\n  models: OllamaModel[];\n}\n\ninterface OllamaMe"
  },
  {
    "path": "scalene/scalene-gui/openai.ts",
    "chars": 6564,
    "preview": "interface OpenAIErrorResponse {\n  error?: {\n    code?: string;\n    message?: string;\n  };\n}\n\ninterface OpenAIChoice {\n  "
  },
  {
    "path": "scalene/scalene-gui/optimizations.ts",
    "chars": 19894,
    "preview": "import { sendPromptToOpenAI, isValidApiKey } from \"./openai\";\nimport { sendPromptToAnthropic } from \"./anthropic\";\nimpor"
  },
  {
    "path": "scalene/scalene-gui/package.json",
    "chars": 1108,
    "preview": "{\n  \"dependencies\": {\n    \"@aws-sdk/client-bedrock\": \"^3.687.0\",\n    \"buffer\": \"^6.0.3\",\n    \"@aws-sdk/client-bedrock-ru"
  },
  {
    "path": "scalene/scalene-gui/persistence.ts",
    "chars": 2786,
    "preview": "// Declare envApiKeys as a global variable that may be injected by the template\ndeclare const envApiKeys: {\n  openai?: s"
  },
  {
    "path": "scalene/scalene-gui/prism.css",
    "chars": 2478,
    "preview": "/* PrismJS 1.26.0\nhttps://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+python&plugins=no"
  },
  {
    "path": "scalene/scalene-gui/prism.d.ts",
    "chars": 226,
    "preview": "// Type declarations for prism.js\nexport const Prism: {\n  highlight: (code: string, grammar: unknown, language: string) "
  },
  {
    "path": "scalene/scalene-gui/prism.js",
    "chars": 64673,
    "preview": "/* PrismJS 1.26.0\nhttps://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+python&plugins=no"
  },
  {
    "path": "scalene/scalene-gui/profile.json",
    "chars": 68005,
    "preview": "{\n    \"alloc_samples\": 52,\n    \"args\": [\n        \"/Users/emerydb/git/scalene/test/testme.py\"\n    ],\n    \"elapsed_time_se"
  },
  {
    "path": "scalene/scalene-gui/profiler.html",
    "chars": 2300,
    "preview": "<html>\n  <head>\n    <title>Scalene</title>\n    <link rel=\"icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n    <!-- Latest "
  },
  {
    "path": "scalene/scalene-gui/scalene-demo.ts",
    "chars": 208,
    "preview": "declare function loadDemo(): void;\n\nconst demoText = document.getElementById(\"demo-text\");\nif (demoText) {\n  demoText.ad"
  },
  {
    "path": "scalene/scalene-gui/scalene-fetch.ts",
    "chars": 50,
    "preview": "declare function loadFetch(): void;\n\nloadFetch();\n"
  },
  {
    "path": "scalene/scalene-gui/scalene-gui-bundle.js",
    "chars": 2520659,
    "preview": "var ScaleneGUI = (() => {\n  var __create = Object.create;\n  var __defProp = Object.defineProperty;\n  var __getOwnPropDes"
  },
  {
    "path": "scalene/scalene-gui/scalene-gui.ts",
    "chars": 54779,
    "preview": "import { Buffer } from \"buffer\";\n(window as unknown as { Buffer: typeof Buffer }).Buffer = Buffer;\nimport vegaEmbed from"
  },
  {
    "path": "scalene/scalene-gui/tablesort.d.ts",
    "chars": 195,
    "preview": "// Type declarations for tablesort.js\ndeclare class Tablesort {\n  constructor(el: Element, options?: { ascending?: boole"
  },
  {
    "path": "scalene/scalene-gui/tablesort.js",
    "chars": 5530,
    "preview": "// tablesort.js\n\n// Utility functions\nconst createEvent = (name) => {\n  let evt;\n  if (!window.CustomEvent || typeof win"
  },
  {
    "path": "scalene/scalene-gui/tsconfig.json",
    "chars": 619,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"lib\": ["
  },
  {
    "path": "scalene/scalene-gui/utils.ts",
    "chars": 1633,
    "preview": "export function unescapeUnicode(s: string): string {\n  return s.replace(/\\\\u([\\dA-F]{4})/gi, function (_match, p1: strin"
  },
  {
    "path": "scalene/scalene-usage.txt",
    "chars": 3058,
    "preview": "Scalene: a high-precision CPU and memory profiler\nhttps://github.com/plasma-umass/scalene\n\nUsage:\n  scalene run [options"
  },
  {
    "path": "scalene/scalene_accelerator.py",
    "chars": 491,
    "preview": "from abc import ABC, abstractmethod\nfrom typing import Tuple\n\n\n# Base class for accelerators (GPUs, TPUs, etc.)\nclass Sc"
  },
  {
    "path": "scalene/scalene_analysis.py",
    "chars": 10460,
    "preview": "import ast\nimport contextlib\nimport importlib\nimport os\nimport re\nimport sys\nfrom typing import Any, Dict, List, Tuple, "
  },
  {
    "path": "scalene/scalene_apple_gpu.py",
    "chars": 9172,
    "preview": "import ctypes\nimport platform\nfrom typing import Tuple\n\nfrom scalene.scalene_accelerator import ScaleneAccelerator\n\n# --"
  },
  {
    "path": "scalene/scalene_arguments.py",
    "chars": 3444,
    "preview": "import argparse\nimport platform\nimport sys\nfrom typing import Any, Optional, TypedDict\n\nfrom typing_extensions import Un"
  },
  {
    "path": "scalene/scalene_async.py",
    "chars": 10687,
    "preview": "\"\"\"Scalene async profiling support.\n\nTracks suspended coroutines and provides await-time attribution.\nWhen enabled (via "
  },
  {
    "path": "scalene/scalene_client_timer.py",
    "chars": 1909,
    "preview": "from typing import Tuple\n\n\nclass ScaleneClientTimer:\n    \"\"\"\n    A class to wrap the logic of a timer running at\n    a d"
  },
  {
    "path": "scalene/scalene_config.py",
    "chars": 703,
    "preview": "\"\"\"Current version of Scalene; reported by --version.\"\"\"\n\nscalene_version = \"2.2.0\"\nscalene_date = \"2026.02.17\"\n\n# Port "
  },
  {
    "path": "scalene/scalene_cpu_profiler.py",
    "chars": 14289,
    "preview": "\"\"\"CPU profiling logic for Scalene.\"\"\"\n\nfrom __future__ import annotations\n\nimport math\nfrom typing import TYPE_CHECKING"
  },
  {
    "path": "scalene/scalene_funcutils.py",
    "chars": 6143,
    "preview": "import dis\nimport sys\nfrom functools import lru_cache\nfrom types import CodeType\nfrom typing import FrozenSet, List, Opt"
  },
  {
    "path": "scalene/scalene_jax.py",
    "chars": 3062,
    "preview": "\"\"\"JAX profiler integration for Scalene.\n\nThis module wraps jax.profiler to capture JAX operation timing and\nattribute i"
  },
  {
    "path": "scalene/scalene_json.py",
    "chars": 31065,
    "preview": "import copy\nimport linecache\nimport math\nimport random\nimport re\nfrom collections import defaultdict\nfrom enum import En"
  },
  {
    "path": "scalene/scalene_jupyter.py",
    "chars": 4215,
    "preview": "import socket\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\nfrom threading import Thread\nfrom typing import"
  },
  {
    "path": "scalene/scalene_leak_analysis.py",
    "chars": 1671,
    "preview": "from typing import Dict, List, Tuple\n\nfrom scalene.scalene_statistics import Filename, LineNumber, ScaleneStatistics\n\n\nc"
  },
  {
    "path": "scalene/scalene_library_profiler.py",
    "chars": 11148,
    "preview": "\"\"\"Abstract base class for library-specific profilers.\n\nThis module provides a common interface for integrating profilin"
  },
  {
    "path": "scalene/scalene_library_registry.py",
    "chars": 3578,
    "preview": "\"\"\"Registry for managing multiple library profilers.\n\nThis module is separate from scalene_library_profiler to avoid cyc"
  },
  {
    "path": "scalene/scalene_lifecycle.py",
    "chars": 6525,
    "preview": "\"\"\"Profiler lifecycle management for Scalene.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport os\nimport"
  },
  {
    "path": "scalene/scalene_magics.py",
    "chars": 4696,
    "preview": "import contextlib\nimport sys\nimport textwrap\nfrom typing import TYPE_CHECKING, Any, Callable, TypeVar\n\nF = TypeVar(\"F\", "
  },
  {
    "path": "scalene/scalene_mapfile.py",
    "chars": 10300,
    "preview": "import mmap\nimport os\nimport sys\nfrom typing import Any, NewType, Optional, TextIO\n\nif sys.platform != \"win32\":\n    from"
  },
  {
    "path": "scalene/scalene_memory_profiler.py",
    "chars": 12803,
    "preview": "\"\"\"\nMemory profiling processor for Scalene profiler.\n\nThis module extracts memory profiling functionality from the main "
  },
  {
    "path": "scalene/scalene_neuron.py",
    "chars": 7288,
    "preview": "import json\nimport os\nimport subprocess\nimport tempfile\nimport threading\nimport time\nfrom functools import lru_cache\nfro"
  },
  {
    "path": "scalene/scalene_nvidia_gpu.py",
    "chars": 5695,
    "preview": "import contextlib\nimport os\nimport sys\nfrom typing import Tuple\n\nimport pynvml\n\nfrom scalene.scalene_accelerator import "
  },
  {
    "path": "scalene/scalene_output.py",
    "chars": 27081,
    "preview": "import linecache\nimport os\nimport random\nimport sys\nimport tempfile\nfrom collections import OrderedDict, defaultdict\nfro"
  },
  {
    "path": "scalene/scalene_parseargs.py",
    "chars": 47192,
    "preview": "import argparse\nimport contextlib\nimport os\nimport re\nimport sys\nfrom textwrap import dedent\nfrom typing import Any, Dic"
  },
  {
    "path": "scalene/scalene_preload.py",
    "chars": 6588,
    "preview": "import argparse\nimport contextlib\nimport os\nimport platform\nimport signal\nimport struct\nimport subprocess\nimport sys\nimp"
  },
  {
    "path": "scalene/scalene_profiler.py",
    "chars": 78363,
    "preview": "# ruff: noqa: E402\n\nfrom __future__ import (\n    annotations,\n)\n\n\"\"\"Scalene: a CPU+memory+GPU (and more) profiler for Py"
  },
  {
    "path": "scalene/scalene_signal_manager.py",
    "chars": 16644,
    "preview": "\"\"\"\nSignal handling manager for Scalene profiler.\n\nThis module extracts signal handling functionality from the main Scal"
  },
  {
    "path": "scalene/scalene_signals.py",
    "chars": 3192,
    "preview": "# Import the necessary libraries.\nimport signal\nimport sys\nfrom types import FrameType\nfrom typing import Callable, List"
  },
  {
    "path": "scalene/scalene_sigqueue.py",
    "chars": 1557,
    "preview": "import queue\nimport threading\nfrom typing import Any, Generic, Optional, TypeVar\n\nT = TypeVar(\"T\")\n\n\nclass ScaleneSigQue"
  },
  {
    "path": "scalene/scalene_statistics.py",
    "chars": 33667,
    "preview": "from __future__ import annotations\n\nimport os\nimport pathlib\nimport pickle\nimport time\nfrom collections import defaultdi"
  },
  {
    "path": "scalene/scalene_tensorflow.py",
    "chars": 5035,
    "preview": "\"\"\"TensorFlow profiler integration for Scalene.\n\nThis module wraps tf.profiler.experimental to capture TensorFlow operat"
  },
  {
    "path": "scalene/scalene_torch.py",
    "chars": 10345,
    "preview": "\"\"\"PyTorch profiler integration for Scalene.\n\nThis module wraps torch.profiler to capture PyTorch operation timing and\na"
  },
  {
    "path": "scalene/scalene_tracer.py",
    "chars": 14260,
    "preview": "\"\"\"Line tracer for Scalene's memory profiling.\n\nThis module provides a unified interface for enabling/disabling line tra"
  },
  {
    "path": "scalene/scalene_tracing.py",
    "chars": 9956,
    "preview": "\"\"\"Tracing and filtering logic for Scalene profiler.\"\"\"\n\nfrom __future__ import annotations\n\nimport functools\nimport os\n"
  },
  {
    "path": "scalene/scalene_utility.py",
    "chars": 15636,
    "preview": "import functools\nimport os\nimport pathlib\nimport shutil\nimport signal\nimport socketserver\nimport subprocess\nimport sys\ni"
  },
  {
    "path": "scalene/scalene_windows.py",
    "chars": 10414,
    "preview": "\"\"\"\nWindows-specific functionality for Scalene memory profiling.\n\nOn Windows, we can't use LD_PRELOAD or DYLD_INSERT_LIB"
  },
  {
    "path": "scalene/set_nvidia_gpu_modes.py",
    "chars": 1374,
    "preview": "import os\nimport subprocess\nimport sys\n\n\ndef set_nvidia_gpu_modes() -> bool:\n    import pynvml\n\n    try:\n        # Initi"
  },
  {
    "path": "scalene/sorted_reservoir.py",
    "chars": 2635,
    "preview": "import math\nimport random\nimport sys\nfrom typing import Any, Callable, List, Union\n\nif sys.version_info >= (3, 11):\n    "
  },
  {
    "path": "scalene/sparkline.py",
    "chars": 2146,
    "preview": "import os\nfrom typing import List, Optional, Tuple\n\n\"\"\"Produces a sparkline, as in ▁▁▁▁▁▂▃▂▄▅▄▆█▆█▆\n\nFrom https://rosett"
  },
  {
    "path": "scalene/syntaxline.py",
    "chars": 336,
    "preview": "from typing import Any, Iterator, List\n\nfrom rich.console import Console\nfrom rich.segment import Segment\n\n\nclass Syntax"
  },
  {
    "path": "scalene/time_info.py",
    "chars": 1434,
    "preview": "import os\nimport sys\nfrom dataclasses import dataclass\nfrom typing import Tuple\n\n\n@dataclass\nclass TimeInfo:\n    virtual"
  },
  {
    "path": "setup.py",
    "chars": 19216,
    "preview": "import sys\nimport sysconfig\nfrom os import environ, path\nfrom pathlib import Path\n\nfrom setuptools import find_packages,"
  },
  {
    "path": "src/include/common.hpp",
    "chars": 823,
    "preview": "#pragma once\n\n#ifndef COMMON_HPP\n#define COMMON_HPP\n\n#if defined(_WIN32)\n// Use Windows-specific definitions\n#include \"c"
  },
  {
    "path": "src/include/common_win.hpp",
    "chars": 1466,
    "preview": "#pragma once\n\n#ifndef COMMON_WIN_HPP\n#define COMMON_WIN_HPP\n\n#if defined(_WIN32)\n\n// Windows-specific definitions for Sc"
  },
  {
    "path": "src/include/lowdiscrepancy.hpp",
    "chars": 1241,
    "preview": "#pragma once\n\n#include <unistd.h>\n\n#include <chrono>\n#include <cmath>\n#include <iostream>\n#include <random>\n#include <th"
  },
  {
    "path": "src/include/mallocrecursionguard.hpp",
    "chars": 2478,
    "preview": "#pragma once\n#ifndef MALLOCRECURSIONGUARD_H\n#define MALLOCRECURSIONGUARD_H\n\n#if defined(_WIN32)\n// Use Windows-specific "
  },
  {
    "path": "src/include/mallocrecursionguard_win.hpp",
    "chars": 2467,
    "preview": "#pragma once\n#ifndef MALLOCRECURSIONGUARD_WIN_H\n#define MALLOCRECURSIONGUARD_WIN_H\n\n#if defined(_WIN32)\n\n#ifndef WIN32_L"
  },
  {
    "path": "src/include/memcpysampler.hpp",
    "chars": 8700,
    "preview": "#pragma once\n#ifndef MEMCPYSAMPLER_HPP\n#define MEMCPYSAMPLER_HPP\n\n#include <fcntl.h>\n#include <stdint.h>\n#include <strin"
  },
  {
    "path": "src/include/poissonsampler.hpp",
    "chars": 2684,
    "preview": "#pragma once\n#include <random>\n#include <unordered_map>\n\n/**\n * @brief \"triggers\" samples using a geometric distribution"
  },
  {
    "path": "src/include/pyptr.h",
    "chars": 890,
    "preview": "#ifndef PYPTR_H\n#define PYPTR_H\n\n#pragma once\n\n#include <Python.h>\n\n// Implements a mini smart pointer to PyObject.\n// M"
  },
  {
    "path": "src/include/pywhere.hpp",
    "chars": 1678,
    "preview": "#ifndef __PYWHERE_H\n#define __PYWHERE_H\n\n#include <atomic>\n#include <string>\n\n// On Windows, we need dllexport/dllimport"
  },
  {
    "path": "src/include/samplefile.hpp",
    "chars": 5349,
    "preview": "#pragma once\n#ifndef SAMPLEFILE_H\n#define SAMPLEFILE_H\n\n#if defined(_WIN32)\n// Use Windows-specific implementation\n#incl"
  },
  {
    "path": "src/include/samplefile_win.hpp",
    "chars": 5958,
    "preview": "#pragma once\n#ifndef SAMPLEFILE_WIN_H\n#define SAMPLEFILE_WIN_H\n\n#if defined(_WIN32)\n\n#ifndef WIN32_LEAN_AND_MEAN\n#define"
  },
  {
    "path": "src/include/sampleheap.hpp",
    "chars": 11303,
    "preview": "#pragma once\n\n#ifndef SAMPLEHEAP_H\n#define SAMPLEHEAP_H\n\n#if defined(_WIN32)\n// Use Windows-specific implementation\n#inc"
  },
  {
    "path": "src/include/sampleheap_win.hpp",
    "chars": 8235,
    "preview": "#pragma once\n\n#ifndef SAMPLEHEAP_WIN_H\n#define SAMPLEHEAP_WIN_H\n\n#if defined(_WIN32)\n\n#ifndef WIN32_LEAN_AND_MEAN\n#defin"
  },
  {
    "path": "src/include/sampler.hpp",
    "chars": 2139,
    "preview": "#pragma once\n\n#if defined(_WIN32)\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <windows.h>\n#i"
  },
  {
    "path": "src/include/scaleneheader.hpp",
    "chars": 2201,
    "preview": "#ifndef SCALENE_HEADER_H\n#define SCALENE_HEADER_H\n\n#include <stddef.h>\n#if defined(__SVR4)\nextern \"C\" size_t malloc_usab"
  },
  {
    "path": "src/include/thresholdsampler.hpp",
    "chars": 2305,
    "preview": "#pragma once\n\n#if defined(_WIN32)\n#include <process.h>\n#define getpid _getpid\n#else\n#include <unistd.h>\n#endif\n\n#include"
  },
  {
    "path": "src/include/traceconfig.hpp",
    "chars": 4689,
    "preview": "#pragma once\n\n#ifndef __TRACECONFIG_H\n#define __TRACECONFIG_H\n\n#include <Python.h>\n\n#if defined(_WIN32)\n#ifndef WIN32_LE"
  },
  {
    "path": "src/source/get_line_atomic.cpp",
    "chars": 2610,
    "preview": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n#include <heaplayers.h>\n#include <string.h>\n\n#include <mutex>\n\n// This uses"
  },
  {
    "path": "src/source/libscalene.cpp",
    "chars": 7928,
    "preview": "#define SCALENE_DISABLE_SIGNALS 0  // for debugging only\n\n#if !defined(_WIN32)\n#include <unistd.h>\n#endif\n\n// Include C+"
  },
  {
    "path": "src/source/libscalene_windows.cpp",
    "chars": 31534,
    "preview": "/**\n * @file libscalene_windows.cpp\n * @brief Windows-specific memory tracking for Scalene profiler\n *\n * This file impl"
  },
  {
    "path": "src/source/pywhere.cpp",
    "chars": 33898,
    "preview": "#include \"pywhere.hpp\"\n\n#include <Python.h>\n#include <frameobject.h>\n\n#if defined(_WIN32)\n#ifndef WIN32_LEAN_AND_MEAN\n#d"
  },
  {
    "path": "src/source/traceconfig.cpp",
    "chars": 170,
    "preview": "#include \"traceconfig.hpp\"\n\nTraceConfig* TraceConfig::_instance = 0;\nstd::mutex TraceConfig::_instanceMutex;\nstd::unorde"
  },
  {
    "path": "test/automatic/README.md",
    "chars": 105,
    "preview": "This directory contains examples of code before and after\nincorporating Scalene's proposed optimizations."
  },
  {
    "path": "test/automatic/dataframe/README.md",
    "chars": 271,
    "preview": "See discussion here:\nhttps://github.com/plasma-umass/scalene/issues/554#issuecomment-1401355354\n\nOriginal code is in `da"
  },
  {
    "path": "test/automatic/dataframe/dataframe-select-optimized.py",
    "chars": 936,
    "preview": "import pandas as pd\nimport numpy as np\nimport timeit\n\nnp.random.seed(1)\n\ncolumn_names_example = [i for i in range(10000)"
  },
  {
    "path": "test/automatic/dataframe/dataframe-select-original.py",
    "chars": 594,
    "preview": "import pandas as pd\nimport numpy as np\nimport timeit\n\nnp.random.seed(1)\n\ncolumn_names_example = [i for i in range(10000)"
  },
  {
    "path": "test/automatic/svm/README.md",
    "chars": 247,
    "preview": "See discussion here:\nhttps://github.com/plasma-umass/scalene/issues/554#issuecomment-1400730365.\n\nOriginal code is in `s"
  },
  {
    "path": "test/automatic/svm/svm-optimized.py",
    "chars": 5876,
    "preview": "import math\nimport pickle\nimport numpy as np\nfrom numpy import linalg as LA\n\nnp.random.seed(1)\n\n\nclass SVM:\n    \"\"\"SVC w"
  },
  {
    "path": "test/automatic/svm/svm-original.py",
    "chars": 4425,
    "preview": "import math\nimport pickle\nimport numpy as np\nfrom numpy import linalg as LA\n\nnp.random.seed(1)\n\n\nclass SVM:\n    \"\"\"SVC w"
  },
  {
    "path": "test/expensive_benchmarks/README.md",
    "chars": 616,
    "preview": "# NOTE: bm_async_tree_io is 3 benchmarks\n\n### async_tree_io ###\nMean +- std dev: 1.44 sec +- 0.04 sec\n\n### docutils ###\n"
  },
  {
    "path": "test/expensive_benchmarks/bm_async_tree_io.py",
    "chars": 5482,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nBenchmark for async tree workload, which calls asyncio.gather() on a tree\n(6 levels deep, 6 b"
  },
  {
    "path": "test/expensive_benchmarks/bm_docutils.py",
    "chars": 1637,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nConvert Docutils' documentation from reStructuredText to <format>.\n\"\"\"\n\nimport contextlib\nfro"
  },
  {
    "path": "test/expensive_benchmarks/bm_fannukh.py",
    "chars": 1317,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\nContributed b"
  },
  {
    "path": "test/expensive_benchmarks/bm_mdp.py",
    "chars": 8852,
    "preview": "#!/usr/bin/env python3\nimport collections\nfrom collections import defaultdict\nfrom fractions import Fraction\nimport time"
  },
  {
    "path": "test/expensive_benchmarks/bm_pprint.py",
    "chars": 551,
    "preview": "#!/usr/bin/env python3\n\"\"\"Test the performance of pprint.PrettyPrinter.\n\nThis benchmark was available as `python -m ppri"
  },
  {
    "path": "test/expensive_benchmarks/bm_raytrace.py",
    "chars": 11888,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nThis file contains definitions for a simple raytracer.\nCopyright Callum and Tony Garnock-Jone"
  },
  {
    "path": "test/expensive_benchmarks/bm_sympy.py",
    "chars": 1272,
    "preview": "#!/usr/bin/env python3\nimport time\nimport pyperf\n\nfrom sympy import expand, symbols, integrate, tan, summation\nfrom symp"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/api/publisher.txt",
    "chars": 10569,
    "preview": "========================\n The Docutils Publisher\n========================\n\n:Author: David Goodger\n:Contact: docutils-dev"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/api/runtime-settings.txt",
    "chars": 6215,
    "preview": "===========================\n Docutils Runtime Settings\n===========================\n\n:Author: David Goodger, Günter Milde"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/api/transforms.txt",
    "chars": 6334,
    "preview": "=====================\n Docutils Transforms\n=====================\n\n:Author: David Goodger\n:Contact: docutils-develop@list"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/distributing.txt",
    "chars": 4530,
    "preview": "===============================\n Docutils_ Distributor's Guide\n===============================\n\n:Author: Lea Wiemann\n:Co"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/enthought-plan.txt",
    "chars": 16986,
    "preview": "===========================================\n Plan for Enthought API Documentation Tool\n================================="
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/enthought-rfp.txt",
    "chars": 4531,
    "preview": "==================================\n Enthought API Documentation Tool\n==================================\n----------------"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/hacking.txt",
    "chars": 9172,
    "preview": "==========================\n Docutils_ Hacker's Guide\n==========================\n\n:Author: Lea Wiemann\n:Contact: docutils"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/policies.txt",
    "chars": 25778,
    "preview": "===========================\n Docutils Project Policies\n===========================\n\n:Author: David Goodger; open to all "
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/pysource.txt",
    "chars": 4380,
    "preview": "======================\n Python Source Reader\n======================\n:Author: David Goodger\n:Contact: docutils-develop@li"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/release.txt",
    "chars": 3497,
    "preview": "=============================\n Docutils_ Release Procedure\n=============================\n\n:Authors: David Goodger; Lea W"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/repository.txt",
    "chars": 9439,
    "preview": "=====================================\n The Docutils_ Version Repository\n=====================================\n\n:Author: "
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/rst/alternatives.txt",
    "chars": 113255,
    "preview": "==================================================\n A Record of reStructuredText Syntax Alternatives\n==================="
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/rst/problems.txt",
    "chars": 35463,
    "preview": "==============================\n Problems With StructuredText\n==============================\n:Author: David Goodger\n:Cont"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/runtime-settings-processing.txt",
    "chars": 10643,
    "preview": "=============================\n Runtime Settings Processing\n=============================\n\n:Author: David Goodger, Günter"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/semantics.txt",
    "chars": 4511,
    "preview": "=====================\n Docstring Semantics\n=====================\n:Author: David Goodger\n:Contact: docutils-develop@lists"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/testing.txt",
    "chars": 9503,
    "preview": "===================\n Docutils_ Testing\n===================\n\n:Authors: Lea Wiemann <LeWiemann@gmail.com>;\n          David"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/todo.txt",
    "chars": 98576,
    "preview": "======================\n Docutils_ To Do List\n======================\n\n:Author: David Goodger (with input from many); open"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/dev/website.txt",
    "chars": 3274,
    "preview": "===================\n Docutils Web Site\n===================\n\n:Author: David Goodger; open to all Docutils developers\n:Con"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/howto/cmdline-tool.txt",
    "chars": 2219,
    "preview": "===============================================\n Inside A Docutils Command-Line Front-End Tool\n========================="
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/howto/html-stylesheets.txt",
    "chars": 3417,
    "preview": "==============================================\n Writing HTML (CSS) Stylesheets for Docutils_\n==========================="
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/howto/i18n.txt",
    "chars": 6869,
    "preview": "================================\n Docutils_ Internationalization\n================================\n\n:Author: David Goodge"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/howto/rst-directives.txt",
    "chars": 16349,
    "preview": "=======================================\n Creating reStructuredText_ Directives\n=======================================\n\n"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/howto/rst-roles.txt",
    "chars": 8907,
    "preview": "==================================================\n Creating reStructuredText Interpreted Text Roles\n==================="
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/howto/security.txt",
    "chars": 6972,
    "preview": "=============================\n Deploying Docutils Securely\n=============================\n\n:Author: David Goodger\n:Contac"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/index.txt",
    "chars": 8264,
    "preview": "==========================================\n Docutils Project Documentation Overview\n===================================="
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/peps/pep-0256.txt",
    "chars": 10437,
    "preview": "PEP: 256\nTitle: Docstring Processing System Framework\nVersion: $Revision$\nLast-Modified: $Date$\nAuthor: David Goodger <g"
  },
  {
    "path": "test/expensive_benchmarks/docutils_data/docs/peps/pep-0257.txt",
    "chars": 11684,
    "preview": "PEP: 257\nTitle: Docstring Conventions\nVersion: $Revision$\nLast-Modified: $Date$\nAuthors: David Goodger <goodger@python.o"
  }
]

// ... and 196 more files (download for full content)

About this extraction

This page contains the full source code of the plasma-umass/scalene GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 396 files (5.5 MB), approximately 1.5M tokens, and a symbol index with 5997 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!