mirror of
https://github.com/apache/arrow.git
synced 2026-10-29 00:56:31 +08:00
ARROW-2357: [Python] Add microbenchmark for PandasObjectIsNull()
Also add Decimal fodder for other benchmarks.
This commit is contained in:
1 parent
d2d4cc72be
commit
b1c64600cd
10 files changed
+432
-227
No files matched your search
@@ -50,6 +50,7 @@ set(ARROW_PYTHON_TEST_LINK_LIBS ${ARROW_PYTHON_MIN_TEST_LIBS})
|
||||
set(ARROW_PYTHON_SRCS
|
||||
arrow_to_pandas.cc
|
||||
arrow_to_python.cc
|
||||
benchmark.cc
|
||||
builtin_convert.cc
|
||||
common.cc
|
||||
config.cc
|
||||
@@ -99,6 +100,7 @@ install(FILES
|
||||
api.h
|
||||
arrow_to_pandas.h
|
||||
arrow_to_python.h
|
||||
benchmark.h
|
||||
builtin_convert.h
|
||||
common.h
|
||||
config.h
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
#include <arrow/python/benchmark.h>
|
||||
#include <arrow/python/helpers.h>
|
||||
|
||||
namespace arrow {
|
||||
namespace py {
|
||||
namespace benchmark {
|
||||
|
||||
void Benchmark_PandasObjectIsNull(PyObject* list) {
|
||||
if (!PyList_CheckExact(list)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expected a list");
|
||||
return;
|
||||
}
|
||||
Py_ssize_t i, n = PyList_GET_SIZE(list);
|
||||
for (i = 0; i < n; i++) {
|
||||
internal::PandasObjectIsNull(PyList_GET_ITEM(list, i));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace benchmark
|
||||
} // namespace py
|
||||
} // namespace arrow
|
||||
@@ -0,0 +1,39 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
#ifndef ARROW_PYTHON_BENCHMARK_H
|
||||
#define ARROW_PYTHON_BENCHMARK_H
|
||||
|
||||
#include "arrow/python/platform.h"
|
||||
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
namespace py {
|
||||
namespace benchmark {
|
||||
|
||||
// Micro-benchmark routines for use from ASV
|
||||
|
||||
// Run PandasObjectIsNull() once over every object in *list*
|
||||
ARROW_EXPORT
|
||||
void Benchmark_PandasObjectIsNull(PyObject* list);
|
||||
|
||||
} // namespace benchmark
|
||||
} // namespace py
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_PYTHON_BENCHMARK_H
|
||||
@@ -16,16 +16,23 @@
|
||||
# under the License.
|
||||
|
||||
import codecs
|
||||
import decimal
|
||||
from functools import partial
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
import unicodedata
|
||||
|
||||
import numpy as np
|
||||
|
||||
import pyarrow as pa
|
||||
|
||||
|
||||
KILOBYTE = 1 << 10
|
||||
MEGABYTE = KILOBYTE * KILOBYTE
|
||||
|
||||
DEFAULT_NONE_PROB = 0.3
|
||||
|
||||
|
||||
def _multiplicate_sequence(base, target_size):
|
||||
q, r = divmod(target_size, len(base))
|
||||
@@ -97,3 +104,248 @@ def get_random_unicode(n, *, seed=42):
|
||||
result = ''.join(unicode_arr.tolist())
|
||||
assert len(result) == n, (len(result), len(unicode_arr))
|
||||
return result
|
||||
|
||||
|
||||
class BuiltinsGenerator(object):
|
||||
|
||||
def __init__(self, seed=42):
|
||||
self.rnd = np.random.RandomState(seed)
|
||||
|
||||
def sprinkle(self, lst, prob, value):
|
||||
"""
|
||||
Sprinkle *value* entries in list *lst* with likelihood *prob*.
|
||||
"""
|
||||
for i, p in enumerate(self.rnd.random_sample(size=len(lst))):
|
||||
if p < prob:
|
||||
lst[i] = value
|
||||
|
||||
def sprinkle_nones(self, lst, prob):
|
||||
"""
|
||||
Sprinkle None entries in list *lst* with likelihood *prob*.
|
||||
"""
|
||||
self.sprinkle(lst, prob, None)
|
||||
|
||||
def generate_int_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of Python ints with *none_prob* probability of
|
||||
an entry being None.
|
||||
"""
|
||||
data = list(range(n))
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
return data
|
||||
|
||||
def generate_float_list(self, n, none_prob=DEFAULT_NONE_PROB,
|
||||
use_nan=False):
|
||||
"""
|
||||
Generate a list of Python floats with *none_prob* probability of
|
||||
an entry being None (or NaN if *use_nan* is true).
|
||||
"""
|
||||
# Make sure we get Python floats, not np.float64
|
||||
data = list(map(float, self.rnd.uniform(0.0, 1.0, n)))
|
||||
assert len(data) == n
|
||||
self.sprinkle(data, none_prob, value=float('nan') if use_nan else None)
|
||||
return data
|
||||
|
||||
def generate_bool_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of Python bools with *none_prob* probability of
|
||||
an entry being None.
|
||||
"""
|
||||
# Make sure we get Python bools, not np.bool_
|
||||
data = [bool(x >= 0.5) for x in self.rnd.uniform(0.0, 1.0, n)]
|
||||
assert len(data) == n
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
return data
|
||||
|
||||
def generate_decimal_list(self, n, none_prob=DEFAULT_NONE_PROB,
|
||||
use_nan=False):
|
||||
"""
|
||||
Generate a list of Python Decimals with *none_prob* probability of
|
||||
an entry being None (or NaN if *use_nan* is true).
|
||||
"""
|
||||
data = [decimal.Decimal('%.9f' % f)
|
||||
for f in self.rnd.uniform(0.0, 1.0, n)]
|
||||
assert len(data) == n
|
||||
self.sprinkle(data, none_prob,
|
||||
value=decimal.Decimal('nan') if use_nan else None)
|
||||
return data
|
||||
|
||||
def generate_object_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of generic Python objects with *none_prob*
|
||||
probability of an entry being None.
|
||||
"""
|
||||
data = [object() for i in range(n)]
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
return data
|
||||
|
||||
def _generate_varying_sequences(self, random_factory, n, min_size, max_size, none_prob):
|
||||
"""
|
||||
Generate a list of *n* sequences of varying size between *min_size*
|
||||
and *max_size*, with *none_prob* probability of an entry being None.
|
||||
The base material for each sequence is obtained by calling
|
||||
`random_factory(<some size>)`
|
||||
"""
|
||||
base_size = 10000
|
||||
base = random_factory(base_size + max_size)
|
||||
data = []
|
||||
for i in range(n):
|
||||
off = self.rnd.randint(base_size)
|
||||
if min_size == max_size:
|
||||
size = min_size
|
||||
else:
|
||||
size = self.rnd.randint(min_size, max_size + 1)
|
||||
data.append(base[off:off + size])
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
assert len(data) == n
|
||||
return data
|
||||
|
||||
def generate_fixed_binary_list(self, n, size, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of bytestrings with a fixed *size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(get_random_bytes, n,
|
||||
size, size, none_prob)
|
||||
|
||||
|
||||
def generate_varying_binary_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of bytestrings with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(get_random_bytes, n,
|
||||
min_size, max_size, none_prob)
|
||||
|
||||
|
||||
def generate_ascii_string_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of ASCII strings with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(get_random_ascii, n,
|
||||
min_size, max_size, none_prob)
|
||||
|
||||
|
||||
def generate_unicode_string_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of unicode strings with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(get_random_unicode, n,
|
||||
min_size, max_size, none_prob)
|
||||
|
||||
|
||||
def generate_int_list_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of lists of Python ints with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(
|
||||
partial(self.generate_int_list, none_prob=none_prob),
|
||||
n, min_size, max_size, none_prob)
|
||||
|
||||
def generate_tuple_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of tuples with random values.
|
||||
Each tuple has the form `(int value, float value, bool value)`
|
||||
"""
|
||||
dicts = self.generate_dict_list(n, none_prob=none_prob)
|
||||
tuples = [(d.get('u'), d.get('v'), d.get('w'))
|
||||
if d is not None else None
|
||||
for d in dicts]
|
||||
assert len(tuples) == n
|
||||
return tuples
|
||||
|
||||
def generate_dict_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of dicts with random values.
|
||||
Each dict has the form `{'u': int value, 'v': float value, 'w': bool value}`
|
||||
"""
|
||||
ints = self.generate_int_list(n, none_prob=none_prob)
|
||||
floats = self.generate_float_list(n, none_prob=none_prob)
|
||||
bools = self.generate_bool_list(n, none_prob=none_prob)
|
||||
dicts = []
|
||||
# Keep half the Nones, omit the other half
|
||||
keep_nones = itertools.cycle([True, False])
|
||||
for u, v, w in zip(ints, floats, bools):
|
||||
d = {}
|
||||
if u is not None or next(keep_nones):
|
||||
d['u'] = u
|
||||
if v is not None or next(keep_nones):
|
||||
d['v'] = v
|
||||
if w is not None or next(keep_nones):
|
||||
d['w'] = w
|
||||
dicts.append(d)
|
||||
self.sprinkle_nones(dicts, none_prob)
|
||||
assert len(dicts) == n
|
||||
return dicts
|
||||
|
||||
def get_type_and_builtins(self, n, type_name):
|
||||
"""
|
||||
Return a `(arrow type, list)` tuple where the arrow type
|
||||
corresponds to the given logical *type_name*, and the list
|
||||
is a list of *n* random-generated Python objects compatible
|
||||
with the arrow type.
|
||||
"""
|
||||
size = None
|
||||
|
||||
if type_name in ('bool', 'decimal', 'ascii', 'unicode', 'int64 list'):
|
||||
kind = type_name
|
||||
elif type_name.startswith(('int', 'uint')):
|
||||
kind = 'int'
|
||||
elif type_name.startswith('float'):
|
||||
kind = 'float'
|
||||
elif type_name.startswith('struct'):
|
||||
kind = 'struct'
|
||||
elif type_name == 'binary':
|
||||
kind = 'varying binary'
|
||||
elif type_name.startswith('binary'):
|
||||
kind = 'fixed binary'
|
||||
size = int(type_name[6:])
|
||||
assert size > 0
|
||||
else:
|
||||
raise ValueError("unrecognized type %r" % (type_name,))
|
||||
|
||||
if kind in ('int', 'float'):
|
||||
ty = getattr(pa, type_name)()
|
||||
elif kind == 'bool':
|
||||
ty = pa.bool_()
|
||||
elif kind == 'decimal':
|
||||
ty = pa.decimal128(9, 9)
|
||||
elif kind == 'fixed binary':
|
||||
ty = pa.binary(size)
|
||||
elif kind == 'varying binary':
|
||||
ty = pa.binary()
|
||||
elif kind in ('ascii', 'unicode'):
|
||||
ty = pa.string()
|
||||
elif kind == 'int64 list':
|
||||
ty = pa.list_(pa.int64())
|
||||
elif kind == 'struct':
|
||||
ty = pa.struct([pa.field('u', pa.int64()),
|
||||
pa.field('v', pa.float64()),
|
||||
pa.field('w', pa.bool_())])
|
||||
|
||||
factories = {
|
||||
'int': self.generate_int_list,
|
||||
'float': self.generate_float_list,
|
||||
'bool': self.generate_bool_list,
|
||||
'decimal': self.generate_decimal_list,
|
||||
'fixed binary': partial(self.generate_fixed_binary_list,
|
||||
size=size),
|
||||
'varying binary': partial(self.generate_varying_binary_list,
|
||||
min_size=3, max_size=40),
|
||||
'ascii': partial(self.generate_ascii_string_list,
|
||||
min_size=3, max_size=40),
|
||||
'unicode': partial(self.generate_unicode_string_list,
|
||||
min_size=3, max_size=40),
|
||||
'int64 list': partial(self.generate_int_list_list,
|
||||
min_size=0, max_size=20),
|
||||
'struct': self.generate_dict_list,
|
||||
'struct from tuples': self.generate_tuple_list,
|
||||
}
|
||||
data = factories[kind](n)
|
||||
return ty, data
|
||||
@@ -15,233 +15,13 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from functools import partial
|
||||
import itertools
|
||||
|
||||
import numpy as np
|
||||
import pyarrow as pa
|
||||
|
||||
from . import common
|
||||
|
||||
|
||||
DEFAULT_NONE_PROB = 0.3
|
||||
|
||||
|
||||
# TODO:
|
||||
# - test dates and times
|
||||
# - test decimals
|
||||
|
||||
class BuiltinsGenerator(object):
|
||||
|
||||
def __init__(self, seed=42):
|
||||
self.rnd = np.random.RandomState(seed)
|
||||
|
||||
def sprinkle_nones(self, lst, prob):
|
||||
"""
|
||||
Sprinkle None entries in list *lst* with likelihood *prob*.
|
||||
"""
|
||||
for i, p in enumerate(self.rnd.random_sample(size=len(lst))):
|
||||
if p < prob:
|
||||
lst[i] = None
|
||||
|
||||
def generate_int_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of Python ints with *none_prob* probability of
|
||||
an entry being None.
|
||||
"""
|
||||
data = list(range(n))
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
return data
|
||||
|
||||
def generate_float_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of Python floats with *none_prob* probability of
|
||||
an entry being None.
|
||||
"""
|
||||
# Make sure we get Python floats, not np.float64
|
||||
data = list(map(float, self.rnd.uniform(0.0, 1.0, n)))
|
||||
assert len(data) == n
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
return data
|
||||
|
||||
def generate_bool_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of Python bools with *none_prob* probability of
|
||||
an entry being None.
|
||||
"""
|
||||
# Make sure we get Python bools, not np.bool_
|
||||
data = [bool(x >= 0.5) for x in self.rnd.uniform(0.0, 1.0, n)]
|
||||
assert len(data) == n
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
return data
|
||||
|
||||
def _generate_varying_sequences(self, random_factory, n, min_size, max_size, none_prob):
|
||||
"""
|
||||
Generate a list of *n* sequences of varying size between *min_size*
|
||||
and *max_size*, with *none_prob* probability of an entry being None.
|
||||
The base material for each sequence is obtained by calling
|
||||
`random_factory(<some size>)`
|
||||
"""
|
||||
base_size = 10000
|
||||
base = random_factory(base_size + max_size)
|
||||
data = []
|
||||
for i in range(n):
|
||||
off = self.rnd.randint(base_size)
|
||||
if min_size == max_size:
|
||||
size = min_size
|
||||
else:
|
||||
size = self.rnd.randint(min_size, max_size + 1)
|
||||
data.append(base[off:off + size])
|
||||
self.sprinkle_nones(data, none_prob)
|
||||
assert len(data) == n
|
||||
return data
|
||||
|
||||
def generate_fixed_binary_list(self, n, size, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of bytestrings with a fixed *size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(common.get_random_bytes, n,
|
||||
size, size, none_prob)
|
||||
|
||||
|
||||
def generate_varying_binary_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of bytestrings with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(common.get_random_bytes, n,
|
||||
min_size, max_size, none_prob)
|
||||
|
||||
|
||||
def generate_ascii_string_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of ASCII strings with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(common.get_random_ascii, n,
|
||||
min_size, max_size, none_prob)
|
||||
|
||||
|
||||
def generate_unicode_string_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of unicode strings with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(common.get_random_unicode, n,
|
||||
min_size, max_size, none_prob)
|
||||
|
||||
|
||||
def generate_int_list_list(self, n, min_size, max_size,
|
||||
none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of lists of Python ints with a random size between
|
||||
*min_size* and *max_size*.
|
||||
"""
|
||||
return self._generate_varying_sequences(
|
||||
partial(self.generate_int_list, none_prob=none_prob),
|
||||
n, min_size, max_size, none_prob)
|
||||
|
||||
def generate_tuple_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of tuples with random values.
|
||||
Each tuple has the form `(int value, float value, bool value)`
|
||||
"""
|
||||
dicts = self.generate_dict_list(n, none_prob=none_prob)
|
||||
tuples = [(d.get('u'), d.get('v'), d.get('w'))
|
||||
if d is not None else None
|
||||
for d in dicts]
|
||||
assert len(tuples) == n
|
||||
return tuples
|
||||
|
||||
def generate_dict_list(self, n, none_prob=DEFAULT_NONE_PROB):
|
||||
"""
|
||||
Generate a list of dicts with random values.
|
||||
Each dict has the form `{'u': int value, 'v': float value, 'w': bool value}`
|
||||
"""
|
||||
ints = self.generate_int_list(n, none_prob=none_prob)
|
||||
floats = self.generate_float_list(n, none_prob=none_prob)
|
||||
bools = self.generate_bool_list(n, none_prob=none_prob)
|
||||
dicts = []
|
||||
# Keep half the Nones, omit the other half
|
||||
keep_nones = itertools.cycle([True, False])
|
||||
for u, v, w in zip(ints, floats, bools):
|
||||
d = {}
|
||||
if u is not None or next(keep_nones):
|
||||
d['u'] = u
|
||||
if v is not None or next(keep_nones):
|
||||
d['v'] = v
|
||||
if w is not None or next(keep_nones):
|
||||
d['w'] = w
|
||||
dicts.append(d)
|
||||
self.sprinkle_nones(dicts, none_prob)
|
||||
assert len(dicts) == n
|
||||
return dicts
|
||||
|
||||
def get_type_and_builtins(self, n, type_name):
|
||||
"""
|
||||
Return a `(arrow type, list)` tuple where the arrow type
|
||||
corresponds to the given logical *type_name*, and the list
|
||||
is a list of *n* random-generated Python objects compatible
|
||||
with the arrow type.
|
||||
"""
|
||||
size = None
|
||||
|
||||
if type_name in ('bool', 'ascii', 'unicode', 'int64 list'):
|
||||
kind = type_name
|
||||
elif type_name.startswith(('int', 'uint')):
|
||||
kind = 'int'
|
||||
elif type_name.startswith('float'):
|
||||
kind = 'float'
|
||||
elif type_name.startswith('struct'):
|
||||
kind = 'struct'
|
||||
elif type_name == 'binary':
|
||||
kind = 'varying binary'
|
||||
elif type_name.startswith('binary'):
|
||||
kind = 'fixed binary'
|
||||
size = int(type_name[6:])
|
||||
assert size > 0
|
||||
else:
|
||||
raise ValueError("unrecognized type %r" % (type_name,))
|
||||
|
||||
if kind in ('int', 'float'):
|
||||
ty = getattr(pa, type_name)()
|
||||
elif kind == 'bool':
|
||||
ty = pa.bool_()
|
||||
elif kind == 'fixed binary':
|
||||
ty = pa.binary(size)
|
||||
elif kind == 'varying binary':
|
||||
ty = pa.binary()
|
||||
elif kind in ('ascii', 'unicode'):
|
||||
ty = pa.string()
|
||||
elif kind == 'int64 list':
|
||||
ty = pa.list_(pa.int64())
|
||||
elif kind == 'struct':
|
||||
ty = pa.struct([pa.field('u', pa.int64()),
|
||||
pa.field('v', pa.float64()),
|
||||
pa.field('w', pa.bool_())])
|
||||
|
||||
factories = {
|
||||
'int': self.generate_int_list,
|
||||
'float': self.generate_float_list,
|
||||
'bool': self.generate_bool_list,
|
||||
'fixed binary': partial(self.generate_fixed_binary_list,
|
||||
size=size),
|
||||
'varying binary': partial(self.generate_varying_binary_list,
|
||||
min_size=3, max_size=40),
|
||||
'ascii': partial(self.generate_ascii_string_list,
|
||||
min_size=3, max_size=40),
|
||||
'unicode': partial(self.generate_unicode_string_list,
|
||||
min_size=3, max_size=40),
|
||||
'int64 list': partial(self.generate_int_list_list,
|
||||
min_size=0, max_size=20),
|
||||
'struct': self.generate_dict_list,
|
||||
'struct from tuples': self.generate_tuple_list,
|
||||
}
|
||||
data = factories[kind](n)
|
||||
return ty, data
|
||||
|
||||
|
||||
class ConvertPyListToArray(object):
|
||||
@@ -250,7 +30,7 @@ class ConvertPyListToArray(object):
|
||||
"""
|
||||
size = 10 ** 5
|
||||
types = ('int32', 'uint32', 'int64', 'uint64',
|
||||
'float32', 'float64', 'bool',
|
||||
'float32', 'float64', 'bool', 'decimal',
|
||||
'binary', 'binary10', 'ascii', 'unicode',
|
||||
'int64 list', 'struct', 'struct from tuples')
|
||||
|
||||
@@ -258,7 +38,7 @@ class ConvertPyListToArray(object):
|
||||
params = [types]
|
||||
|
||||
def setup(self, type_name):
|
||||
gen = BuiltinsGenerator()
|
||||
gen = common.BuiltinsGenerator()
|
||||
self.ty, self.data = gen.get_type_and_builtins(self.size, type_name)
|
||||
|
||||
def time_convert(self, *args):
|
||||
@@ -270,15 +50,15 @@ class InferPyListToArray(object):
|
||||
Benchmark pa.array(list of values) with type inference
|
||||
"""
|
||||
size = 10 ** 5
|
||||
types = ('int64', 'float64', 'bool', 'binary', 'ascii', 'unicode',
|
||||
'int64 list')
|
||||
types = ('int64', 'float64', 'bool', 'decimal', 'binary', 'ascii',
|
||||
'unicode', 'int64 list')
|
||||
# TODO add 'struct' when supported
|
||||
|
||||
param_names = ['type']
|
||||
params = [types]
|
||||
|
||||
def setup(self, type_name):
|
||||
gen = BuiltinsGenerator()
|
||||
gen = common.BuiltinsGenerator()
|
||||
self.ty, self.data = gen.get_type_and_builtins(self.size, type_name)
|
||||
|
||||
def time_infer(self, *args):
|
||||
@@ -292,7 +72,7 @@ class ConvertArrayToPyList(object):
|
||||
"""
|
||||
size = 10 ** 5
|
||||
types = ('int32', 'uint32', 'int64', 'uint64',
|
||||
'float32', 'float64', 'bool',
|
||||
'float32', 'float64', 'bool', 'decimal',
|
||||
'binary', 'binary10', 'ascii', 'unicode',
|
||||
'int64 list', 'struct')
|
||||
|
||||
@@ -300,7 +80,7 @@ class ConvertArrayToPyList(object):
|
||||
params = [types]
|
||||
|
||||
def setup(self, type_name):
|
||||
gen = BuiltinsGenerator()
|
||||
gen = common.BuiltinsGenerator()
|
||||
self.ty, self.data = gen.get_type_and_builtins(self.size, type_name)
|
||||
self.arr = pa.array(self.data, type=self.ty)
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
import pyarrow as pa
|
||||
import pyarrow.benchmark as pb
|
||||
|
||||
from . import common
|
||||
|
||||
|
||||
class PandasObjectIsNull(object):
|
||||
size = 10 ** 5
|
||||
types = ('int', 'float', 'object', 'decimal')
|
||||
|
||||
param_names = ['type']
|
||||
params = [types]
|
||||
|
||||
def setup(self, type_name):
|
||||
gen = common.BuiltinsGenerator()
|
||||
if type_name == 'int':
|
||||
lst = gen.generate_int_list(self.size)
|
||||
elif type_name == 'float':
|
||||
lst = gen.generate_float_list(self.size, use_nan=True)
|
||||
elif type_name == 'object':
|
||||
lst = gen.generate_object_list(self.size)
|
||||
elif type_name == 'decimal':
|
||||
lst = gen.generate_decimal_list(self.size)
|
||||
else:
|
||||
assert 0
|
||||
self.lst = lst
|
||||
|
||||
def time_PandasObjectIsNull(self, *args):
|
||||
pb.benchmark_PandasObjectIsNull(self.lst)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
|
||||
def benchmark_PandasObjectIsNull(list obj):
|
||||
Benchmark_PandasObjectIsNull(obj)
|
||||
@@ -0,0 +1,20 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
from pyarrow.lib import benchmark_PandasObjectIsNull
|
||||
@@ -978,6 +978,10 @@ cdef extern from 'arrow/python/config.h' namespace 'arrow::py':
|
||||
void set_numpy_nan(object o)
|
||||
|
||||
|
||||
cdef extern from 'arrow/python/benchmark.h' namespace 'arrow::py::benchmark':
|
||||
void Benchmark_PandasObjectIsNull(object lst) except *
|
||||
|
||||
|
||||
cdef extern from 'arrow/util/compression.h' namespace 'arrow' nogil:
|
||||
enum CompressionType" arrow::Compression::type":
|
||||
CompressionType_UNCOMPRESSED" arrow::Compression::UNCOMPRESSED"
|
||||
|
||||
@@ -126,5 +126,8 @@ include "feather.pxi"
|
||||
# Python serialization
|
||||
include "serialization.pxi"
|
||||
|
||||
# Micro-benchmark routines
|
||||
include "benchmark.pxi"
|
||||
|
||||
# Public API
|
||||
include "public-api.pxi"
|
||||
Reference in new issue
Block a user