Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve JSON serialisation of strtabs #14549

Merged
merged 1 commit into from
Jun 5, 2020
Merged

Conversation

PMunch
Copy link
Contributor

@PMunch PMunch commented Jun 2, 2020

This creates a more compact serialisation of strtabs that is more in
line with the normal tables.

This creates a more compact serialisation of strtabs that is more in
line with the normal tables.
@@ -353,6 +353,14 @@ proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) {.inline.} =
assert(obj.kind == JObject)
obj.fields[key] = val

proc `%`*(table: StringTableRef): JsonNode =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be done inside strtabs itself? The module can make use of external % implementation afaik (and if it doesn't, we can make it do so)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the json module already contains the implementation for Table and OrderedTable so it just felt more at home along with them. But I don't object to moving it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it does save us from having to export the mode field :P

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but at least this field should be readable through a template anyways..

@Araq
Copy link
Member

Araq commented Jun 3, 2020

json.nim should use some concept like TableLike that strtabs fullfills.

@PMunch
Copy link
Contributor Author

PMunch commented Jun 3, 2020

Not sure that would work as strtabs still needs to store its mode..

@Araq
Copy link
Member

Araq commented Jun 4, 2020

Then maybe it should be a Serializable concept?

@PMunch
Copy link
Contributor Author

PMunch commented Jun 4, 2020

Well they are serialiseable as they are now, aren't most things serialiseable? The issue here was just that strtabs stored the internal sequence of data which meant a lot of empty fields. Just have a look at one of the old logs (warning, takes a while to load). Most of that log is just {"Field0": null, "Field1": null}.

@Araq
Copy link
Member

Araq commented Jun 4, 2020

Sure, my major gripe is a json.nim that imports all the stdlib collections, there should be a better way. At least it's better than everything depending on json though...

@alaviss
Copy link
Collaborator

alaviss commented Jun 4, 2020

Isn't just implementing all of these functions in strtabs itself will solve this issue? Or am I missing something here?

@PMunch
Copy link
Contributor Author

PMunch commented Jun 4, 2020

By that logic every module would end up depending on the JSON module, which isn't great. Is there a way to check if the importer imports another module as well?

@timotheecour
Copy link
Member

timotheecour commented Jun 5, 2020

let t = {"name": "John", "city": "Monaco"}.newStringTable
doAssert $t.toJson2 == """{"mode":"modeCaseSensitive","city":"Monaco","name":"John"}"""

@PMunch
Copy link
Contributor Author

PMunch commented Jun 5, 2020

  • A new module would still need to import everything that should have special serialisations. It is better than forcing everyone who imports the json module to also import them, but it's still not great.

  • This doesn't really work as I explained in the linked draft. The problem is that you can't have "mode" as a key in the table any longer as it would shadow the "mode" of the table itself.

Not sure how feasable it is, but I believe the best option is a pragma that conditionally checks if the importer has imported another module, and if so then define procedures that have this module available to them. This would mean the code could be moved into strtabs and look a bit something like this:

proc `%`*(table: StringTableRef): JsonNode {.withImport: json.} =
## Generic constructor for JSON data. Creates a new ``JObject JsonNode``.
  result = newJObject()
  result["mode"] = %($table.mode)
  var data = newJObject()
  for k, v in table: data[k] = %v
  result["data"] = data

@timotheecour
Copy link
Member

timotheecour commented Jun 5, 2020

This doesn't really work as I explained in the linked draft. The problem is that you can't have "mode" as a key in the table any longer as it would shadow the "mode" of the table itself.

that's now fixed see #14563 (comment) (and again, with #11992 you'd pass a single symbol instead of having to pass 3 procs)

@PMunch
Copy link
Contributor Author

PMunch commented Jun 5, 2020

Would it be possible to merge this for now so that strtabs could be serialised better, and then create an RFC where we can discuss the various ways of solving the json <-> strtabs (or more generally the serialiser <-> serialisee) relationship?

@Araq
Copy link
Member

Araq commented Jun 5, 2020

Ok.

@Araq Araq merged commit 7cb4ef2 into nim-lang:devel Jun 5, 2020
@timotheecour
Copy link
Member

timotheecour commented Jun 5, 2020

after this merge, merely importing json results in the following extra modules:

Hint: strtabs [Processing]
Hint: os [Processing]
Hint: pathnorm [Processing]
Hint: osseps [Processing]
Hint: posix [Processing]
Hint: times [Processing]

I don't think that's good, given that os and times are in particular heavy dependencies.
Especially when I showed there was an alternative way #14563

json should be light and unrelated to any OS specific stuff, but is now a kitchen sink of dependencies; here's the total imports for import json:

Hint: system [Processing]
Hint: widestrs [Processing]
Hint: io [Processing]
Hint: t10888 [Processing]
Hint: json [Processing]
Hint: hashes [Processing]
Hint: tables [Processing]
Hint: math [Processing]
Hint: bitops [Processing]
Hint: macros [Processing]
Hint: algorithm [Processing]
Hint: strtabs [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: unicode [Processing]
Hint: os [Processing]
Hint: pathnorm [Processing]
Hint: osseps [Processing]
Hint: posix [Processing]
Hint: times [Processing]
Hint: options [Processing]
Hint: typetraits [Processing]
Hint: lexbase [Processing]
Hint: streams [Processing]
Hint: parsejson [Processing]

@ghost
Copy link

ghost commented Jun 5, 2020

@timotheecour but we have dead code elimination anyway, so I don't see it being that bad

@PMunch
Copy link
Contributor Author

PMunch commented Jun 5, 2020

Yes, the extra imports are bad, no-one is arguing the opposite (except Yardanico it seems :P). But this should be discussed elsewhere and implemented properly, however this has little bearing on strtabs in particular.

One reason it's bad: if you want to bundle NimScript into your program and want to create a custom stdlib you'd have to rip things out of files in order to bring the size down. It's a small use-case, but in general I think it would be a good idea to keep the interconnectedness of libraries to a minimum.

timotheecour added a commit to timotheecour/Nim that referenced this pull request Jun 6, 2020
@disruptek
Copy link
Contributor

See what you think of my approach here: https://github.com/disruptek/jason

@timotheecour
Copy link
Member

timotheecour commented Jun 6, 2020

@Yardanico

@timotheecour but we have dead code elimination anyway, so I don't see it being that bad

it still needs to be parsed and is not cheap, eg look at this: #14179
simply adding dependency on os (without using any symbols) yields a 30x slowdown in that case

and it can lead to cyclic dependency issues

timotheecour added a commit to timotheecour/Nim that referenced this pull request Jun 6, 2020
timotheecour added a commit to timotheecour/Nim that referenced this pull request Jun 7, 2020
Araq pushed a commit that referenced this pull request Jun 8, 2020
…ependency on strtabs thanks to a hooking mechanism (#14563)

* json custom serialization; application for strtabs
* serialize using nesting
* make toJson more feature complete
* add since
* Revert "Improve JSON serialisation of strtabs (#14549)"

This reverts commit 7cb4ef2.

* better approach via mixin
* toJson, jsonTo
* fix test
* address comments
* move to jsonutils
* doc
* cleanups
* also test for js
* also test for vm
@timotheecour timotheecour mentioned this pull request Dec 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants