Commit Graph

20969 Commits

Author SHA1 Message Date
Steve Howell c953759486 Get unread messages from the server in the web app.
The server sends down lists of unread message ids in various
buckets, and we now use those on the client to provide more
complete counts of unread messages.
2017-09-12 06:02:40 -07:00
Steve Howell 6c90940f84 performance: Add UserMessageLite class.
This speeds up sending messages significantly.

For 1000 users, this speeds up create_user_messages from
0.652s to 0.0558s, so basically a 10x speedup.
2017-09-12 04:22:55 -07:00
Steve Howell 811fcf51ee Extract create_user_messages.
The logic to create UserMessage rows when you create a message
is very self-contained, and it's helpful to be able to profile it.
2017-09-12 04:22:55 -07:00
Steve Howell 7fbffb8e30 Optimize bulk inserts for UserMessage rows.
Avoiding ORM overhead makes inserting UserMessage rows
about 15 times faster.
2017-09-12 04:22:55 -07:00
Steve Howell d723be125a Optimize get_recipient_info() for sending messages.
This commit makes get_recipient_info() faster by never creating
Django ORM objects.  We use the ORM to create a values query
instead, and then we iterate over the rows to create various
collections of ids.

In order to avoid lots of code duplication, this commit unifies
how we query UserProfile for PMs and streams.  Prior to this
commit we were getting "wide" UserProfile objects out of
our memcached cache.  Now we just go to the database with our
list of userids.  The new approach at worst adds one hop to the
database for PMs, which aren't really a performance bottleneck
(compared to streams).  And the new approach actually saves a
hop when both partners aren't in cache (plus we don't pay the
penalty of hitting the cache itself).

The performance improvement here is easy to measure for messages
to streams with many users, even with all the other activity
that goes on inside do_send_messages().  I took test_performance()
in test_messages.py, set num_extra_users to 3000, and consistently
measured a ~20% speedup in do_send_messages().

This commit also eliminates fetching of emails.  We probably
could have done that in a prior commit, but in this commit it
is very explicit that we don't need it.  While removing email
from the query is a no-brainer, it actually had a negigible
impact on performance.  Almost all the savings here comes from
not create UserProfile objects.
2017-09-12 04:22:55 -07:00
Steve Howell d00c001b5f Create get_recipient_info().
This function returns a summary of recipient data for a message
that's being sent.  It's mostly just moving code into the
old function called get_recipient_user_profiles().
2017-09-12 04:22:55 -07:00
Steve Howell b562dedb53 Avoid using email to detect that the feedback bot is addressed.
This commit is necessary to prevent bringing back emails from the
DB for all N recipients of a message just to see if the feedback
bot is being invoked.
2017-09-12 04:22:55 -07:00
Steve Howell 6f0289ae79 do_send_messages(): Extract internal push_notify_user_ids set.
This is one more step toward not needing UserProfile objects.
2017-09-12 04:22:55 -07:00
Steve Howell 82b2bd8b65 Take user_ids in get_userids_for_missed_messages().
This helps us phase out the need for getting lots of UserProfile
objects.
2017-09-12 04:22:55 -07:00
Steve Howell 06c388774f do_send_messages(): Clean up service bot code.
We calculate `service_bot_tuples` earlier in the function, so that
we don't need "full" UserProfile objects later in the function.

This is part of consolidating code that basically just needs to
triage user_ids.
2017-09-12 04:22:55 -07:00
Steve Howell a22a22966f do_send_messages(): Create UserMessage objects with user_id.
This starts to phase out the need for UserProfile objects in
do_send_messages().  UserProfile objects are expensive to create
for large streams with lots of users.  The objects in the code
before this commit aren't even full UserProfile objects.

This change mostly sets up future performance improvements, but
we also get a minor speedup here when we run a test with 3000
stream subscribers.
2017-09-12 04:22:55 -07:00
Steve Howell ba397b5109 Use user_ids, not full objects, in render path.
There is no reason for either render_incoming_message() or
render_markdown() to require full UserProfile objects just to
triage alert words.

By only asking for user_ids, we save extra queries in two
callpaths and we make it easier to start using user_ids in
do_send_messages().
2017-09-12 04:22:55 -07:00
Steve Howell 9e8c24168d Extract get_typing_user_profiles().
This function is essentially a copy of get_recipient_user_profiles,
which is about to go away. The new function enforces the contract of
typing indicators, which is that they don't apply to streams, which
allows us to use a relatively simple approach for getting user
profile objects.

We are diverging this code, because the send-message path needs
more optimizations.
2017-09-12 04:22:55 -07:00
Steve Howell c87cc1447f Extract get_recipient_user_ids. 2017-09-12 04:22:55 -07:00
Steve Howell 56a552eec3 Get UserProfile objects directly for stream messages.
This change introduces an extra hop to the database, but it is
generally faster due to nuances of the DB and the ORM.  It
also sets us up to optimize get_recipient_user_profiles() by
avoiding creating ORM objects.

I measured the impact of this using a stream with 3000
subscribers, half of whom were idle, and it speeds things up
by 10%.
2017-09-12 04:22:55 -07:00
Steve Howell 262abe41ab Add a performance test for do_send_messages(). 2017-09-12 04:22:55 -07:00
Robert Hönig 53436d9ea7 linter: Add test case for custom_check.py
Fixes #5406.
2017-09-12 03:29:18 -07:00
Robert Hönig b5cf31efdc linter: Move custom_check_file to global namespace.
This is needed in order to mock the method when testing
`custom_check.py`. The diff for this commit is a bit broken;
all it really does is moving the method out of `build_custom_checkers`.
2017-09-12 03:24:59 -07:00
Robert Hönig 7a2234dfa2 linter: Remove redundant custom rule file delimitors. 2017-09-12 03:24:59 -07:00
Robert Hönig 2248c7ac0d linter: Add explanation for custom rule file delimitation operators. 2017-09-12 03:24:59 -07:00
Eeshan Garg e39197a9b7 requirements: Upgrade to version 0.3.4 of the Zulip API packages. 2017-09-12 03:02:29 -07:00
rht 720d5d3bf4 Update roadmap.md. 2017-09-12 03:01:43 -07:00
Sampriti Panda 073bc318cf compose: Fix rendering error with message edit forms.
Fixes #6412
2017-09-11 09:24:11 -07:00
Yusei Tahara 56cb06dc19 lightbox: Fix repeated code in exports.open.
Call display_XXX function after the payload if-clause, don't repeat
the same thing.
2017-09-10 00:40:03 -07:00
Kir Chou 0b9bd6a510 Recommend virtualbox version should be a fixed version (fixes #6448) 2017-09-10 00:38:14 -07:00
Kir Chou 7c1802c8b1 docs: Change the start directory after `vagrant ssh` from ~ to /srv/zulip . 2017-09-10 16:35:11 +09:00
Steve Howell 019d541e47 Optimize UserMessage.flags_list().
This small function was consuming way too much time when we
sent messages to many recipients.
2017-09-09 11:03:43 -07:00
Cynthia Lin b2f7c80ed2 click_handlers: Remove duplicate compose state checks. 2017-09-08 23:20:43 -07:00
Robert Hönig e65ad533d0 docs: Add guide for mocking in tests. 2017-09-08 13:18:28 -07:00
Steve Howell d3cfa1ab35 Optimize PushDeviceToken query.
Avoid a join to UserProfile here speeds up the query from
86ms -> 28ms when you analyze it with about 2000 mobile users
in a 5000-user realm.

We also avoid some code duplication here, since we filter
UserPresence for the same group of users as we filter
PushDeviceToken.
2017-09-08 12:32:17 -07:00
Steve Howell cb3832a147 Use sets, not lists, for mobile_user_ids.
This avoids an O(N-squared) hit during presence queries.  The speedup
here is probably negligible compared to everything else going on, but
sets are more semantically correct, anyway.
2017-09-08 12:32:17 -07:00
Steve Howell b6bb7f2b1e Fix bug where we hard code realm for PushDeviceToken.
This had no test coverage, which is part of the reason it went
undetected, plus many instances probably only have one realm
with realm_id=1.
2017-09-08 12:32:17 -07:00
Steve Howell 730da55bf8 Pre-fetch user ids for presence query.
Before this commit, postgres would choose a non-optimal query
plan to find all presence rows belonging to a realm.  We now
do an extra query to get the list of relevant user_ids, which allows
the next query to take advantage of UserPresence's index on
user_profile_id.

Here is the query plan for the offending query (this particular query isn't
verbatim from the code, but it's representative of the problem):

    explain analyze
    select client_id
    from zerver_userpresence
    INNER JOIN zerver_userprofile ON
        zerver_userprofile.id = zerver_userpresence.user_profile_id
    WHERE
        zerver_userprofile.is_active and
        zerver_userprofile.realm_id = 3;

     Hash Join  (cost=149.66..506.82 rows=5007 width=4) (actual time=48.834..121.215 rows=5007 loops=1)
       Hash Cond: (zerver_userprofile.id = zerver_userpresence.user_profile_id)
       ->  Seq Scan on zerver_userprofile  (cost=0.00..260.11 rows=5369 width=4) (actual time=0.009..24.322 rows=5021 loops=1)
             Filter: (is_active AND (realm_id = 3))
             Rows Removed by Filter: 3
       ->  Hash  (cost=87.07..87.07 rows=5007 width=8) (actual time=48.789..48.789 rows=5010 loops=1)
             Buckets: 1024  Batches: 1  Memory Usage: 196kB
             ->  Seq Scan on zerver_userpresence  (cost=0.00..87.07 rows=5007 width=8) (actual time=0.007..24.355 rows=5010 loops=1)
     Total runtime: 145.063 ms

You can see above that we're filtering on realm_id instead of using an index.

When you decompose the query into two queries, the total time is about 100ms, for a
savings of 33%.  I imagine the savings would be even greater on an instance with lots
of realms.  This was tested on dev with one really large realm and one tiny realm.
2017-09-08 12:32:17 -07:00
Steve Howell 6076a6a38d Remove unused is_mirror_dummy fields. 2017-09-08 12:32:17 -07:00
Steve Howell c19b3aec0c Avoid sorting in UserPresence query.
We were using `.order_by('user_profile_id', '-timestamp') in our
UserPresence query in get_status_dicts_for_query.

We don't need a full sort to produce the dictionary of statuses.
In fact the whole operation in Python is still O(N):

    - divvy rows up to be per-user in an O(N) pass
    - find max row for the 'aggregated' entry in an O(n) pass
      per user

The one minor annoyance of this fix is that datetime_to_timestamp
is lossy, so if you naively call to_presence_dict before finding
the "max" row, you get test flakes if rows are created during the
same second.  I decided to avoid calling to_presence_dict so there
are fewer moving parts, but there's still the ugly step of having
to remove the "dt" field from the final results.
2017-09-08 12:32:17 -07:00
Cynthia Lin 19e134698e compose: Refocus compose box if message view link is clicked.
Fixes #4331
2017-09-08 11:30:57 -07:00
Cynthia Lin ead2a4c071 left sidebar: Prevent closing in responsive mode.
Fixes #2913
2017-09-08 11:20:36 -07:00
Cynthia Lin 44b514d897 left sidebar: Move Streams header icons out of <a> elements. 2017-09-08 11:20:36 -07:00
Cynthia Lin 99025c8f10 search: Remove search close button when narrowed to home view.
Fixes #6426
2017-09-08 11:13:06 -07:00
Akash Nimare bf470d3d1e updated desktop app to v1.4.0 2017-09-08 07:55:25 -07:00
Brock Whittaker 26f6d708c2 Make plan CTA buttons all line up. 2017-09-07 12:43:47 -07:00
Brock Whittaker f026fc6f0c Add :hover and :active states to button.green.
This now adds these interactive states to the /plans/ page by
proxy of adding them to the `button.green` component.
2017-09-07 12:43:47 -07:00
Brock Whittaker caf98941cb Change "&" => "&amp;" HTML entity.
This is a good change for HTML encoding.
2017-09-07 12:43:47 -07:00
Brock Whittaker 8895561ae3 Uncomment "Plans & Pricing" link in the footer. 2017-09-07 12:43:47 -07:00
Brock Whittaker e82cc3f993 Add more margin-top to <h3> tag.
The <h3> default margin of 10px brought it too close vertically to the
the paragraph tag above it, so this increases it to 20px.
2017-09-07 12:40:03 -07:00
Brock Whittaker aac7b3c5eb Increase font size of <p> and <li> to 1.2em.
This increases the font size from 1em => 1.2em.
2017-09-07 12:40:03 -07:00
Brock Whittaker 26281df767 Change line height in <p> and <li>.
This decreases the <p> line height from 1.8em to 1.6em, and increases
the <li> line height from 20px to 1.6.
2017-09-07 12:40:03 -07:00
Steve Howell 642e059725 fix_unreads: Add docstring explaining migration use case. 2017-09-07 07:06:03 -07:00
Steve Howell 4dfe6bb320 Add migration to fix unread messages. 2017-09-07 07:06:03 -07:00
Steve Howell 69203c1c81 fix_unreads: Remove commit() call in fix().
The commit() call in fix() breaks migrations and tests (unless you
mock) due to outer transactions.

We now explicitly call commit() from the management command.
2017-09-07 07:06:03 -07:00