Skip to content

Commit

Permalink
Merge pull request plasma-umass#68 from johanvergeer/cleanup-duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
emeryberger authored Jul 26, 2020
2 parents 26467cc + 7fd6cb7 commit e2642ad
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 147 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,5 @@ dmypy.json

# Pyre type checker
.pyre/

.idea
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include LICENSE
include scalene/libscalene.so
include scalene/libscalene.dylib
include scalene/scalene.py
include scalene/adaptive.py
include scalene/Adaptive.py
include scalene/sparkline.py
include test/testme.py

1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
pyperf = "*"
pytest = "*"

[packages]
Expand Down
170 changes: 170 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 2 additions & 12 deletions scalene/adaptive.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import math
import random
from typing import List


class adaptive:
class Adaptive:
"""Implements sampling to achieve the effect of a uniform random sample."""

sample_array: List[float] = []
current_index = 0
total_samples = 0
max_samples = 0
count_average = 0
sum_average = 0
max_average = 1

def __init__(self, size: int):
self.max_samples = size
Expand All @@ -22,19 +16,15 @@ def __init__(self, size: int):
def add(self, value: float) -> None:
if self.current_index >= self.max_samples:
# Decimate
# print("DECIMATION " + str(self.sample_array))
new_array = [0.0] * self.max_samples
for i in range(0, self.max_samples // 3):
arr = [self.sample_array[i * 3 + j] for j in range(0, 3)]
arr.sort()
new_array[i] = arr[1] # Median
self.current_index = self.max_samples // 3
self.sample_array = new_array
# print("POST DECIMATION = " + str(self.sample_array))
# Update average length
self.max_average *= 3
self.sample_array[self.current_index] = value
self.current_index += 1 # count_average += 1
self.current_index += 1

def get(self) -> List[float]:
return self.sample_array
Expand Down
98 changes: 8 additions & 90 deletions scalene/scalene.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,77 +54,9 @@
cast,
)

from scalene.adaptive import Adaptive
from scalene.sparkline import SparkLine

class adaptive:
"""Implements sampling to achieve the effect of a uniform random sample."""

sample_array: List[float] = []
current_index = 0
max_samples = 0

def __init__(self, size: int):
self.max_samples = size
# must be a power of two
self.sample_array = [0] * size

def add(self, value: float) -> None:
if self.current_index >= self.max_samples:
# Decimate
new_array = [0.0] * self.max_samples
for i in range(0, self.max_samples // 3):
arr = [self.sample_array[i * 3 + j] for j in range(0, 3)]
arr.sort()
new_array[i] = arr[1] # Median
self.current_index = self.max_samples // 3
self.sample_array = new_array
self.sample_array[self.current_index] = value
self.current_index += 1

def get(self) -> List[float]:
return self.sample_array

def len(self) -> int:
return self.current_index


# Sparkline stuff

# Check if we are in Windows Subsystem for Linux and *not* using
# the highly recommended Windows Terminal
# (https://aka.ms/windowsterminal)
if "WSL_DISTRO_NAME" in os.environ and "WT_PROFILE_ID" not in os.environ:
# We are running in the Windows Subsystem for Linux Display, a
# crappy version of the sparkline because the Windows console
# *still* only properly displays IBM Code page 437 by default.
# ▄▄■■■■▀▀
bar = chr(0x2584) * 2 + chr(0x25A0) * 3 + chr(0x2580) * 3
else:
# Reasonable system. Use Unicode characters.
# Unicode: 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608
# ▁▂▃▄▅▆▇█
bar = "".join([chr(i) for i in range(9601, 9609)])

barcount = len(bar)

# From https://rosettacode.org/wiki/Sparkline_in_unicode#Python
def sparkline(
numbers: List[float], fixed_min: float = -1, fixed_max: float = -1
) -> Tuple[float, float, str]:
if fixed_min == -1:
mn = float(min(numbers))
else:
mn = fixed_min
if fixed_max == -1:
mx = float(max(numbers))
else:
mx = fixed_max
extent = mx - mn
if extent == 0:
extent = 1
sparkstr = "".join(
bar[min([barcount - 1, int((n - mn) / extent * barcount)])] for n in numbers
)
return mn, mx, sparkstr


# Logic to ignore @profile decorators.
Expand Down Expand Up @@ -456,12 +388,12 @@ def new_subprocess_Popen(args, bufsize=-1, executable=None, stdin=None, stdout=N
# when did we last receive a signal?
__last_signal_time: float = 0

# memory footprint samples (time, footprint), using 'adaptive' sampling.
__memory_footprint_samples = adaptive(27)
# memory footprint samples (time, footprint), using 'Adaptive' sampling.
__memory_footprint_samples = Adaptive(27)

# same, but per line
__per_line_footprint_samples: Dict[str, Dict[int, adaptive]] = defaultdict(
lambda: defaultdict(lambda: adaptive(9))
__per_line_footprint_samples: Dict[str, Dict[int, Adaptive]] = defaultdict(
lambda: defaultdict(lambda: Adaptive(9))
)

# path for the program being profiled
Expand Down Expand Up @@ -1038,20 +970,6 @@ def stop() -> None:
Scalene.disable_signals()
Scalene.__elapsed_time += Scalene.gettime() - Scalene.__start_time

@staticmethod
def generate_sparkline(
arr: List[float], minimum: float = -1, maximum: float = -1
) -> Tuple[float, float, str]:
"""Produces a sparkline, as in ▁▁▁▁▁▂▃▂▄▅▄▆█▆█▆"""
iterations = len(arr)
all_zeros = all(i == 0 for i in arr)
if all_zeros:
return 0, 0, ""
# Prevent negative memory output due to sampling error.
samples = [i if i > 0 else 0 for i in arr]
minval, maxval, sp_line = sparkline(samples[0:iterations], minimum, maximum)
return minval, maxval, sp_line

@staticmethod
def output_profile_line(
fname: Filename, line_no: LineNumber, line: str, console: Console, tbl: Table,
Expand Down Expand Up @@ -1138,7 +1056,7 @@ def output_profile_line(
for i in range(0, len(samples.get())):
samples.get()[i] *= n_usage_fraction
if samples.get():
_, _, spark_str = Scalene.generate_sparkline(
_, _, spark_str = SparkLine().generate(
samples.get()[0 : samples.len()], 0, current_max
)

Expand Down Expand Up @@ -1224,7 +1142,7 @@ def output_profiles() -> bool:
samples = Scalene.__memory_footprint_samples
if len(samples.get()) > 0:
# Output a sparkline as a summary of memory usage over time.
_, _, spark_str = Scalene.generate_sparkline(
_, _, spark_str = SparkLine().generate(
samples.get()[0 : samples.len()], 0, current_max
)
mem_usage_line = Text.assemble(
Expand Down
Loading

0 comments on commit e2642ad

Please sign in to comment.