Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ Method names are `<terms>-<format>`, plus `-<API>` for Jelly, which has two APIs
| `rdflib-jelly-graph` | Jelly through rdflib's plugin API: `Graph.serialize` | `Graph.parse` |
| `rdflib-jelly-stream` | Jelly with pyjelly's flat streaming API, from the list | `parse_jelly_flat` |
| `generic-jelly-stream` | The same, with the generic integration's terms instead of rdflib's | `parse_jelly_flat` |
| `rdflib-jelly11-stream`, `generic-jelly11-stream` | The same two, writing Jelly-RDF 1.1 instead of 1.2 | `parse_jelly_flat` |

All Jelly methods use pyjelly's default options: the "big" lookup preset (4000 names, 150 prefixes, 32 datatypes) and frames of 250 rows. The other formats' writers get the dataset's prefixes.
All Jelly methods use pyjelly's default options: the "big" lookup preset (4000 names, 150 prefixes, 32 datatypes) and frames of 1024 rows. The other formats' writers get the dataset's prefixes.

### Tasks

Expand Down
14 changes: 9 additions & 5 deletions benchmarks/measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,6 @@ def operation() -> None:
def operation() -> int:
return int(method.read(written, quads=data.quads))

# Everything made so far lives until the end. Freezing it keeps the garbage
# collector from going through it again and again during the measurement.
gc.collect()
gc.freeze()

_measure(
operation,
result,
Expand All @@ -177,6 +172,14 @@ def _measure( # noqa: PLR0913
profile: Path | None,
) -> None:
"""Run the warmup and measured iterations, and fill in the result."""
# All objects allocated up to this point will be needed until the end
# of the benchmark. We freeze it to keep the GC from going through it
# again and again during the measurement. PyPy has no gc.freeze(),
# and doesn't need it: its collector doesn't go through old objects
# again unless they change.
gc.collect()
if hasattr(gc, "freeze"):
gc.freeze()
result.warmup = [
_iteration(operation, result.statements, seconds) for _ in range(warmup)
]
Expand Down Expand Up @@ -212,6 +215,7 @@ def environment() -> dict[str, Any]:
"platform": platform.platform(),
"machine": platform.machine(),
"cpu_affinity": sorted(affinity) if affinity else None,
"pyjelly": importlib.metadata.version("pyjelly"),
"pyjelly_commit": commit,
"pyjelly_compiled_with_mypyc": compiled,
"pyjelly_max_jelly_version": MAX_VERSION,
Expand Down
20 changes: 15 additions & 5 deletions benchmarks/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
from pyjelly.integrations.generic import serialize as generic_serialize
from pyjelly.integrations.rdflib import parse as rdflib_parse
from pyjelly.integrations.rdflib import serialize as rdflib_serialize
from pyjelly.options import StreamParameters
from pyjelly.serialize.streams import SerializerOptions


class NullOutput(io.BytesIO):
Expand Down Expand Up @@ -254,12 +256,14 @@ class PyjellyFlat(Method):
Jelly with pyjelly's flat streaming API, using pyjelly's default options.

`integration` is "rdflib" for statements made of rdflib terms, or "generic"
for pyjelly's own terms.
for pyjelly's own terms. With `version`, the stream is written in that protocol
version instead of the default one, e.g. 2 for Jelly-RDF 1.1.
"""

def __init__(self, integration: str) -> None:
self.name = f"{integration}-jelly-stream"
def __init__(self, integration: str, version: int | None = None) -> None:
self.name = f"{integration}-jelly{'11' if version == 2 else ''}-stream" # noqa: PLR2004
self.generic = integration == "generic"
self.version = version

@override
def statements(self, data: BenchData) -> list[Any]:
Expand All @@ -269,10 +273,13 @@ def statements(self, data: BenchData) -> list[Any]:
def write(self, data: BenchData, out: IO[bytes]) -> None:
# The API takes a generator, so the list is wrapped in one
statements = (statement for statement in self.statements(data))
options = None
if self.version is not None:
options = SerializerOptions(params=StreamParameters(version=self.version))
if self.generic:
generic_serialize.flat_stream_to_file(statements, out)
generic_serialize.flat_stream_to_file(statements, out, options)
else:
rdflib_serialize.flat_stream_to_file(statements, out)
rdflib_serialize.flat_stream_to_file(statements, out, options)

def _parse(self, data: bytes) -> Iterable[Any]:
if self.generic:
Expand Down Expand Up @@ -305,6 +312,9 @@ def read_all(self, data: bytes, *, quads: bool) -> list[tuple[Any, ...]]:
# Jelly through pyjelly's flat streaming API
PyjellyFlat("rdflib"),
PyjellyFlat("generic"),
# The same, writing Jelly-RDF 1.1, to compare it with 1.2
PyjellyFlat("rdflib", version=2),
PyjellyFlat("generic", version=2),
)
}

Expand Down
18 changes: 13 additions & 5 deletions benchmarks/suites.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
from dataclasses import dataclass
from typing import Any

from benchmarks import data, sparql_data
from benchmarks import data
from benchmarks.methods import METHODS, round_trip
from benchmarks.sparql_methods import SPARQL_METHODS, sparql_round_trip


@dataclass(frozen=True)
Expand All @@ -33,13 +32,22 @@ class Suite:
data.load,
round_trip,
),
"sparql": Suite(
}

try:
from benchmarks import sparql_data
from benchmarks.sparql_methods import SPARQL_METHODS, sparql_round_trip
except ImportError:
# pyjelly 0.8 and older have no Jelly-SPARQL, but the rdf suite still runs on
# them, to compare them with the current version
pass
else:
SUITES["sparql"] = Suite(
"sparql",
"cells",
sparql_data.DATASETS,
sparql_data.DEFAULT_DATASETS,
SPARQL_METHODS,
sparql_data.load,
sparql_round_trip,
),
}
)
2 changes: 1 addition & 1 deletion pyjelly/serialize/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
if TYPE_CHECKING:
from pyjelly.serialize.columns import ColumnBatch

DEFAULT_FRAME_SIZE = 250
DEFAULT_FRAME_SIZE = 1024


class FrameFlow:
Expand Down
Loading