feat(core): add ScenarioFileFormat SPI for alternative file formats - #5027
feat(core): add ScenarioFileFormat SPI for alternative file formats#5027nkuehnel wants to merge 4 commits into
Conversation
Introduce a ServiceLoader-based extension point that allows contribs to provide alternative readers (e.g. protobuf, parquet) for all scenario element types without modifying core. ScenarioLoaderImpl checks for a registered provider by file extension before falling back to the built-in XML readers. Compression suffixes (.gz, .zst, .bz2) are stripped to resolve the effective format extension.
Route population writing through PopulationUtils.writePopulation() which checks the SPI registry before falling back to XML PopulationWriter. Both DumpDataAtEndImpl and PlansDumpingImpl now use this dispatch layer.
|
for context, a protobuf population reader implementation based on this architecture achieves 8-12x read speed-up and could live in the protobuf contrib (not part of this PR) |
Makes the no-extension case explicit rather than returning empty string.
|
Nice adaption! |
Either way would work for me, happy to complete it both ways |
|
I am not sure if using another injection framework is helpful. I already find this confusing if SPI is used for binding SimWrapper Dashboards (for the same reason that on the scenario level we don't have the guice injector yet). IMHO, we should rather offer a guice binding already on the scenario level. Before, I would add new file types to the existing framework and decide based on the file ending which reader/writer is used (as it is done right now). A side node: For our rust prototype, we have already defined a proto scheme https://github.com/matsim-vsp/parallel_qsim_rust/tree/main/rust_qsim/src/simulation/io/proto/types I am happy to discuss if there are any adaptations needed and where this should be located. Maybe this discussion is a good motivation to create a separate git repository for schema definitions for proto/parquet/... such that it can be used in other repositories. I have thought about this already but for now, the level of suffering wasn't high enough. |
This is basically what @jfbischoff said, and would mean linking protobuf to matsim core, do I understand right? Thanks for the proto scheme reference! Happy to work on a shared version of these, I'd have a few suggestions for further improvement. So a way forward would be to:
|
Yes.
Yes, that's what I was thinking of, so maybe a new repository inside of matsim-org, such as |
|
I would prefer SPI over Guice. If I need a guice injector just to read a scenario, it would harm the dev-experience in my opinion. Currently, we can essentially do If I understand the proposal correctly, various formats can be registered automatically using SPI, and when reading/writing, the correct format is chosen based on the file-ending. This is actually the same as Java uses for ImageIO to support various image encodings. Dependency Injection was originally designed to set one specific implementation for a required functionality. Supporting multiple implementations for something requires workarounds (in MATSim, e.g. to support multiple replanning strategies). If I want to provide a converter, reading one format and writing another format, I would probably have to provide two implementations. TL;DR: I would prefer SPI, as it is the standard Java way to do this, and I fear that with Guice existing simple code becomes more complex and convoluted. But feel free to convince me otherwise and show me how a solution with Guice could look like. |
|
TBH I'm also lacking the fantasy of how a good guice integration could look like here. We could still just link protobuf to matsim core and discriminate file reading explicitly, without any guice/spi? Maybe that is actually what @jfbischoff meant with:
|
Sure, I think this is a fair approach. However, should we use this repo for the file formats? https://github.com/matsim-org/matsim-schemas |
Summary
ScenarioFileFormatSPI (ServiceLoader-based) that allows alternative file format providers (e.g. protobuf, parquet) to be discovered at runtimeScenarioFileFormatRegistryfor extension-based provider lookupPopulationUtilswhich checks the SPI registry before falling back to built-in XML readers/writersDumpDataAtEndImplandPlansDumpingImplto usePopulationUtils.writePopulation()as the central dispatch layerMotivation
MATSim's I/O is currently hardcoded to XML. For large-scale scenarios (100k+ agents with full routes), XML parsing becomes a bottleneck. This SPI enables alternative formats to be plugged in without modifying core code — providers just need to implement
ScenarioFileFormatand register viaMETA-INF/services.Why ServiceLoader instead of Guice?
I'd like your opinion on this, happy to adapt.
@mrieser @kainagel @sebhoerl