qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

introspect.py output representation (was: [PATCH v2 00/11] qapi: static


From: Markus Armbruster
Subject: introspect.py output representation (was: [PATCH v2 00/11] qapi: static typing conversion, pt2)
Date: Mon, 16 Nov 2020 14:17:32 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)

Warning: losely related brain dump ahead.

introspect.py's purpose is providing query-qmp-schema with the data it
needs to built its response, which is a JSON object conforming to
['SchemaInfo'].

Stupidest solution that could possibly work: have this module generate a
C string holding the (JSON text) response.

Since a QMP command handler returns a QAPI object, not the response
string, this becomes:

     schema
        |
        |                                       qapi-gen.py
        v
    C string        --------------------------------------------------
        |
        |           qobject_from_json()
        v
     QObject                                    qmp_query_qmp_schema()
        |
        |           QObject input visitor
        v
  SchemaInfoList    --------------------------------------------------
        |
        |           QObject output visitor      generated wrapper
        v
     QObject        --------------------------------------------------
        |
        |           qobject_to_json()           QMP core
        v
    C string

Meh.  So many pointless conversions.

Shortcut: 'gen' false lets us cut out two:

     schema
        |
        |                                       qapi-gen.py
        v
    C string        --------------------------------------------------
        |
        |           qobject_from_json()         qmp_query_qmp_schema()
        v
     QObject        --------------------------------------------------
        |
        |           qobject_to_json()           QMP core
        v
    C string

Less work for handwritten qmp_query_qmp_schema(); it's now a one-liner.
This is the initial version (commit 39a1815816).

Commit 7d0f982bfb replaced the generated C string by a QLitObject:

     schema
        |
        |                                       qapi-gen.py
        v
     QLitObj        --------------------------------------------------
        |
        |           qobject_from_qlit()         qmp_query_qmp_schema()
        v
     QObject        --------------------------------------------------
        |
        |           qobject_to_json()           QMP core
        v
    C string

The commit message claims the QLitObj is "easier to deal with".  I doubt
it.  The conversion to QObject is a one-liner before and after.  Neither
form is hard to generate (example appended).

QLitObj takes more memory: ~360KiB, mostly .data (unnecessarily?),
wheras the C string is ~150KiB .text.  Of course, both are dwarved many
times over by QObject: 12.4MiB.  Gross.

However, to actually work with the introspection data in C, we'd want it
as SchemaInfoList.  I have a few uses for introspection data in mind,
and I definitely won't code them taking QObject input.

SchemaInfoList is one visitor away from QObject, so no big deal.

But what if we generated SchemaInfoList directly?  We'd have:

     schema
        |
        |                                       qapi-gen.py
        v
  SchemaInfoList    --------------------------------------------------
        |
        |           QObject output visitor      generated wrapper
        v
     QObject        --------------------------------------------------
        |
        |           qobject_to_json()           QMP core
        v
    C string

At ~480KiB, SchemaInfoList is less compact than QLitObj (let alone the C
string).  It should go entirely into .text, though.

I don't think generating SchemaInfoList would be particularly hard.
Just work.  Bigger fish to fry, I guess.  But getting the idea out can't
hurt.



Example: BlockdevOptionsFile

    { 'struct': 'BlockdevOptionsFile',
      'data': { 'filename': 'str',
                '*pr-manager': 'str',
                '*locking': 'OnOffAuto',
                '*aio': 'BlockdevAioOptions',
                '*drop-cache': {'type': 'bool',
                                'if': 'defined(CONFIG_LINUX)'},
                '*x-check-cache-dropped': 'bool' },
      'features': [ { 'name': 'dynamic-auto-read-only',
                      'if': 'defined(CONFIG_POSIX)' } ] }

Generated QLitObj:

        /* "267" = BlockdevOptionsFile */
        QLIT_QDICT(((QLitDictEntry[]) {
            { "features", QLIT_QLIST(((QLitObject[]) {
    #if defined(CONFIG_POSIX)
                QLIT_QSTR("dynamic-auto-read-only"),
    #endif /* defined(CONFIG_POSIX) */
                {}
            })), },
            { "members", QLIT_QLIST(((QLitObject[]) {
                QLIT_QDICT(((QLitDictEntry[]) {
                    { "name", QLIT_QSTR("filename"), },
                    { "type", QLIT_QSTR("str"), },
                    {}
                })),
                QLIT_QDICT(((QLitDictEntry[]) {
                    { "default", QLIT_QNULL, },
                    { "name", QLIT_QSTR("pr-manager"), },
                    { "type", QLIT_QSTR("str"), },
                    {}
                })),
                QLIT_QDICT(((QLitDictEntry[]) {
                    { "default", QLIT_QNULL, },
                    { "name", QLIT_QSTR("locking"), },
                    { "type", QLIT_QSTR("412"), },
                    {}
                })),
                QLIT_QDICT(((QLitDictEntry[]) {
                    { "default", QLIT_QNULL, },
                    { "name", QLIT_QSTR("aio"), },
                    { "type", QLIT_QSTR("413"), },
                    {}
                })),
    #if defined(CONFIG_LINUX)
                QLIT_QDICT(((QLitDictEntry[]) {
                    { "default", QLIT_QNULL, },
                    { "name", QLIT_QSTR("drop-cache"), },
                    { "type", QLIT_QSTR("bool"), },
                    {}
                })),
    #endif /* defined(CONFIG_LINUX) */
                QLIT_QDICT(((QLitDictEntry[]) {
                    { "default", QLIT_QNULL, },
                    { "name", QLIT_QSTR("x-check-cache-dropped"), },
                    { "type", QLIT_QSTR("bool"), },
                    {}
                })),
                {}
            })), },
            { "meta-type", QLIT_QSTR("object"), },
            { "name", QLIT_QSTR("267"), },
            {}
        })),

Generated C string would look like this:

        "{\"features\": ["
    #if defined(CONFIG_POSIX)
        "\"dynamic-auto-read-only\""
    #endif /* defined(CONFIG_POSIX) */
        "], "
        "\"members\": ["
        "{\"name\": \"filename\", \"type\": \"str\"}, "
        "{\"name\": \"pr-manager\", \"default\": null, \"type\": \"str\"}, "
        "{\"name\": \"locking\", \"default\": null, \"type\": \"412\"}, "
        "{\"name\": \"aio\", \"default\": null, \"type\": \"413\"}, "
    #if defined(CONFIG_LINUX)
        "{\"name\": \"drop-cache\", \"default\": null, \"type\": \"bool\"}, "
    #endif /* defined(CONFIG_LINUX) */
        "{\"name\": \"x-check-cache-dropped\", \"default\": null, \"type\": 
\"bool\"}"
        "], "
        "\"meta-type\": \"object\", "
        "\"name\": \"267\""
        "}"




reply via email to

[Prev in Thread] Current Thread [Next in Thread]