I have tested map1
, which is the same as map
, but is more efficient implementation for the case of 1 iterable. Also, implemented mapg = Custom(map1, map)
, which selects which map
function to use based on the input.
from hello import ilen
from map1 import map1
from custom import Custom
mapg = Custom(map1, map)
def test_map1(a):
ilen(map1(bool, a))
def test_mapg(a):
ilen(mapg(bool, a))
def test_map(a):
ilen(map(bool, a))
ns = nda.ary([1, 5, 10, 50, 100, 500, 1000, 5_000, 10_000, 100_000])
rngs = [range(i) for i in ns]
lambdas = [
[ftl.partial(test_map1, a),
ftl.partial(test_mapg, a),
ftl.partial(test_map, a)] for a in rngs
]
βββββββββββββββββββββββββββββββββββββββββββ
β 5 repeats, 10,000 times β
β£ββββββββββββββββββββββββββββββββββββββββββ«
β Units: ns map1 mapg map β
β βββββββββββββββββββββββββββββββ«
β 1 β 241 250 247 β
β 5 β 290 292 301 β
β 10 β 355 368 377 β
β 50 β 887 898 934 β
β 100 β 1518 1545 1666 β
β 500 β 9680 9619 10319 β
β 1000 β 21492 21935 23451 β
β 5000 β 117899 118968 126211 β
β 10000 β 243840 237693 255482 β
β 100000 β 2427835 2439256 2490276 β
βββββββββββββ»ββββββββββββββββββββββββββββββ
| map1 % mapg % map1 ns/iter mapg ns/iter
-------+----------------------------------------
1 | 2.4 -1.3 5.9 -3.1
5 | 3.5 2.8 2.1 1.7
10 | 5.9 2.5 2.2 1.0
50 | 5.1 3.9 1.0 0.7
100 | 8.9 7.2 1.5 1.2
500 | 6.2 6.8 1.3 1.4
1000 | 8.4 6.5 2.0 1.5
5000 | 6.6 5.7 1.7 1.4
10000 | 4.6 7.0 1.2 1.8
100000 | 2.5 2.0 0.6 0.5
Biggest performance gain is close to 10% for iterables of size 100.
mapg = Custom(map1, map)
does selection for the cost of 10 ns
. So it could be efficiently implemented to benefit existing code as well.
Although performance benefit isnβt very big, however it is non-trivial for sizes of 10-100, which is approximately the range which I was trying to address in Builtins.any performance - #29 by dgrigonis, where I was looking for ways to improve functional tools so that they are competitive against simple loop for short iterable sizes.
This is one part out of 2 for improvement that I came up with while looking at it and is a simpler one.
map
function is used extensively so the performance benefits potentially amounts to something a bit more significant. Also, most of use-cases are with 1 argument.
Cpython:
zg '\Wmap\([^,]*,[^,]*\)' | wc -l
452
zg '\Wmap\([^,]*,[^,]*,[^,]\)' | wc -l
15
Github:
565k files \Wmap\([\w\s]*,[\w\s]*\)
14k files \Wmap\([\w\s]*,[\w\s]*,[\w\s]*\)
Does this sound like something that would be worthwhile?