)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":14511,"name":"Maciej Szankin","email":"maciej+review@szankin.pl","username":"mszankin"},"change_message_id":"6339f247cadc69b4481523ccef304f939f26f4d1","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Guillaume Espanel \u003cguillaume.espanel@objectif-libre.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2016-07-18 17:31:31 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Reduce time and memory usage of tenant usage."},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: Id5841c6f33247042deb88e2519503d65b52dc1dc"},{"line_number":10,"context_line":"Closes-Bug: #1481262"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"dada55a8_9c79a7ff","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":45},"updated":"2016-07-18 19:37:46.000000000","message":"Can you extend commit message with more details? Maybe some benchmarks?","commit_id":"e066869d8296d5e42e21c055a897bdad971682bc"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"d02f26569a9c409065a66049e4840985c1c80524","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"On a devstack with around 4000 instances spawned and terminated during the"},{"line_number":10,"context_line":"usage command period, this patch drops the response from ~10s to ~2s."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Memory usage is also decreased, although it\u0027s difficult to estimate with"},{"line_number":13,"context_line":"such a small sample."},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"9ad45d7e_97056712","line":11,"updated":"2016-08-11 13:37:16.000000000","message":"I\u0027d also recommend to document where this performance boost comes from, cause it took me quite a while to go over the changes in simple_tenant_usage.py before I realized that you dropped useless joins and stopped using ORM objects - both must be the main driving forces behind this improvement.","commit_id":"605ae878bc204edfd6e1fbf8d08af96d92a4de14"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"2f70f9f8d303ffb7f2d325451e181591402b6dfe","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"On a devstack with around 4000 instances spawned and terminated during the"},{"line_number":10,"context_line":"usage command period, this patch drops the response from ~10s to ~2s."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Memory usage is also decreased, although it\u0027s difficult to estimate with"},{"line_number":13,"context_line":"such a small sample."},{"line_number":14,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"9ad45d7e_d211ad05","line":11,"in_reply_to":"9ad45d7e_97056712","updated":"2016-08-11 14:08:16.000000000","message":"The ORM wasn\u0027t really the problem, but you\u0027re right about some joins (on our production, some of the query results raw were about 12KB long) and a lot of loops were used for calculation.","commit_id":"605ae878bc204edfd6e1fbf8d08af96d92a4de14"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"e0cf8f8c52569a80cf2c7b627aa88648584f1a6e","unresolved":false,"context_lines":[{"line_number":12,"context_line":"Memory usage is also decreased, although it\u0027s difficult to estimate with"},{"line_number":13,"context_line":"such a small sample."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"The improvement comes mostly from removing costly joints in the DB"},{"line_number":16,"context_line":"layer."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"Change-Id: Id5841c6f33247042deb88e2519503d65b52dc1dc"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"1a95cdbc_7404ea14","line":15,"range":{"start_line":15,"start_character":50,"end_line":15,"end_character":56},"updated":"2016-10-05 10:10:38.000000000","message":"typo: joins","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":16907,"name":"Diana Clarke","email":"diana.joan.clarke@gmail.com","username":"diana-clarke"},"change_message_id":"fcdc7ad7ba6bd535cbb4a4765aa799f2eaefaf34","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Reduce time and memory usage of tenant usage."},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"On a devstack with around 4000 instances spawned and terminated during the"},{"line_number":10,"context_line":"usage command period, this patch drops the response from ~10s to ~2s."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Memory usage is also decreased, although it\u0027s difficult to estimate with"},{"line_number":13,"context_line":"such a small sample."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"da36d5c6_2308d8d9","line":10,"range":{"start_line":9,"start_character":0,"end_line":10,"end_character":69},"updated":"2017-02-24 18:22:04.000000000","message":"Apologies for not reviewing this sooner. I do remember looking at this patch series a few months ago, and thinking that it looked good to me.\n\nWould it possible to get updated profiling stats? Before and after this patch, that is. Solid numbers on that front would make the most compelling argument for change here.\n\nIf I recall correctly, I wasn\u0027t able to reproduce the performance gains when I quickly profiled these changes back in October 2016.\n\nI could be wrong, but I think I came to the conclusion that it was the following change that made the largest difference in memory usage and response times.\n\n- Limit InstanceList join to system_metadata in os-simple-tenant-usage\n- https://review.openstack.org/#/c/129732/","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"}],"nova/api/openstack/compute/simple_tenant_usage.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"e0cf8f8c52569a80cf2c7b627aa88648584f1a6e","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"class SimpleTenantUsageController(wsgi.Controller):"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def _build_flavors_cache(self, context):"},{"line_number":45,"context_line":"        return {f.id: f for f in objects.FlavorList.get_all(context)}"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def _get_flavor_from_extradata(self, context, instance_id):"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_34498260","line":44,"updated":"2016-10-05 10:10:38.000000000","message":"nit: this method does not use self argument and could be made a @staticmethod (or a plain function)","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"e0cf8f8c52569a80cf2c7b627aa88648584f1a6e","unresolved":false,"context_lines":[{"line_number":44,"context_line":"    def _build_flavors_cache(self, context):"},{"line_number":45,"context_line":"        return {f.id: f for f in objects.FlavorList.get_all(context)}"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def _get_flavor_from_extradata(self, context, instance_id):"},{"line_number":48,"context_line":"        try:"},{"line_number":49,"context_line":"            inst \u003d objects.InstanceList.get_by_filters("},{"line_number":50,"context_line":"                context, {\u0027uuid\u0027: instance_id},"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_b473d2b0","line":47,"updated":"2016-10-05 10:10:38.000000000","message":"ditto","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"e0cf8f8c52569a80cf2c7b627aa88648584f1a6e","unresolved":false,"context_lines":[{"line_number":50,"context_line":"                context, {\u0027uuid\u0027: instance_id},"},{"line_number":51,"context_line":"                expected_attrs\u003d[\u0027flavor\u0027, \u0027system_metadata\u0027])[0]"},{"line_number":52,"context_line":"        except IndexError:"},{"line_number":53,"context_line":"            # No instance foudn with this UUID"},{"line_number":54,"context_line":"            raise exception.InstanceNotFound(instance_id)"},{"line_number":55,"context_line":"        return (inst.instance_type_id, inst.get_flavor())"},{"line_number":56,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_74a06af5","line":53,"range":{"start_line":53,"start_character":26,"end_line":53,"end_character":31},"updated":"2016-10-05 10:10:38.000000000","message":"typo: found","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"64cff7226a223ff488966a0dd65eeca466f05b3b","unresolved":false,"context_lines":[{"line_number":101,"context_line":"        normalized_period_stop \u003d timeutils.normalize_time(period_stop)"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"        for instance in instances:"},{"line_number":104,"context_line":"            (project_id, instance_id, memory_mb, root_gb,"},{"line_number":105,"context_line":"             ephemeral_gb, vcpus, launched_at, terminated_at,"},{"line_number":106,"context_line":"             vm_state, flavor_id, instance_name) \u003d instance"},{"line_number":107,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"1a6eadb0_97f02d00","line":104,"updated":"2016-12-15 09:29:47.000000000","message":"nit: as a namedtuple is returned we could probably make this easier and safer (in a sense of possible confusion of indexes) to change, if we just reference the attributes by name, e.g.:\n\n   for i in instances:\n      # do something with i.project_id, etc, etc","commit_id":"a677d5b0bde156fea21761957971a5b9f5e18fe8"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"40064377759d1d8bd9d958da4bcfd7842d87fc51","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        try:"},{"line_number":57,"context_line":"            inst \u003d objects.InstanceList.get_by_filters("},{"line_number":58,"context_line":"                context, {\u0027uuid\u0027: instance_id},"},{"line_number":59,"context_line":"                expected_attrs\u003d[\u0027flavor\u0027, \u0027system_metadata\u0027])[0]"},{"line_number":60,"context_line":"        except IndexError:"},{"line_number":61,"context_line":"            # No instance found with this UUID"},{"line_number":62,"context_line":"            raise exception.InstanceNotFound(instance_id)"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba2be162_1fd562b8","line":59,"range":{"start_line":59,"start_character":42,"end_line":59,"end_character":59},"updated":"2017-03-02 05:35:13.000000000","message":"why we need \u0027system_metadata\u0027?","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"fddd0472e716d9ca42e4385678a5e6a1628d0f2b","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        try:"},{"line_number":57,"context_line":"            inst \u003d objects.InstanceList.get_by_filters("},{"line_number":58,"context_line":"                context, {\u0027uuid\u0027: instance_id},"},{"line_number":59,"context_line":"                expected_attrs\u003d[\u0027flavor\u0027, \u0027system_metadata\u0027])[0]"},{"line_number":60,"context_line":"        except IndexError:"},{"line_number":61,"context_line":"            # No instance found with this UUID"},{"line_number":62,"context_line":"            raise exception.InstanceNotFound(instance_id)"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba2be162_69f21e71","line":59,"range":{"start_line":59,"start_character":42,"end_line":59,"end_character":59},"in_reply_to":"ba2be162_1fd562b8","updated":"2017-03-02 11:31:29.000000000","message":"I think we can get rid of it. I\u0027m note sure why I got it there in the first place.","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"40064377759d1d8bd9d958da4bcfd7842d87fc51","unresolved":false,"context_lines":[{"line_number":148,"context_line":"            flavor \u003d flavors_cache.get(flavor_id)"},{"line_number":149,"context_line":"            if not flavor:"},{"line_number":150,"context_line":"                try:"},{"line_number":151,"context_line":"                    fid, flavor \u003d self._get_flavor_from_extradata("},{"line_number":152,"context_line":"                        context, instance_id"},{"line_number":153,"context_line":"                    )"},{"line_number":154,"context_line":"                    flavors_cache[flavor_id] \u003d flavor"},{"line_number":155,"context_line":"                    flavor_name \u003d flavor.name"},{"line_number":156,"context_line":"                except exception.InstanceNotFound:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba2be162_424c6142","line":153,"range":{"start_line":151,"start_character":20,"end_line":153,"end_character":21},"updated":"2017-03-02 05:35:13.000000000","message":"Just as the proposal in https://review.openstack.org/#/c/265282/, I prefer to use the flavor from the instance_extra directly. Then we actually needn\u0027t that flavors_cache.\n\nAnd that can be done in a single sql in the line 104","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"fddd0472e716d9ca42e4385678a5e6a1628d0f2b","unresolved":false,"context_lines":[{"line_number":148,"context_line":"            flavor \u003d flavors_cache.get(flavor_id)"},{"line_number":149,"context_line":"            if not flavor:"},{"line_number":150,"context_line":"                try:"},{"line_number":151,"context_line":"                    fid, flavor \u003d self._get_flavor_from_extradata("},{"line_number":152,"context_line":"                        context, instance_id"},{"line_number":153,"context_line":"                    )"},{"line_number":154,"context_line":"                    flavors_cache[flavor_id] \u003d flavor"},{"line_number":155,"context_line":"                    flavor_name \u003d flavor.name"},{"line_number":156,"context_line":"                except exception.InstanceNotFound:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba2be162_f6c6e947","line":153,"range":{"start_line":151,"start_character":20,"end_line":153,"end_character":21},"in_reply_to":"ba2be162_424c6142","updated":"2017-03-02 11:31:29.000000000","message":"Is this going to work even with instances created before the Kilo release? It seems that all this code was there to be able to account for \"legacy\" flavors. On another note, is it worth it to fetch the extra_data for each and every instance?","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":5754,"name":"Alex Xu","email":"hejie.xu@intel.com","username":"xuhj"},"change_message_id":"ba9ec5ae0410207d15664d7d86da331beb0784ff","unresolved":false,"context_lines":[{"line_number":148,"context_line":"            flavor \u003d flavors_cache.get(flavor_id)"},{"line_number":149,"context_line":"            if not flavor:"},{"line_number":150,"context_line":"                try:"},{"line_number":151,"context_line":"                    fid, flavor \u003d self._get_flavor_from_extradata("},{"line_number":152,"context_line":"                        context, instance_id"},{"line_number":153,"context_line":"                    )"},{"line_number":154,"context_line":"                    flavors_cache[flavor_id] \u003d flavor"},{"line_number":155,"context_line":"                    flavor_name \u003d flavor.name"},{"line_number":156,"context_line":"                except exception.InstanceNotFound:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba2be162_1bc8f621","line":153,"range":{"start_line":151,"start_character":20,"end_line":153,"end_character":21},"in_reply_to":"ba2be162_f6c6e947","updated":"2017-03-02 15:02:30.000000000","message":"We force the migration https://review.openstack.org/#/c/174480/ before","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f45cdceaa308ae165937075137329128b2908e2","unresolved":false,"context_lines":[{"line_number":316,"context_line":"        tenant_usage \u003d {\u0027tenant_usage\u0027: usage}"},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"        if links:"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"            usages_links \u003d self._view_builder.get_links("},{"line_number":321,"context_line":"                req, server_usages, tenant_id\u003dtenant_id)"},{"line_number":322,"context_line":"            if usages_links:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3a461143_6c7e1bb0","line":319,"updated":"2017-01-31 12:39:46.000000000","message":"nit: unrelated change","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"}],"nova/db/api.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"0b28c85156d0cd4f2ba205a35129fb405ff12cfc","unresolved":false,"context_lines":[{"line_number":764,"context_line":""},{"line_number":765,"context_line":""},{"line_number":766,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone):"},{"line_number":767,"context_line":"    \"\"\"Get a list of tuples representing the resource usage of each instance."},{"line_number":768,"context_line":""},{"line_number":769,"context_line":"    :returns: A query for a list of tuples of the form (project_id, uuid,"},{"line_number":770,"context_line":"    memory_mb, root_gb, ephemeral_gb, vcpus, launched_at, terminated_at,"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a629dbe_a911295f","line":767,"range":{"start_line":767,"start_character":13,"end_line":767,"end_character":27},"updated":"2016-11-10 21:55:32.000000000","message":"ditto","commit_id":"cbb9271ec5fc9df599e532de9efcd1825e46b35c"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"0b28c85156d0cd4f2ba205a35129fb405ff12cfc","unresolved":false,"context_lines":[{"line_number":766,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone):"},{"line_number":767,"context_line":"    \"\"\"Get a list of tuples representing the resource usage of each instance."},{"line_number":768,"context_line":""},{"line_number":769,"context_line":"    :returns: A query for a list of tuples of the form (project_id, uuid,"},{"line_number":770,"context_line":"    memory_mb, root_gb, ephemeral_gb, vcpus, launched_at, terminated_at,"},{"line_number":771,"context_line":"    vm_state, instance_type_id, display_name)"},{"line_number":772,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"9a629dbe_c9149d4e","line":769,"range":{"start_line":769,"start_character":28,"end_line":769,"end_character":42},"updated":"2016-11-10 21:55:32.000000000","message":"ditto","commit_id":"cbb9271ec5fc9df599e532de9efcd1825e46b35c"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f45cdceaa308ae165937075137329128b2908e2","unresolved":false,"context_lines":[{"line_number":765,"context_line":""},{"line_number":766,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone,"},{"line_number":767,"context_line":"                                 limit\u003dNone, marker\u003dNone):"},{"line_number":768,"context_line":"    \"\"\"Get an iterator for a list of tuples representing the resource usage"},{"line_number":769,"context_line":"    of each instance."},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"    :returns: An iterator for a list of tuples of the form (project_id, uuid,"}],"source_content_type":"text/x-python","patch_set":9,"id":"3a461143_69dc7b46","line":768,"range":{"start_line":768,"start_character":11,"end_line":768,"end_character":21},"updated":"2017-01-31 12:39:46.000000000","message":"nit: not true anymore - just a list","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f45cdceaa308ae165937075137329128b2908e2","unresolved":false,"context_lines":[{"line_number":768,"context_line":"    \"\"\"Get an iterator for a list of tuples representing the resource usage"},{"line_number":769,"context_line":"    of each instance."},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"    :returns: An iterator for a list of tuples of the form (project_id, uuid,"},{"line_number":772,"context_line":"    memory_mb, root_gb, ephemeral_gb, vcpus, launched_at, terminated_at,"},{"line_number":773,"context_line":"    vm_state, instance_type_id, display_name)"},{"line_number":774,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3a461143_e9f06bcb","line":771,"updated":"2017-01-31 12:39:46.000000000","message":"ditto","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"}],"nova/db/sqlalchemy/api.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"d02f26569a9c409065a66049e4840985c1c80524","unresolved":false,"context_lines":[{"line_number":2493,"context_line":"@require_context"},{"line_number":2494,"context_line":"@pick_context_manager_reader_allow_async"},{"line_number":2495,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone):"},{"line_number":2496,"context_line":"    \"\"\"Return instances and joins that were active during window.\"\"\""},{"line_number":2497,"context_line":"    query \u003d context.session.query(models.Instance)"},{"line_number":2498,"context_line":""},{"line_number":2499,"context_line":"    query \u003d query.filter(or_(models.Instance.terminated_at \u003d\u003d null(),"}],"source_content_type":"text/x-python","patch_set":5,"id":"9ad45d7e_bca4d0b9","line":2496,"updated":"2016-08-11 13:37:16.000000000","message":"This no longer returns instances objects, but named tuples instead:\n\n(Pdb) result\n[(u\u0027fake\u0027, u\u0027bbe35c88-47d0-4462-95a9-952fa80f7649\u0027, 2048, 10, 3, 3, datetime.datetime(2013, 10, 10, 17, 16, 37, 156701), None, u\u0027fake\u0027, 1, u\u0027testinstance\u0027), (u\u0027fake\u0027, u\u0027eade413b-0cd8-4816-8c79-83f5761110a8\u0027, 2048, 10, 3, 3, datetime.datetime(2013, 10, 10, 17, 19, 37, 156701), None, u\u0027fake\u0027, 1, u\u0027testinstance\u0027)]\n(Pdb) result[0]\n(u\u0027fake\u0027, u\u0027bbe35c88-47d0-4462-95a9-952fa80f7649\u0027, 2048, 10, 3, 3, datetime.datetime(2013, 10, 10, 17, 16, 37, 156701), None, u\u0027fake\u0027, 1, u\u0027testinstance\u0027)\n(Pdb) type(result[0])\n\u003cclass \u0027sqlalchemy.util._collections.result\u0027\u003e\n\nwhich is good for performance and memory usage. Let\u0027s just be clear about that in the docstring and function name.","commit_id":"605ae878bc204edfd6e1fbf8d08af96d92a4de14"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"2f70f9f8d303ffb7f2d325451e181591402b6dfe","unresolved":false,"context_lines":[{"line_number":2493,"context_line":"@require_context"},{"line_number":2494,"context_line":"@pick_context_manager_reader_allow_async"},{"line_number":2495,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone):"},{"line_number":2496,"context_line":"    \"\"\"Return instances and joins that were active during window.\"\"\""},{"line_number":2497,"context_line":"    query \u003d context.session.query(models.Instance)"},{"line_number":2498,"context_line":""},{"line_number":2499,"context_line":"    query \u003d query.filter(or_(models.Instance.terminated_at \u003d\u003d null(),"}],"source_content_type":"text/x-python","patch_set":5,"id":"9ad45d7e_724ba159","line":2496,"in_reply_to":"9ad45d7e_bca4d0b9","updated":"2016-08-11 14:08:16.000000000","message":"I specified this information in nova.db.api but forgot to write it there as well.","commit_id":"605ae878bc204edfd6e1fbf8d08af96d92a4de14"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"d02f26569a9c409065a66049e4840985c1c80524","unresolved":false,"context_lines":[{"line_number":2503,"context_line":"    if project_id:"},{"line_number":2504,"context_line":"        query \u003d query.filter_by(project_id\u003dproject_id)"},{"line_number":2505,"context_line":""},{"line_number":2506,"context_line":"    return query.with_entities("},{"line_number":2507,"context_line":"        \u0027project_id\u0027, \u0027uuid\u0027, \u0027memory_mb\u0027, \u0027root_gb\u0027, \u0027ephemeral_gb\u0027, \u0027vcpus\u0027,"},{"line_number":2508,"context_line":"        models.Instance.launched_at, models.Instance.terminated_at, \u0027vm_state\u0027,"},{"line_number":2509,"context_line":"        \u0027instance_type_id\u0027, \u0027display_name\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9ad45d7e_7ce538a6","line":2506,"updated":"2016-08-11 13:37:16.000000000","message":"why not put this into session.query() in 2497?","commit_id":"605ae878bc204edfd6e1fbf8d08af96d92a4de14"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"2f70f9f8d303ffb7f2d325451e181591402b6dfe","unresolved":false,"context_lines":[{"line_number":2503,"context_line":"    if project_id:"},{"line_number":2504,"context_line":"        query \u003d query.filter_by(project_id\u003dproject_id)"},{"line_number":2505,"context_line":""},{"line_number":2506,"context_line":"    return query.with_entities("},{"line_number":2507,"context_line":"        \u0027project_id\u0027, \u0027uuid\u0027, \u0027memory_mb\u0027, \u0027root_gb\u0027, \u0027ephemeral_gb\u0027, \u0027vcpus\u0027,"},{"line_number":2508,"context_line":"        models.Instance.launched_at, models.Instance.terminated_at, \u0027vm_state\u0027,"},{"line_number":2509,"context_line":"        \u0027instance_type_id\u0027, \u0027display_name\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9ad45d7e_170b372b","line":2506,"in_reply_to":"9ad45d7e_7ce538a6","updated":"2016-08-11 14:08:16.000000000","message":"Good question... I haven\u0027t thought about it. Will try!","commit_id":"605ae878bc204edfd6e1fbf8d08af96d92a4de14"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"e0cf8f8c52569a80cf2c7b627aa88648584f1a6e","unresolved":false,"context_lines":[{"line_number":2523,"context_line":"    if project_id:"},{"line_number":2524,"context_line":"        query \u003d query.filter_by(project_id\u003dproject_id)"},{"line_number":2525,"context_line":""},{"line_number":2526,"context_line":"    return query"},{"line_number":2527,"context_line":""},{"line_number":2528,"context_line":""},{"line_number":2529,"context_line":"def _instance_get_all_query(context, project_only\u003dFalse, joins\u003dNone):"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_41680df6","line":2526,"updated":"2016-10-05 10:10:38.000000000","message":"Do you deliberately want to return a query, not a result, here to allow additional filtering? We could do:\n\n  return query.all()\n\ninstead to avoid additional list() calls later","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"edfa0a5b1e4cdbf8b1fb84557b9dfbe593d3903f","unresolved":false,"context_lines":[{"line_number":2523,"context_line":"    if project_id:"},{"line_number":2524,"context_line":"        query \u003d query.filter_by(project_id\u003dproject_id)"},{"line_number":2525,"context_line":""},{"line_number":2526,"context_line":"    return query"},{"line_number":2527,"context_line":""},{"line_number":2528,"context_line":""},{"line_number":2529,"context_line":"def _instance_get_all_query(context, project_only\u003dFalse, joins\u003dNone):"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_66fa7244","line":2526,"in_reply_to":"1a95cdbc_41680df6","updated":"2016-10-05 13:55:36.000000000","message":"I was thinking of maybe doing a yield_per. When the query is run on a significant time-frame, a large amount of row can be returned by the DB. I\u0027m however not sure yield_per would make such a big difference given that the rows are pre-buffered anyway. What do you think?","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f2739c093f754d6c2f192ff9384d0329412c96e","unresolved":false,"context_lines":[{"line_number":2523,"context_line":"    if project_id:"},{"line_number":2524,"context_line":"        query \u003d query.filter_by(project_id\u003dproject_id)"},{"line_number":2525,"context_line":""},{"line_number":2526,"context_line":"    return query"},{"line_number":2527,"context_line":""},{"line_number":2528,"context_line":""},{"line_number":2529,"context_line":"def _instance_get_all_query(context, project_only\u003dFalse, joins\u003dNone):"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_ba21c1a1","line":2526,"in_reply_to":"1a95cdbc_66fa7244","updated":"2016-10-06 09:56:02.000000000","message":"Hmm, that\u0027s an interesting idea: as we return the aggregated info on usages here, we indeed could load and process rows in batches to avoid creation of a potentially large continuous list in memory.\n\nUnfortunately, as you pointed out, most DBAPIs pre-buffer the results anyway, so that would not give us anything. At the same time, looks like PyMySQL supports server side cursors: https://github.com/PyMySQL/PyMySQL/blob/40f6a706144a9b65baa123e6d5d89d23558646ac/pymysql/cursors.py#L400 , but we would need to make SQLAlchemy aware of that, before we can use it here.\n\nThe bottom line is, let\u0027s consider yield_per() as potential memory usage optimization for the future, when the tooling supports that.\n\nI suggest we either return query.all() here or change the function name a bit to indicate a Query instance is returned, not the result.","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"0b28c85156d0cd4f2ba205a35129fb405ff12cfc","unresolved":false,"context_lines":[{"line_number":2499,"context_line":"@require_context"},{"line_number":2500,"context_line":"@pick_context_manager_reader_allow_async"},{"line_number":2501,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone):"},{"line_number":2502,"context_line":"    \"\"\"Get a list of tuples representing the resource usage of each instance."},{"line_number":2503,"context_line":""},{"line_number":2504,"context_line":"    :returns: A query for a list of tuples of the form (project_id, uuid,"},{"line_number":2505,"context_line":"    memory_mb, root_gb, ephemeral_gb, vcpus, launched_at, terminated_at,"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a629dbe_e9ea41da","line":2502,"range":{"start_line":2502,"start_character":13,"end_line":2502,"end_character":17},"updated":"2016-11-10 21:55:32.000000000","message":"nit: update this to denote the fact an iterator is returned\n\nnit: named tuples","commit_id":"cbb9271ec5fc9df599e532de9efcd1825e46b35c"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"0b28c85156d0cd4f2ba205a35129fb405ff12cfc","unresolved":false,"context_lines":[{"line_number":2501,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone):"},{"line_number":2502,"context_line":"    \"\"\"Get a list of tuples representing the resource usage of each instance."},{"line_number":2503,"context_line":""},{"line_number":2504,"context_line":"    :returns: A query for a list of tuples of the form (project_id, uuid,"},{"line_number":2505,"context_line":"    memory_mb, root_gb, ephemeral_gb, vcpus, launched_at, terminated_at,"},{"line_number":2506,"context_line":"    vm_state, instance_type_id, display_name)"},{"line_number":2507,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"9a629dbe_49ec0df3","line":2504,"range":{"start_line":2504,"start_character":28,"end_line":2504,"end_character":32},"updated":"2016-11-10 21:55:32.000000000","message":"ditto","commit_id":"cbb9271ec5fc9df599e532de9efcd1825e46b35c"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"0b28c85156d0cd4f2ba205a35129fb405ff12cfc","unresolved":false,"context_lines":[{"line_number":2523,"context_line":"    if project_id:"},{"line_number":2524,"context_line":"        query \u003d query.filter_by(project_id\u003dproject_id)"},{"line_number":2525,"context_line":""},{"line_number":2526,"context_line":"    return query.all()"},{"line_number":2527,"context_line":""},{"line_number":2528,"context_line":""},{"line_number":2529,"context_line":"def _instance_get_all_query(context, project_only\u003dFalse, joins\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a629dbe_4967adb6","line":2526,"updated":"2016-11-10 21:55:32.000000000","message":"I\u0027m sorry for changing my mind on this, but let\u0027s actually try query.yield_per(1000) here: support for server side cursors in pymysql and mysqldb was added in https://gerrit.sqlalchemy.org/#/c/225/ , so people running recent sqlalchemy versions will actually be able to use this optimization. For older versions the behavior will not change (as long as we iterate over the returned result, not treat it as a list).","commit_id":"cbb9271ec5fc9df599e532de9efcd1825e46b35c"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f45cdceaa308ae165937075137329128b2908e2","unresolved":false,"context_lines":[{"line_number":2567,"context_line":"@pick_context_manager_reader_allow_async"},{"line_number":2568,"context_line":"def instance_get_usage_by_window(context, begin, end\u003dNone, project_id\u003dNone,"},{"line_number":2569,"context_line":"                                 limit\u003dNone, marker\u003dNone):"},{"line_number":2570,"context_line":"    \"\"\"Get an iterator for a list of tuples representing the resource usage"},{"line_number":2571,"context_line":"    of each instance."},{"line_number":2572,"context_line":""},{"line_number":2573,"context_line":"    :returns: An iterator for a list of tuples of the form (project_id, uuid,"}],"source_content_type":"text/x-python","patch_set":9,"id":"3a461143_6c745bfd","line":2570,"range":{"start_line":2570,"start_character":14,"end_line":2570,"end_character":22},"updated":"2017-01-31 12:39:46.000000000","message":"nit: this is no longer true - a list is returned","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f45cdceaa308ae165937075137329128b2908e2","unresolved":false,"context_lines":[{"line_number":2570,"context_line":"    \"\"\"Get an iterator for a list of tuples representing the resource usage"},{"line_number":2571,"context_line":"    of each instance."},{"line_number":2572,"context_line":""},{"line_number":2573,"context_line":"    :returns: An iterator for a list of tuples of the form (project_id, uuid,"},{"line_number":2574,"context_line":"    memory_mb, root_gb, ephemeral_gb, vcpus, launched_at, terminated_at,"},{"line_number":2575,"context_line":"    vm_state, instance_type_id, display_name)"},{"line_number":2576,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3a461143_8c5fc774","line":2573,"updated":"2017-01-31 12:39:46.000000000","message":"ditto","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"}],"nova/tests/unit/api/openstack/compute/test_simple_tenant_usage.py":[{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"e0cf8f8c52569a80cf2c7b627aa88648584f1a6e","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        self.assertEqual(objects.Flavor, type(flavor))"},{"line_number":288,"context_line":"        self.assertEqual(FAKE_INST_TYPE[\u0027id\u0027], flavor.id)"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    def test_get_flavor_from_deleted_with_id_of_deleted(self):"},{"line_number":291,"context_line":"        # Verify the legacy behavior of instance_type_id pointing to a"},{"line_number":292,"context_line":"        # missing type being non-fatal"},{"line_number":293,"context_line":"        flavors_cache \u003d self.controller._build_flavors_cache(self.context)"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_01c28533","line":290,"updated":"2016-10-05 10:10:38.000000000","message":"nit: I wonder, if this test makes sense now, as this logic moved to another method","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":9642,"name":"Guillaume Espanel","email":"guillaume.espanel@gmail.com","username":"quatre"},"change_message_id":"edfa0a5b1e4cdbf8b1fb84557b9dfbe593d3903f","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        self.assertEqual(objects.Flavor, type(flavor))"},{"line_number":288,"context_line":"        self.assertEqual(FAKE_INST_TYPE[\u0027id\u0027], flavor.id)"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    def test_get_flavor_from_deleted_with_id_of_deleted(self):"},{"line_number":291,"context_line":"        # Verify the legacy behavior of instance_type_id pointing to a"},{"line_number":292,"context_line":"        # missing type being non-fatal"},{"line_number":293,"context_line":"        flavors_cache \u003d self.controller._build_flavors_cache(self.context)"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_5a1b8672","line":290,"in_reply_to":"1a95cdbc_01c28533","updated":"2016-10-05 13:55:36.000000000","message":"You\u0027re right. I wasn\u0027t sure it was right to remove a test, but all this does is testing that dict.get() returns None on an inexistent key.","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"6f2739c093f754d6c2f192ff9384d0329412c96e","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        self.assertEqual(objects.Flavor, type(flavor))"},{"line_number":288,"context_line":"        self.assertEqual(FAKE_INST_TYPE[\u0027id\u0027], flavor.id)"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    def test_get_flavor_from_deleted_with_id_of_deleted(self):"},{"line_number":291,"context_line":"        # Verify the legacy behavior of instance_type_id pointing to a"},{"line_number":292,"context_line":"        # missing type being non-fatal"},{"line_number":293,"context_line":"        flavors_cache \u003d self.controller._build_flavors_cache(self.context)"}],"source_content_type":"text/x-python","patch_set":6,"id":"1a95cdbc_5a17ddec","line":290,"in_reply_to":"1a95cdbc_5a1b8672","updated":"2016-10-06 09:56:02.000000000","message":"I think, you should just remove it.","commit_id":"479b7bb8b83a93fe3dbb9d7b8228a6e05c5f5b95"},{"author":{"_account_id":16907,"name":"Diana Clarke","email":"diana.joan.clarke@gmail.com","username":"diana-clarke"},"change_message_id":"2d474e3f7fe0c8e16f6ac073ec4783838492b423","unresolved":false,"context_lines":[{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"@classmethod"},{"line_number":95,"context_line":"def fake_get_active_by_window_joined(cls, context, begin, end\u003dNone,"},{"line_number":96,"context_line":"                                     project_id\u003dNone, host\u003dNone,"},{"line_number":97,"context_line":"                                     expected_attrs\u003dNone, use_slave\u003dFalse,"},{"line_number":98,"context_line":"                                     limit\u003dNone, marker\u003dNone):"},{"line_number":99,"context_line":"    return objects.InstanceList(objects\u003d["},{"line_number":100,"context_line":"        _fake_instance(START, STOP, x,"},{"line_number":101,"context_line":"                       project_id or \u0027faketenant_%s\u0027 % (x // SERVERS))"},{"line_number":102,"context_line":"        for x in range(TENANTS * SERVERS)])"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"def fake_instance_get_usage_by_window(context, begin, end, project_id,"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba2be162_48c0e6e0","line":102,"range":{"start_line":95,"start_character":0,"end_line":102,"end_character":43},"updated":"2017-03-02 14:50:31.000000000","message":"This is dead code too.","commit_id":"1b87b0ecd7df7d253dfd9325b1cfb2d1de9529dd"}]}
