Don't return early on ds line render to avoid breaking profiling

The pg profiler seems to have trouble with early `return`s in function
calls (likely muckery with the GC/`.__delete__()`) so let's just try
to avoid it for now until we either fix it (probably by implementing as
a ctx mngr) or use diff one.
big_data_lines
Tyler Goodlet 2022-04-06 09:09:44 -04:00
parent b20e9e58ee
commit 1a95712680
2 changed files with 140 additions and 143 deletions

View File

@ -265,6 +265,7 @@ class FastAppendCurve(pg.GraphicsObject):
y_iv: np.ndarray, y_iv: np.ndarray,
view_range: Optional[tuple[int, int]] = None, view_range: Optional[tuple[int, int]] = None,
profiler: Optional[pg.debug.Profiler] = None,
) -> QtGui.QPainterPath: ) -> QtGui.QPainterPath:
''' '''
@ -274,7 +275,7 @@ class FastAppendCurve(pg.GraphicsObject):
a length diff. a length diff.
''' '''
profiler = pg.debug.Profiler( profiler = profiler or pg.debug.Profiler(
msg=f'FastAppendCurve.update_from_array(): `{self._name}`', msg=f'FastAppendCurve.update_from_array(): `{self._name}`',
disabled=not pg_profile_enabled(), disabled=not pg_profile_enabled(),
gt=ms_slower_then, gt=ms_slower_then,

View File

@ -318,7 +318,6 @@ class BarItems(pg.GraphicsObject):
return self.path return self.path
def x_uppx(self) -> int: def x_uppx(self) -> int:
if self._ds_line: if self._ds_line:
return self._ds_line.x_uppx() return self._ds_line.x_uppx()
@ -335,6 +334,7 @@ class BarItems(pg.GraphicsObject):
ohlc_iv: np.ndarray, ohlc_iv: np.ndarray,
view_range: Optional[tuple[int, int]] = None, view_range: Optional[tuple[int, int]] = None,
profiler: Optional[pg.debug.Profiler] = None,
) -> None: ) -> None:
''' '''
@ -350,7 +350,7 @@ class BarItems(pg.GraphicsObject):
This routine should be made (transitively) as fast as possible. This routine should be made (transitively) as fast as possible.
''' '''
profiler = pg.debug.Profiler( profiler = profiler or pg.debug.Profiler(
disabled=not pg_profile_enabled(), disabled=not pg_profile_enabled(),
gt=ms_slower_then, gt=ms_slower_then,
delayed=True, delayed=True,
@ -393,15 +393,12 @@ class BarItems(pg.GraphicsObject):
profiler('ds logic complete') profiler('ds logic complete')
if ( if should_line:
should_line
):
# update the line graphic # update the line graphic
# x, y = self._ds_line_xy = ohlc_flatten(ohlc_iv) # x, y = self._ds_line_xy = ohlc_flatten(ohlc_iv)
x, y = self._ds_line_xy = ohlc_flatten(ohlc) x, y = self._ds_line_xy = ohlc_flatten(ohlc)
x_iv, y_iv = self._ds_line_xy = ohlc_flatten(ohlc_iv) x_iv, y_iv = self._ds_line_xy = ohlc_flatten(ohlc_iv)
profiler('flattening bars to line') profiler('flattening bars to line')
print(f'rendering linesc')
# TODO: we should be diffing the amount of new data which # TODO: we should be diffing the amount of new data which
# needs to be downsampled. Ideally we actually are just # needs to be downsampled. Ideally we actually are just
@ -416,6 +413,7 @@ class BarItems(pg.GraphicsObject):
x_iv=x_iv, x_iv=x_iv,
y_iv=y_iv, y_iv=y_iv,
view_range=None, # hack view_range=None, # hack
profiler=profiler,
) )
profiler('updated ds line') profiler('updated ds line')
@ -438,179 +436,177 @@ class BarItems(pg.GraphicsObject):
# stop here since we don't need to update bars path any more # stop here since we don't need to update bars path any more
# as we delegate to the downsample line with updates. # as we delegate to the downsample line with updates.
profiler.finish() profiler.finish()
print('terminating early') # print('terminating early')
return return
elif ( else:
not should_line # we should be in bars mode
and self._in_ds
):
# flip back to bars graphics and hide the downsample line.
log.info(f'showing bars graphic {self._name}')
curve = self._ds_line if self._in_ds:
curve.hide() # flip back to bars graphics and hide the downsample line.
# self._pi.removeItem(curve) log.info(f'showing bars graphic {self._name}')
# XXX: is this actually any faster? curve = self._ds_line
# self._pi.addItem(self) curve.hide()
self.show() # self._pi.removeItem(curve)
self._in_ds = False
# generate in_view path # XXX: is this actually any faster?
self.path = gen_qpath( # self._pi.addItem(self)
ohlc_iv, self.show()
0, self._in_ds = False
self.w,
# path=self.path,
)
# TODO: to make the downsampling faster # generate in_view path
# - allow mapping only a range of lines thus only drawing as self.path = gen_qpath(
# many bars as exactly specified. ohlc_iv,
# - move ohlc "flattening" to a shmarr 0,
# - maybe move all this embedded logic to a higher self.w,
# level type? # path=self.path,
)
# ohlc = in_view # TODO: to make the downsampling faster
# - allow mapping only a range of lines thus only drawing as
# many bars as exactly specified.
# - move ohlc "flattening" to a shmarr
# - maybe move all this embedded logic to a higher
# level type?
# if prepend_length: # if prepend_length:
# # new history was added and we need to render a new path # # new history was added and we need to render a new path
# prepend_bars = ohlc[:prepend_length] # prepend_bars = ohlc[:prepend_length]
# if ds_prepend_length: # if ds_prepend_length:
# ds_prepend_bars = ohlc[:ds_prepend_length] # ds_prepend_bars = ohlc[:ds_prepend_length]
# pre_x, pre_y = ohlc_flatten(ds_prepend_bars) # pre_x, pre_y = ohlc_flatten(ds_prepend_bars)
# fx = np.concatenate((pre_x, fx)) # fx = np.concatenate((pre_x, fx))
# fy = np.concatenate((pre_y, fy)) # fy = np.concatenate((pre_y, fy))
# profiler('ds line prepend diff complete') # profiler('ds line prepend diff complete')
# if append_length: # if append_length:
# # generate new graphics to match provided array # # generate new graphics to match provided array
# # path appending logic: # # path appending logic:
# # we need to get the previous "current bar(s)" for the time step # # we need to get the previous "current bar(s)" for the time step
# # and convert it to a sub-path to append to the historical set # # and convert it to a sub-path to append to the historical set
# # new_bars = ohlc[istop - 1:istop + append_length - 1] # # new_bars = ohlc[istop - 1:istop + append_length - 1]
# append_bars = ohlc[-append_length - 1:-1] # append_bars = ohlc[-append_length - 1:-1]
# # print(f'ohlc bars to append size: {append_bars.size}\n') # # print(f'ohlc bars to append size: {append_bars.size}\n')
# if ds_append_length: # if ds_append_length:
# ds_append_bars = ohlc[-ds_append_length - 1:-1] # ds_append_bars = ohlc[-ds_append_length - 1:-1]
# post_x, post_y = ohlc_flatten(ds_append_bars) # post_x, post_y = ohlc_flatten(ds_append_bars)
# print( # print(
# f'ds curve to append sizes: {(post_x.size, post_y.size)}' # f'ds curve to append sizes: {(post_x.size, post_y.size)}'
# ) # )
# fx = np.concatenate((fx, post_x)) # fx = np.concatenate((fx, post_x))
# fy = np.concatenate((fy, post_y)) # fy = np.concatenate((fy, post_y))
# profiler('ds line append diff complete') # profiler('ds line append diff complete')
profiler('array diffs complete') profiler('array diffs complete')
# does this work? # does this work?
last = ohlc[-1] last = ohlc[-1]
# fy[-1] = last['close'] # fy[-1] = last['close']
# # incremental update and cache line datums # # incremental update and cache line datums
# self._ds_line_xy = fx, fy # self._ds_line_xy = fx, fy
# maybe downsample to line # maybe downsample to line
# ds = self.maybe_downsample() # ds = self.maybe_downsample()
# if ds: # if ds:
# # if we downsample to a line don't bother with # # if we downsample to a line don't bother with
# # any more path generation / updates # # any more path generation / updates
# self._ds_xrange = first_index, last_index # self._ds_xrange = first_index, last_index
# profiler('downsampled to line') # profiler('downsampled to line')
# return # return
# print(in_view.size) # print(in_view.size)
# if self.path: # if self.path:
# self.path = path # self.path = path
# self.path.reserve(path.capacity()) # self.path.reserve(path.capacity())
# self.path.swap(path) # self.path.swap(path)
# path updates # path updates
# if prepend_length: # if prepend_length:
# # XXX: SOMETHING IS MAYBE FISHY HERE what with the old_path # # XXX: SOMETHING IS MAYBE FISHY HERE what with the old_path
# # y value not matching the first value from # # y value not matching the first value from
# # ohlc[prepend_length + 1] ??? # # ohlc[prepend_length + 1] ???
# prepend_path = gen_qpath(prepend_bars, 0, self.w) # prepend_path = gen_qpath(prepend_bars, 0, self.w)
# old_path = self.path # old_path = self.path
# self.path = prepend_path # self.path = prepend_path
# self.path.addPath(old_path) # self.path.addPath(old_path)
# profiler('path PREPEND') # profiler('path PREPEND')
# if append_length: # if append_length:
# append_path = gen_qpath(append_bars, 0, self.w) # append_path = gen_qpath(append_bars, 0, self.w)
# self.path.moveTo( # self.path.moveTo(
# float(istop - self.w), # float(istop - self.w),
# float(append_bars[0]['open']) # float(append_bars[0]['open'])
# ) # )
# self.path.addPath(append_path) # self.path.addPath(append_path)
# profiler('path APPEND') # profiler('path APPEND')
# fp = self.fast_path # fp = self.fast_path
# if fp is None: # if fp is None:
# self.fast_path = append_path # self.fast_path = append_path
# else: # else:
# fp.moveTo( # fp.moveTo(
# float(istop - self.w), float(new_bars[0]['open']) # float(istop - self.w), float(new_bars[0]['open'])
# ) # )
# fp.addPath(append_path) # fp.addPath(append_path)
# self.setCacheMode(QtWidgets.QGraphicsItem.NoCache) # self.setCacheMode(QtWidgets.QGraphicsItem.NoCache)
# flip_cache = True # flip_cache = True
self._xrange = first_index, last_index self._xrange = first_index, last_index
# trigger redraw despite caching # trigger redraw despite caching
self.prepareGeometryChange() self.prepareGeometryChange()
# generate new lines objects for updatable "current bar" # generate new lines objects for updatable "current bar"
self._last_bar_lines = bar_from_ohlc_row(last, self.w) self._last_bar_lines = bar_from_ohlc_row(last, self.w)
# last bar update # last bar update
i, o, h, l, last, v = last[ i, o, h, l, last, v = last[
['index', 'open', 'high', 'low', 'close', 'volume'] ['index', 'open', 'high', 'low', 'close', 'volume']
] ]
# assert i == self.start_index - 1 # assert i == self.start_index - 1
# assert i == last_index # assert i == last_index
body, larm, rarm = self._last_bar_lines body, larm, rarm = self._last_bar_lines
# XXX: is there a faster way to modify this? # XXX: is there a faster way to modify this?
rarm.setLine(rarm.x1(), last, rarm.x2(), last) rarm.setLine(rarm.x1(), last, rarm.x2(), last)
# writer is responsible for changing open on "first" volume of bar # writer is responsible for changing open on "first" volume of bar
larm.setLine(larm.x1(), o, larm.x2(), o) larm.setLine(larm.x1(), o, larm.x2(), o)
if l != h: # noqa if l != h: # noqa
if body is None: if body is None:
body = self._last_bar_lines[0] = QLineF(i, l, i, h) body = self._last_bar_lines[0] = QLineF(i, l, i, h)
else: else:
# update body # update body
body.setLine(i, l, i, h) body.setLine(i, l, i, h)
# XXX: pretty sure this is causing an issue where the bar has # XXX: pretty sure this is causing an issue where the bar has
# a large upward move right before the next sample and the body # a large upward move right before the next sample and the body
# is getting set to None since the next bar is flat but the shm # is getting set to None since the next bar is flat but the shm
# array index update wasn't read by the time this code runs. Iow # array index update wasn't read by the time this code runs. Iow
# we're doing this removal of the body for a bar index that is # we're doing this removal of the body for a bar index that is
# now out of date / from some previous sample. It's weird # now out of date / from some previous sample. It's weird
# though because i've seen it do this to bars i - 3 back? # though because i've seen it do this to bars i - 3 back?
profiler('last bar set') profiler('last bar set')
self.update() self.update()
profiler('.update()') profiler('.update()')
if flip_cache: if flip_cache:
self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache) self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)
profiler.finish() profiler.finish()
def boundingRect(self): def boundingRect(self):
# Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect # Qt docs: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect