Summarized using AI

Your API is Too Slow!

Grzegorz Witek • June 23, 2016 • Singapore • Talk

In this talk titled 'Your API is Too Slow!', Grzegorz Witek, a Lead Software Engineer at Kaligo, addresses common misconceptions about API performance. He begins by asserting that many developers are overly concerned with speed, often overlooking that users are accustomed to slower loading times on various websites. Witek emphasizes that unless speed is a core feature of your product, it may not be as critical as perceived.

Key Points Discussed:
- Understanding API Necessity of Speed:
- Not all APIs need to be lightning-fast; user expectations vary across applications.
- Examples such as GitHub highlight that speed is not always a primary selection criterion for users.
- Products like Algolia thrive on speed and user expectations are higher.

  • Assessing Pains Related to Speed:

    • Developers should determine if speed is a feature or a bug based on client requirements and user needs.
    • It's crucial to benchmark and profile APIs correctly to ensure improvements target slow areas effectively.
  • Optimizing API Performance:

    • Utilize Content Delivery Networks (CDNs) to minimize latency for distant users.
    • Diversify server locations for applications with international audiences to balance loads and improve response times.
  • Database Optimization:

    • Relate to your database efficiently and leverage its capabilities instead of relying solely on caching mechanisms.
    • Consider moving processing to background jobs to enhance user experience by providing quicker response times.
  • Using Proper Tools and Techniques:

    • Profile applications using tools like Ruby Prof and Rack Mini Profiler to identify performance bottlenecks accurately.
    • Upgrade libraries regularly to benefit from micro-optimizations and ensure optimal performance.
    • Employ multi-layered caching strategies to maximize cache hit ratios across different user requests.
  • Conclusion and Final Thoughts:

    • Witek concludes that while speed optimizations are important, rewriting an application is a last resort unless absolutely necessary. Developers should focus on incrementally improving performance by assessing the slowest parts of their applications. The message reinforces that many Ruby applications can efficiently process half a million requests per minute without urgent need for rewrites, as long as proper optimization techniques are applied.

Your API is Too Slow!
Grzegorz Witek • June 23, 2016 • Singapore • Talk

Speaker: Grzegorz Witek, Lead Software Engineer, Kaligo

While premature optimization might be the root of all evil, at some point, whether you want it or not, you must look at your beautiful (and of course fully tested) code, and make it a bit less pretty, but much, much faster. API performance optimization does not need to be scary, though. To start you just need some benchmarking tools and a few optimization techniques. In my talk I'm going to present example problems and solutions that will make speeding up API much easier.

Speaker's Bio
I boost economy by making bugs here and there, so that others always have something to fix and they can keep their jobs. Constantly afraid of stack overflows, I work as an empty-stack developer.

Event Page: http://www.reddotrubyconf.com/

Produced by Engineers.SG

Help us caption & translate this video!

http://amara.org/v/ONq0/

Red Dot Ruby Conference 2016

00:00:14.000 hi everyone I came here today to you
00:00:16.640 from a place far far
00:00:18.800 away it's called gayang and I literally
00:00:21.840 had to travel through half of the
00:00:23.400 country 30 minutes by taxi because of
00:00:25.920 the traffic and I came here to tell you
00:00:29.759 that your API is too slow and I want to
00:00:34.640 give you this one weird trick that will
00:00:37.960 change everything and make your API
00:00:39.960 super
00:00:41.039 fast careful this is the trick your API
00:00:44.840 is already fast enough now this might
00:00:48.440 sound like a joke but I really mean it I
00:00:52.480 feel that as developers we're very often
00:00:55.840 so uh so careful about speed of our
00:00:59.440 application
00:01:00.680 that we miss the fact that out there in
00:01:04.600 the world there our users who do not
00:01:07.200 really care about it so much I mean
00:01:09.799 there are people who open the Bloomberg
00:01:12.080 or Forbes page that takes like 20
00:01:14.479 megabytes and a minute or more to load
00:01:17.360 and they still read the articles there
00:01:19.000 right so if your API renders some result
00:01:22.360 within 300 milliseconds like come on
00:01:25.079 it's not even a second and people wait
00:01:26.799 minutes to load to load websites so this
00:01:30.320 is my real message to you that your API
00:01:32.399 is probably already fast enough but who
00:01:34.759 would accept a presentation with such
00:01:36.240 thatle you know I needed to work on
00:01:38.720 marketing my name is gregorek I work for
00:01:41.640 a company called cigo where we're
00:01:43.240 building a hotel booking platform I'm
00:01:45.560 responsible for building API that powers
00:01:48.200 some websites and Powers mobile
00:01:50.360 application before I spent quite some
00:01:52.840 time working for company called fiber
00:01:55.719 where we had also a web API that was
00:01:58.719 built in Ruby and we scaled it up to
00:02:01.200 around half a million requests per
00:02:03.000 minute so when I think about speeding up
00:02:06.119 apis I always ask myself if speed is a
00:02:10.959 feature and if not then if lack of speed
00:02:16.200 is a
00:02:17.560 bug so you might thinking that one
00:02:21.440 excludes another but in my opinion it's
00:02:25.599 the the truth is somewhere in the middle
00:02:27.680 so depending on your product depending
00:02:30.080 on how you promote your application
00:02:32.480 speed might be a feature and if your
00:02:36.160 application is extremely slow it might
00:02:37.920 be considered a bug if you work for a
00:02:40.519 clients that deliver you the functional
00:02:42.640 and nonfunctional requirements often in
00:02:45.239 the letter ones you will see that the
00:02:48.519 application must respond within certain
00:02:50.800 amount of time and then of course if
00:02:52.920 your application is slower then it's a
00:02:54.920 bug right it doesn't fulfill the
00:02:56.959 requirement that you got from your
00:02:58.319 client
00:03:00.400 and let's consider two different
00:03:02.720 products here first is GitHub I use
00:03:05.720 GitHub API on daily basis and it's fast
00:03:10.040 and even if it was way slower like four
00:03:12.879 or five times slower I would still be
00:03:15.000 using GitHub because the speed is not
00:03:17.760 something that made me choose that
00:03:20.560 product over the competitors GitHub
00:03:22.879 doesn't say hey choose us over over
00:03:25.200 other applications because we are fast
00:03:27.400 no their features the stuff that they
00:03:29.840 deliver uh is something else is there
00:03:32.959 there are different qualities of their
00:03:34.439 product that may me choose them over
00:03:36.640 over other applications on the other
00:03:39.000 hand we've got algolia which is a search
00:03:43.120 as a service they've got API that takes
00:03:45.959 your data and returns results uh as you
00:03:49.159 type we use it for example for uh
00:03:51.480 autocomplete for the destinations so as
00:03:54.239 soon as I type n it shows me New York
00:03:57.040 New Delhi and other cities on my website
00:03:59.799 and algolia promotes themselves as an
00:04:02.720 application that delivers results
00:04:04.599 instantly so if their API was twice
00:04:07.760 slower I would probably choose another
00:04:10.239 application that that offers the same
00:04:12.560 functionality but is faster so whenever
00:04:15.519 you think about speed of your API the
00:04:17.680 speed of your web application you need
00:04:19.759 to think what is the strength of my
00:04:21.919 product am I more like agolia do I
00:04:24.840 promote the speed of my application and
00:04:27.280 if yes then you should definitely focus
00:04:29.440 on on delivering results as quickly as
00:04:32.280 possible but if there are more strengths
00:04:34.479 there are other strengths of your
00:04:35.560 application and speed is not something
00:04:38.160 that you want to promote to your users
00:04:40.400 then then maybe you should focus on
00:04:42.280 bunch of other things now let's assume
00:04:45.039 that you really have a problem with the
00:04:47.160 speed and that your users complain your
00:04:50.000 boss hates you nobody's using your
00:04:52.320 product because it's so slow so then if
00:04:54.759 you have a web application there's many
00:04:57.160 many topics that you uh that you should
00:05:00.120 think about there's many layers of
00:05:02.520 optimizing web application very often
00:05:05.280 these are totally independent layers and
00:05:07.440 this is such a broad topic that today
00:05:09.639 instead of talking about everything I
00:05:11.560 will just focus about optimizing API so
00:05:14.720 we'll not be talking about JavaScript
00:05:16.400 static content Etc just the stuff that
00:05:19.240 relates to your AP that is related to
00:05:21.960 rendering Json or or XML by your by your
00:05:25.759 web
00:05:28.199 server whenever user uses the device to
00:05:32.160 make a request to your application this
00:05:35.319 request goes a long long way okay maybe
00:05:38.639 not always if you reach a certain
00:05:40.840 website that is hosted here in Singapore
00:05:42.639 this way will be just a few kilometers
00:05:44.440 right but if you for example pin GitHub
00:05:47.560 that has a server in United States then
00:05:49.639 it's a couple of thousand kilometers
00:05:51.560 that the requests must go there and back
00:05:54.800 and if we were able to achieve the full
00:05:58.199 speed of light we with our requests and
00:06:01.039 and packages then this request within
00:06:04.880 one second would be able to go around
00:06:07.039 the a like seven or eight times but of
00:06:10.240 course we are not able to do that first
00:06:12.880 because we do not live in a vacuum so
00:06:15.080 the speed of light the speed of internet
00:06:16.960 is way slower and the second thing is
00:06:19.880 that we can't directly hit the server
00:06:22.800 somewhere in the other part of the world
00:06:24.680 we have to go through many many devices
00:06:27.039 that slow down this request until we
00:06:29.759 reach the server so whenever you think
00:06:34.639 about speeding up your application
00:06:37.120 speeding up your web API you need to
00:06:39.520 think where are my users because if your
00:06:43.000 server if your database is in Singapore
00:06:45.199 and your users are right close from here
00:06:48.000 in Jakarta then the latency will be
00:06:50.599 around 10 to 20 milliseconds but if you
00:06:53.919 go further to Vietnam this will go up to
00:06:56.639 100 New York 260 milliseconds just for a
00:07:01.440 pink just for a small tiny package to
00:07:04.599 hit the server in New York and go back
00:07:06.919 is 200 milliseconds so even if your API
00:07:10.000 if your application will render results
00:07:12.560 within 10 milliseconds user will have to
00:07:14.800 wait way way more uh until until we'll
00:07:18.759 see the
00:07:19.879 result then if you have for example uh
00:07:23.840 customers in Shanghai in China this gets
00:07:26.080 even worse because of their internet
00:07:28.400 infrastructure and the great firewall
00:07:30.160 that slows down all the traffic uh going
00:07:33.599 out of the country and coming uh coming
00:07:36.440 from another countries so the first
00:07:39.720 thing that you should do if you have
00:07:42.160 users out of your country if you have
00:07:44.520 users far away is to put your
00:07:46.680 application behind the CDN
00:07:48.680 infrastructure initially the CDN were
00:07:52.199 designed and are still considered a
00:07:55.520 solution to serve static content but
00:07:57.960 this is not the only case where the
00:07:59.599 useful so CDN is not only the server
00:08:02.720 that is closer to your user that will
00:08:04.440 store your Javascript file and render it
00:08:06.560 faster cdns actually have a powerful big
00:08:10.159 infrastructure that will allow you to
00:08:13.199 that will help you to serve even Dynamic
00:08:15.520 content faster for example when user
00:08:19.440 makes a request and this request instead
00:08:21.840 of trying to reach your server goes
00:08:24.560 first to the C the closest CDN endpoint
00:08:28.360 then the traffic between one endpoint of
00:08:30.560 that CDN and another endpoint that is
00:08:32.880 closest to your server will be way
00:08:34.919 faster than if it go through normal
00:08:37.360 route that's because the routes between
00:08:39.959 the end points of that of that
00:08:42.240 infrastructure are are improved are
00:08:45.120 optimized what's more certain CDM
00:08:48.080 providers uh work on special protocols
00:08:51.880 to move the data between their endpoints
00:08:54.399 so sometimes they make just a plain HTTP
00:08:57.440 request between one endpoint and another
00:08:59.480 but certain companies uh work on binary
00:09:02.120 protocols that that allow to this
00:09:04.920 requests to go way way
00:09:06.920 faster another thing that will make it
00:09:10.760 uh that allows to take advantage the CDN
00:09:13.880 is http2 so this is a new protocol uh
00:09:17.560 like new version of the protocol that we
00:09:19.160 already know and while we can't fully
00:09:22.360 take advantage of what http2 offers us
00:09:25.800 because of the limitations of the
00:09:27.760 software that we use uh the the user the
00:09:31.000 user's browser probably uh allows the
00:09:33.839 usage of http2 and the CDN
00:09:36.560 infrastructure also allows it so the
00:09:39.000 traffic between the user's device and
00:09:41.480 the last end point of CDN the one last
00:09:44.480 step between your server will be will be
00:09:46.880 going through hp2 so it will allow uh it
00:09:50.519 will allow uh users to to get that
00:09:53.760 faster now the next thing after putting
00:09:57.519 your application behind CDN
00:10:00.320 is thinking about where your servers are
00:10:04.040 because even if you have CDN but your
00:10:06.600 server is in Singapore and your users
00:10:08.560 are let's say in Saudi Arabia this is
00:10:10.760 quite a distance to go through so you
00:10:13.760 might consider instead of having one
00:10:15.800 server and one database using multiple
00:10:19.040 copies all over the world this is quite
00:10:21.519 a trick tricky topic because you need to
00:10:24.440 decide if your application is read heavy
00:10:26.720 or is it right heavy if your application
00:10:29.760 uh if you mostly are reading from
00:10:31.360 database then it's quite easy because
00:10:33.320 you have you can have multiple read only
00:10:35.760 replicas of your database spread all all
00:10:38.480 around the world however if your
00:10:40.920 application is Right heavy then you need
00:10:42.839 to somehow synchronize these databases
00:10:44.959 and then you're going to quite a rocky
00:10:47.440 area where you may have issues with
00:10:49.880 synchronization of data anyway if your
00:10:53.040 application is read heavy then you
00:10:55.399 should certainly consider putting your
00:10:58.279 application servers and a copy of
00:11:00.160 databases in various endpoints that will
00:11:02.480 be closer to
00:11:05.240 user the second
00:11:07.320 step after reaching your server is
00:11:10.279 obviously waiting for the result it
00:11:13.440 boils down to speeding up your Ruby
00:11:16.480 application and there's many
00:11:18.480 presentations there's many books about
00:11:21.880 how to speed up your Ruby application
00:11:24.320 how to speed up your Ruby code and the
00:11:27.560 very very first rule that I have here is
00:11:30.720 not to be a
00:11:31.920 smartass I used to be a smartass and it
00:11:36.079 costed me a lot of time because whenever
00:11:38.760 my application was slow I was like oh
00:11:40.920 yes sure we sure we should cash it and
00:11:43.800 of course sometimes it helped maybe in
00:11:46.000 50% of examples but in the other half I
00:11:50.320 cached the the content and I deployed it
00:11:53.120 to production and I saw maybe 3% of
00:11:55.880 improvement and obviously my boss wasn't
00:11:58.760 happy when after a couple of days of
00:12:00.360 work he so 3% of improvement that's not
00:12:02.360 what you expect so the first thing to do
00:12:06.760 whenever you want to speed up something
00:12:08.680 is to determine what is slow you
00:12:11.040 shouldn't focus on the part that the
00:12:13.120 parts that are already fast because well
00:12:15.800 they're already fast just focus on the
00:12:17.800 slowest part of your
00:12:19.399 application so to measure the
00:12:21.720 performance of your application you can
00:12:23.760 use uh many tools the gems that I'm
00:12:27.040 wrote here are Ruby Prof and Rak Mini
00:12:29.199 profiler both of them will allow you to
00:12:31.920 see which exact line which exact method
00:12:35.440 takes more time than others or which
00:12:37.959 method is called many many times so that
00:12:40.760 you can you can notice that it takes too
00:12:43.560 much time it's called too many times it
00:12:45.480 becomes a problem so the problem might
00:12:48.079 be database and in some cases will be
00:12:51.000 but it's not always uh it's not always
00:12:54.160 true whenever you measure your
00:12:56.680 application you should do it in
00:12:58.480 production mode
00:12:59.800 this is obvious but sometimes I see
00:13:02.079 people forgetting about it and they see
00:13:04.279 that oh my application spends like 90%
00:13:06.959 of time on reloading classes or
00:13:09.040 compiling assets how does it happen well
00:13:11.560 of course in production mode it will not
00:13:13.279 happen it will happen only when you
00:13:15.279 start your application so you should
00:13:17.440 always test it in production mode and
00:13:19.800 for that I suggest something called
00:13:21.320 pre-production or beta stage this is
00:13:23.800 basically copy of your production
00:13:26.120 environment uh that is not available to
00:13:28.920 you users that uses these gems and
00:13:32.440 preferably if it's possible it should
00:13:34.639 use read only replica of your of your
00:13:36.680 production database because well the
00:13:39.079 time that your application spends on
00:13:40.880 loading 10 users that you have in your
00:13:42.600 local database and a couple of thousands
00:13:45.720 users that you have in production
00:13:47.000 database will be definitely very
00:13:48.839 different one of these two gems a rack
00:13:51.399 mini profiler is actually meant also to
00:13:53.639 be used in in the real production
00:13:56.160 environment but nevertheless I recommend
00:13:58.480 you to use this pre-production stage
00:14:01.360 except for these two gems you've got a
00:14:03.279 bunch of external tools uh both New
00:14:05.680 Relic and Skylight are commercial
00:14:08.519 products that have some free plans so
00:14:11.120 you can use them and what they do is
00:14:13.600 that you install a gem that will that
00:14:16.720 will analyze your running application
00:14:18.880 will send this information to their
00:14:20.199 servers and then you've got nice web
00:14:21.839 applications to that will allow you to
00:14:24.560 learn something about your application
00:14:27.639 and then it does not work uh only on a
00:14:30.839 single request but obviously uh all over
00:14:33.800 the time that your application is
00:14:35.079 running so thanks to that you can see
00:14:38.160 not only how much time your application
00:14:40.560 spends on certain p uh on certain part
00:14:43.240 of code in a single request but for all
00:14:45.920 the
00:14:46.560 users and the nice thing about the about
00:14:49.320 these applications is that they allow
00:14:51.639 you to see not only the average time but
00:14:54.639 also the 75th or 95th percentiles
00:14:58.480 average is a terrible measure that
00:15:01.120 people
00:15:02.440 overuse if my brother is a millionaire
00:15:05.360 and I am broke on average we're both
00:15:07.600 very rich but well I do not really
00:15:11.199 experience the same as my brother so if
00:15:13.440 one of your users see the result in 10
00:15:15.519 milliseconds and the other in 500 well
00:15:18.519 the average is 250 milliseconds that's
00:15:20.639 nothing right but one of your users is
00:15:22.639 very happy and the other is frustrated
00:15:25.279 therefore you should use these
00:15:26.480 applications and you should focus on the
00:15:28.240 75th or 95th
00:15:31.279 percentiles now when you measure
00:15:33.720 something first you need to profile
00:15:37.199 which means that you need to determine
00:15:39.639 what is the slowest part of your
00:15:41.000 application and focus on it and then you
00:15:44.000 Benchmark which means that you compare
00:15:46.000 alternative
00:15:47.560 Solutions first profile then Benchmark
00:15:50.959 do not do not Benchmark things that
00:15:53.040 don't matter and uh these two things are
00:15:57.000 not exclusive they are just one after
00:15:59.079 another and that's that's how you should
00:16:01.399 do
00:16:03.360 that now when you measure and when you
00:16:06.040 determine what is the slowest part of
00:16:07.720 your application you should start
00:16:09.759 improving and the first thing that I
00:16:13.360 always do and that I think that people
00:16:17.120 say quite the opposite is to rely on
00:16:19.600 your
00:16:21.160 database whenever someone says that we
00:16:24.160 need to speed up our application we
00:16:26.279 start by thinking about caching because
00:16:28.959 because in many cases the time spent in
00:16:31.720 database is very significant but I
00:16:34.959 believe that we learned to treat
00:16:38.079 database as a big black box that we just
00:16:40.560 throw stuff in and take it out while
00:16:42.759 databases are really powerful systems
00:16:45.720 they have many functions that can
00:16:48.199 aggregate the data they can analyze
00:16:50.279 process the data and instead of just
00:16:52.360 fetching everything we have in database
00:16:54.480 and processing it in our Ruby
00:16:55.839 application we can just use databases
00:17:00.079 I think that the problem is that we are
00:17:02.440 so used to using ORS like SQL or active
00:17:05.160 record these tools teach us to write
00:17:09.240 Ruby syntax and to fetch just simply
00:17:12.360 fetch the data instead of writing cql
00:17:15.720 that allows us to to fully use all the
00:17:19.280 database features so ORS do not offer
00:17:21.959 you everything that the database offers
00:17:23.799 you just because ORS usually try to
00:17:26.480 cover uh a try to support as many
00:17:30.080 databases as possible so very often they
00:17:32.600 only support these functions that are
00:17:34.559 common for multiple
00:17:36.080 databases a couple of weeks ago here in
00:17:38.679 Singapore on the Ruby Meetup we had a
00:17:41.080 developer talking about the cubes
00:17:42.679 functionality in postgress database this
00:17:45.120 is not supported by anym but this is
00:17:47.520 functionality that allows you to
00:17:48.880 aggregate your data in database over
00:17:50.760 multiple Dimensions at the same time and
00:17:53.880 this is something new this is something
00:17:55.440 that probably we will not see supported
00:17:57.520 in any orms but if you learn you if you
00:18:00.559 learn some SQL then you can take
00:18:02.720 advantage of it already right
00:18:04.960 now when I was at University I had like
00:18:08.080 two semesters of the Oracle database
00:18:11.159 course and after that after these two
00:18:13.600 semesters my professor told me that hey
00:18:15.840 so now you know the basics so now you
00:18:17.840 can go and learn yourself something more
00:18:20.559 of course I never learned more of Oracle
00:18:22.720 databases database later but I learned
00:18:25.799 during this time that I can write the
00:18:28.000 whole application
00:18:29.520 using just Oracle so it's not only a
00:18:32.400 tool to store data but databases are
00:18:35.640 really powerful applications it's really
00:18:37.600 powerful software and you should not be
00:18:40.760 afraid of that you should just learn
00:18:42.360 some SQL and you should trust and rely
00:18:44.840 on your
00:18:47.039 database of course at some point you
00:18:49.159 will be forced or you will want to use
00:18:50.960 the cache and then you need to consider
00:18:54.919 where to put that cache it might be a
00:18:57.240 weird question but
00:18:59.600 you might keep it on a separate machine
00:19:01.679 so you might store some information in
00:19:03.480 red on a separate server in the same
00:19:05.919 network which will be fast then you
00:19:08.520 might have red on the same machine and
00:19:10.919 obviously it will be faster because
00:19:12.400 we're removing this period of time that
00:19:14.960 is needed for transferring data from one
00:19:17.400 machine to the other and the third
00:19:19.960 option is to store uh information in
00:19:23.080 your application memory of course if I
00:19:25.840 say that the application memory is the
00:19:27.480 fastest why not or everything there
00:19:29.679 right well each piece of memory that you
00:19:33.640 use for the cache is the memory that you
00:19:36.240 cannot use for your server to be running
00:19:38.919 and we all know that Ruby applications
00:19:41.039 are pretty hungry when it comes to the
00:19:42.799 memory right the simple race application
00:19:45.559 run on unicorn can consume around 4 to
00:19:49.960 500 megabytes so you need to consider
00:19:54.360 you need to consider this tradeoff like
00:19:56.559 do I want to spend my memory
00:19:59.159 on another service or another server
00:20:01.600 worker or on a cache what I usually do
00:20:05.280 is combine the third and first approach
00:20:08.280 so whatever data is accessed almost
00:20:12.400 every single request and doesn't change
00:20:14.320 often I try to keep in application
00:20:16.200 memory but whatever doesn't fall in that
00:20:19.080 category I move to separate machine on
00:20:21.400 red CU you need to remember that even
00:20:25.000 though everyone uh keeps repeating that
00:20:27.760 memory is cheap
00:20:29.200 cheap doesn't mean that it's
00:20:31.760 free the next thing about cash is using
00:20:34.520 multi-layered cach so whenever user
00:20:37.720 reaches your server you try to increase
00:20:40.000 your cash hit ratio so you want your
00:20:42.280 user to take advantage of this cach and
00:20:46.039 sometimes different pieces of
00:20:48.000 information are a bit different for each
00:20:50.159 user for example at caligo we store a
00:20:53.640 static information about hotels so some
00:20:56.600 of this information is the same for each
00:20:58.280 user like the hotel rating or how good
00:21:01.000 is the Wi-Fi or how tasty was the
00:21:03.320 breakfast in terms of in terms of some
00:21:05.320 scale from 1 to 5 this is the same for
00:21:07.720 each user but then we've got description
00:21:09.799 of the hotel which is in text and will
00:21:12.200 be different for user in Russia and user
00:21:14.559 in Singapore just because it will be
00:21:16.039 written in different language for that
00:21:18.200 case we use this Russ doll or
00:21:20.240 multi-layered Cache where all the users
00:21:23.279 will take advantage of this common cache
00:21:26.039 the information that is common for all
00:21:27.559 of them and they will not take advantage
00:21:30.960 of the other part because it will be in
00:21:33.360 the different
00:21:36.880 languages the next part is what I really
00:21:39.720 hate to say because I'm a huge fan of
00:21:43.039 functional programming I use erlang and
00:21:45.480 elixir on daily basis I really enjoyed
00:21:48.080 writing husk and prolog at
00:21:50.000 University and all these languages are
00:21:52.240 functional and do not allow you to
00:21:55.480 mutate data and Ruby allows you to do
00:21:58.240 that
00:22:00.080 and you should do it pretty often that's
00:22:02.960 because Ruby even though Ruby allows you
00:22:05.279 to write functional code it's not really
00:22:08.320 optimized for that so imagine that you
00:22:10.360 have a hash with thousand elements and
00:22:12.600 now you want to add one element to that
00:22:14.559 hash if you do uh hash do merge and then
00:22:18.440 put that one other element what will
00:22:20.520 happen is that Ruby will copy the whole
00:22:23.520 element the whole thousands keys to
00:22:26.720 another structure to another part uh
00:22:28.640 address in the memory and then add this
00:22:30.679 one piece there which means that it is
00:22:33.360 very expensive operation if you work on
00:22:35.360 big data structures purely functional
00:22:37.919 languages languages that do not allow
00:22:39.679 you to uh to mutate your data they will
00:22:42.720 just create a new piece uh with one
00:22:45.480 element and a reference to that old
00:22:47.919 address in memory that's because that
00:22:49.919 address that data is immutable so it
00:22:52.240 will never
00:22:53.400 change and using merge with exclamation
00:22:56.400 mark instead of merge can be T fast T
00:23:00.520 time faster or if if your data is really
00:23:03.039 huge then can be even hundreds times
00:23:04.760 faster so I really hate to say that but
00:23:07.559 when you need you should mutate your
00:23:10.240 data it is risky and you should be
00:23:12.120 careful about it but in in many cases it
00:23:15.880 will help you to save off a lot of
00:23:18.559 time now this is pretty cheap technique
00:23:21.320 but people often forget about it
00:23:23.679 upgrading your libraries even between
00:23:26.640 some minor or tiny releases can have a
00:23:29.400 big impact of your performance that's
00:23:32.240 because when developers release a new
00:23:33.840 version of Library they increase their
00:23:36.200 minor or major version Whenever there is
00:23:38.320 some new big feature or something that
00:23:40.120 breaks the compatibility but between the
00:23:42.440 big features there is a lot of work
00:23:44.720 happening in open source just on this
00:23:47.039 level of the micro optimizations and a
00:23:49.159 bunch of them can sum up to pretty big
00:23:51.480 difference for example we sometimes
00:23:53.840 sometime ago we used a ro Library which
00:23:57.320 is a representative Library and moving
00:23:59.440 from
00:24:00.279 one minor version to
00:24:02.840 another reduced our response time by
00:24:05.600 about 10 to 20% just because we upgraded
00:24:09.360 this gem we didn't have to do anything
00:24:13.600 else sometimes it will happen that you
00:24:16.080 cannot uh use some Library anymore and
00:24:19.679 then you should obviously consider
00:24:21.600 replacing it in some cases it is
00:24:24.200 extremely cheap for example if you have
00:24:26.840 problem with Json parsing you can
00:24:28.840 replace the Json gem with these two gems
00:24:31.559 here OJ stands for optimize Json and
00:24:34.159 it's a uh Json parcel written in C and
00:24:38.200 the OJ mimic Json Jam will basically
00:24:41.159 allow you to use the same current syntax
00:24:43.399 that use for Json right now with the uh
00:24:46.960 with the new library and it if if you're
00:24:49.720 often passing passing big Json it will
00:24:52.360 make a big big
00:24:55.000 difference now it's get pretty difficult
00:24:58.559 native
00:24:59.559 extensions I wrote maybe one native
00:25:02.039 extension in my life it wasn't
00:25:05.039 easy but you can check some existing
00:25:08.559 native extensions that are written for
00:25:10.200 Ruby some of them are written for C if
00:25:12.159 they are for MRI some are written in
00:25:13.760 Java if the a 4J Ruby it's not that bad
00:25:16.840 it may happen that there is a certain
00:25:18.600 function certain method in your
00:25:20.480 application that is called many many
00:25:22.559 many times and maybe just by moving this
00:25:25.520 one method this one function to a faster
00:25:27.880 language
00:25:28.919 uh you can save a lot of time and maybe
00:25:30.760 it will not be that difficult and if you
00:25:33.159 do not want to use C you can use rust
00:25:35.960 thanks to two uh libraries that that
00:25:39.200 already exist and allow you to write
00:25:40.919 some extensions in
00:25:43.320 Rust the next thing this is quite
00:25:45.600 obvious but often people forget about it
00:25:48.880 is move processing to the background the
00:25:51.600 most obvious example here is sending
00:25:53.320 emails usually you can send email after
00:25:55.640 user gets a response no you do not need
00:25:59.039 to make user waiting until that email is
00:26:01.399 sent especially that if you're using
00:26:03.279 SMTP protocol this will be quite slow
00:26:05.840 but there's many other cases where you
00:26:08.159 can give user a response and you can
00:26:10.840 send a status of a transaction for
00:26:12.760 example when you're processing payment
00:26:14.440 it may take up to a minute so instead of
00:26:16.720 making user wait a minute you just send
00:26:18.679 ID of the transaction and status in
00:26:20.559 progress and then user can hit your uh
00:26:23.440 hit your server again every couple of
00:26:25.320 seconds to check if the transaction was
00:26:27.679 was finished or
00:26:29.200 not when you're really really
00:26:31.960 desperate you might want to extract part
00:26:34.320 of your
00:26:35.360 application and I really mean when
00:26:37.080 you're desperate and I really mean part
00:26:40.039 not ever write rewrite everything in go
00:26:43.440 I often read articles like oh we rewrote
00:26:46.320 our Ruby application in go now we use 10
00:26:48.559 servers instead of 100 and we spent a
00:26:51.919 couple of thousand man hours just for
00:26:54.200 that even though we could afford that
00:26:56.880 servers so you should be really really
00:26:59.559 careful with that one and I think that
00:27:01.799 this is overused and overhyped rewriting
00:27:04.960 application is not a good stuff to do
00:27:07.880 because you're basically spending a lot
00:27:09.360 of time on building the same thing that
00:27:11.159 you've already
00:27:12.600 built there's way more things to talk
00:27:15.080 about that I do not really have time to
00:27:17.679 cover so I will just skip to the third
00:27:20.919 part of the request which is the
00:27:23.600 download of course we do not have many
00:27:26.360 more things left to do
00:27:28.840 the most obvious is to use gzip and to
00:27:31.640 compress your response if you already
00:27:34.159 have your application behind CDN this
00:27:36.640 will also make an impact here and the
00:27:39.520 third thing to consider is that maybe
00:27:41.600 you don't need need you don't need to
00:27:43.760 send all the data that you want to the
00:27:45.640 user maybe big part of this response
00:27:48.039 will be used only in certain cases in 10
00:27:50.399 15% of cases and you should you should
00:27:53.200 move it to another end
00:27:55.159 point so our request come through the
00:27:58.640 user device through the whole world to
00:28:00.559 the server and back to the user device
00:28:03.240 and I would like to write wrap up my
00:28:05.320 presentation just by telling you that
00:28:07.360 you should use CDN infrastructure you
00:28:09.440 should profile and then Benchmark always
00:28:12.200 in this case always focus on the slowest
00:28:14.360 part and rewriting is the last thing to
00:28:17.519 consider Ruby is really fast enough for
00:28:20.000 you catron R and all the other
00:28:22.159 Frameworks are faster in my previous
00:28:24.519 company we scaled the application Ruby
00:28:27.039 application to handle half a million
00:28:28.679 requests per minute before that
00:28:31.000 application will start being extracted
00:28:33.320 to other languages so unless you hit
00:28:35.679 such a big limit then you do you
00:28:38.159 shouldn't really consider rewriting your
00:28:39.880 application you should just focus on the
00:28:42.000 slowest part and gradually improve the
00:28:44.399 speed my name is Gregor vitek this was a
00:28:46.880 presentation about your API which is
00:28:49.519 most probably fast enough thank you very
00:28:51.840 much
Explore all talks recorded at Red Dot Ruby Conference 2016
+17