parse_redis.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. use criterion::{black_box, criterion_group, criterion_main, Criterion};
  2. use flodgatt::config;
  3. use flodgatt::request::{Content::*, Reach::*, Stream::*, Timeline};
  4. use flodgatt::response::{Event, Manager, RedisMsg, RedisParseOutput};
  5. use flodgatt::Id;
  6. use futures::{Async, Stream};
  7. use lru::LruCache;
  8. use std::convert::TryFrom;
  9. use std::fs;
  10. fn parse_long_redis_input<'a>(input: &'a str) -> RedisMsg<'a> {
  11. if let RedisParseOutput::Msg(msg) = RedisParseOutput::try_from(input).unwrap() {
  12. assert_eq!(msg.timeline_txt, "timeline:1");
  13. msg
  14. } else {
  15. panic!()
  16. }
  17. }
  18. fn parse_to_timeline(msg: RedisMsg) -> Timeline {
  19. let trimmed_tl_txt = &msg.timeline_txt["timeline:".len()..];
  20. let tl = Timeline::from_redis_text(trimmed_tl_txt, &mut LruCache::new(1000)).unwrap();
  21. assert_eq!(tl, Timeline(User(Id(1)), Federated, All));
  22. tl
  23. }
  24. fn parse_to_checked_event(msg: RedisMsg) -> Event {
  25. Event::TypeSafe(serde_json::from_str(msg.event_txt).unwrap())
  26. }
  27. fn parse_to_dyn_event(msg: RedisMsg) -> Event {
  28. Event::Dynamic(serde_json::from_str(msg.event_txt).unwrap())
  29. }
  30. fn redis_msg_to_event_string(msg: RedisMsg) -> String {
  31. msg.event_txt.to_string()
  32. }
  33. fn string_to_checked_event(event_txt: &String) -> Event {
  34. Event::TypeSafe(serde_json::from_str(event_txt).unwrap())
  35. }
  36. fn input_msg(i: usize) -> Vec<u8> {
  37. fs::read_to_string(format!("test_data/redis_input_{:03}.resp", i))
  38. .expect("test input not found")
  39. .as_bytes()
  40. .to_vec()
  41. }
  42. fn criterion_benchmark(c: &mut Criterion) {
  43. let input = ONE_MESSAGE_FOR_THE_USER_TIMLINE_FROM_REDIS;
  44. let mut group = c.benchmark_group("Parse redis RESP array");
  45. group.bench_function("parse redis input to RedisMsg", |b| {
  46. b.iter(|| black_box(parse_long_redis_input(input)))
  47. });
  48. let msg = parse_long_redis_input(input);
  49. group.bench_function("parse RedisMsg to Timeline", |b| {
  50. b.iter(|| black_box(parse_to_timeline(msg.clone())))
  51. });
  52. group.bench_function("parse RedisMsg -> CheckedEvent", |b| {
  53. b.iter(|| black_box(parse_to_checked_event(msg.clone())))
  54. });
  55. group.bench_function("parse RedisMsg -> DynamicEvent", |b| {
  56. b.iter(|| black_box(parse_to_dyn_event(msg.clone())))
  57. });
  58. group.bench_function("parse RedisMsg -> String -> CheckedEvent", |b| {
  59. b.iter(|| {
  60. let txt = black_box(redis_msg_to_event_string(msg.clone()));
  61. black_box(string_to_checked_event(&txt));
  62. })
  63. });
  64. group.bench_function("parse six messages from Redis", |b| {
  65. b.iter_batched(
  66. || {
  67. let mut manager = Manager::try_from(&config::Redis::default()).expect("bench");
  68. for i in 1..=6 {
  69. manager.redis_conn.add(&input_msg(i));
  70. }
  71. manager
  72. },
  73. |mut m| {
  74. black_box({
  75. let mut i = 1;
  76. while let Ok(Async::Ready(Some(len))) = m.redis_conn.poll_redis(m.unread_idx.1)
  77. {
  78. m.unread_idx = (0, m.unread_idx.1 + len);
  79. while let Ok(Async::Ready(Some((_tl, event)))) = m.poll() {
  80. // println!("Parsing Event #{:03}", i + 1);
  81. // assert_eq!(event, output(i));
  82. i += 1;
  83. }
  84. }
  85. assert_eq!(i, 7)
  86. })
  87. },
  88. criterion::BatchSize::SmallInput,
  89. )
  90. });
  91. }
  92. criterion_group!(benches, criterion_benchmark);
  93. criterion_main!(benches);
  94. const ONE_MESSAGE_FOR_THE_USER_TIMLINE_FROM_REDIS: &str = "*3\r\n$7\r\nmessage\r\n$10\r\ntimeline:1\r\n$3790\r\n{\"event\":\"update\",\"payload\":{\"id\":\"102775370117886890\",\"created_at\":\"2019-09-11T18:42:19.000Z\",\"in_reply_to_id\":null,\"in_reply_to_account_id\":null,\"sensitive\":false,\"spoiler_text\":\"\",\"visibility\":\"unlisted\",\"language\":\"en\",\"uri\":\"https://mastodon.host/users/federationbot/statuses/102775346916917099\",\"url\":\"https://mastodon.host/@federationbot/102775346916917099\",\"replies_count\":0,\"reblogs_count\":0,\"favourites_count\":0,\"favourited\":false,\"reblogged\":false,\"muted\":false,\"content\":\"<p>Trending tags:<br><a href=\\\"https://mastodon.host/tags/neverforget\\\" class=\\\"mention hashtag\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\">#<span>neverforget</span></a><br><a href=\\\"https://mastodon.host/tags/4styles\\\" class=\\\"mention hashtag\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\">#<span>4styles</span></a><br><a href=\\\"https://mastodon.host/tags/newpipe\\\" class=\\\"mention hashtag\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\">#<span>newpipe</span></a><br><a href=\\\"https://mastodon.host/tags/uber\\\" class=\\\"mention hashtag\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\">#<span>uber</span></a><br><a href=\\\"https://mastodon.host/tags/mercredifiction\\\" class=\\\"mention hashtag\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\">#<span>mercredifiction</span></a></p>\",\"reblog\":null,\"account\":{\"id\":\"78\",\"username\":\"federationbot\",\"acct\":\"federationbot@mastodon.host\",\"display_name\":\"Federation Bot\",\"locked\":false,\"bot\":false,\"created_at\":\"2019-09-10T15:04:25.559Z\",\"note\":\"<p>Hello, I am mastodon.host official semi bot.</p><p>Follow me if you want to have some updates on the view of the fediverse from here ( I only post unlisted ). </p><p>I also randomly boost one of my followers toot every hour !</p><p>If you don\'t feel confortable with me following you, tell me: unfollow and I\'ll do it :)</p><p>If you want me to follow you, just tell me follow ! </p><p>If you want automatic follow for new users on your instance and you are an instance admin, contact me !</p><p>Other commands are private :)</p>\",\"url\":\"https://mastodon.host/@federationbot\",\"avatar\":\"https://instance.codesections.com/system/accounts/avatars/000/000/078/original/d9e2be5398629cf8.jpeg?1568127863\",\"avatar_static\":\"https://instance.codesections.com/system/accounts/avatars/000/000/078/original/d9e2be5398629cf8.jpeg?1568127863\",\"header\":\"https://instance.codesections.com/headers/original/missing.png\",\"header_static\":\"https://instance.codesections.com/headers/original/missing.png\",\"followers_count\":16636,\"following_count\":179532,\"statuses_count\":50554,\"emojis\":[],\"fields\":[{\"name\":\"More stats\",\"value\":\"<a href=\\\"https://mastodon.host/stats.html\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\"><span class=\\\"invisible\\\">https://</span><span class=\\\"\\\">mastodon.host/stats.html</span><span class=\\\"invisible\\\"></span></a>\",\"verified_at\":null},{\"name\":\"More infos\",\"value\":\"<a href=\\\"https://mastodon.host/about/more\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\"><span class=\\\"invisible\\\">https://</span><span class=\\\"\\\">mastodon.host/about/more</span><span class=\\\"invisible\\\"></span></a>\",\"verified_at\":null},{\"name\":\"Owner/Friend\",\"value\":\"<span class=\\\"h-card\\\"><a href=\\\"https://mastodon.host/@gled\\\" class=\\\"u-url mention\\\" rel=\\\"nofollow noopener\\\" target=\\\"_blank\\\">@<span>gled</span></a></span>\",\"verified_at\":null}]},\"media_attachments\":[],\"mentions\":[],\"tags\":[{\"name\":\"4styles\",\"url\":\"https://instance.codesections.com/tags/4styles\"},{\"name\":\"neverforget\",\"url\":\"https://instance.codesections.com/tags/neverforget\"},{\"name\":\"mercredifiction\",\"url\":\"https://instance.codesections.com/tags/mercredifiction\"},{\"name\":\"uber\",\"url\":\"https://instance.codesections.com/tags/uber\"},{\"name\":\"newpipe\",\"url\":\"https://instance.codesections.com/tags/newpipe\"}],\"emojis\":[],\"card\":null,\"poll\":null},\"queued_at\":1568227693541}\r\n";