Comment

Comment by eesmith

The parse code at https://github.com/gregstoll/baseballstats/blob/443dbefe1d9b... shows a few ways the Python code could be sped up:

        if (not doneParsingEvent):
            if (batterEvent.startswith('K')):
                runnerDests['B'] = 0
                runnersDefaultStayStill = True
                if (batterEvent.startswith('K+') or batterEvent.startswith('K23+')):
                    if batterEvent.startswith('K+'):
The "not doneParsingEvent" is used to emulate a "continue" statement. As is, every line can trigger a large number if "if (not doneParsing):" tests.

Python's s.startswith() methods are very attractive, but slow compared to the error-prone:

    if batterEvent[0] == "K":
      ...
      if batterEvent[:2] == "K+":
         ..
Here are the timings:

    % python -m timeit -s 's = "Knights"' 's.startswith("K")'
    2000000 loops, best of 5: 119 nsec per loop
    % python -m timeit -s 's = "Knights"' 's[:1] == "K"'
    5000000 loops, best of 5: 76.5 nsec per loop
    % python -m timeit -s 's = "Knights"' 's[0] == "K"'
    5000000 loops, best of 5: 41.4 nsec per loop
There are a number of uses of:

    simpleHitMatch = getRe(r"^([SDTH])(?:\d|/)").match(batterEvent)
where "getRe()" implements a simple regex cache. However 1) re.match() also implements a simple regex cache, and 2) I typically implement this as a per-module variable, one per regex:

    _simple_hit_pattern_matcher = re.compile(r"^([SDTH])(?:\d|/)").match
which is then used as:

    simpleHitMatch = _simple_hit_pattern_matcher(batterEvent)
This would reduce the call overhead by removing the double cache table lookup.

Bear in mind that I don't know where the time is spent (so I may be looking in the wrong place) and I don't think these changes could get an 8x performance improvement.

parent eesmith 5 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton