Cold start issue


#1

Hi, my name is Denis. We’ve (me and my folks) been trying to solve the cold start issue of our pet project (https://github.com/fnproject/fdk-python). At this moment we use aiohttp as the base unix http server.
However, when we started to do a solid performance testing, we’ve figured out that aiohttp takes almost 9 seconds to start within 128Mb RAM (this is our criteria: a server must start within 3 seconds, not longer).
Then I decided to look around to see what else we can use and then i came across sanic.
I was able to reduce the cold start time up to 6.5 seconds, however, this is still x2 of the required cold start time.

I figured out that sanic doesn’t have any importing rules and when i attempt to do things like "from sanic. import "tons of unnecessary imports being executed (for instance, if i don’t use blueprints - i don’t want the import to be loaded; if I don’t use websocket - i don’t want it to affect the cold start, etc.)

Here are my measures of import time:

import time: self [us] | cumulative | imported package
import time:     75054 |      75054 | zipimport
import time:       971 |        971 | _frozen_importlib_external
import time:       166 |        166 |     _codecs
import time:     91712 |      91877 |   codecs
import time:      4969 |       4969 |   encodings.aliases
import time:     11474 |     108320 | encodings
import time:       810 |        810 | encodings.utf_8
import time:       501 |        501 | _signal
import time:      4961 |       4961 | encodings.latin_1
import time:       170 |        170 |     _abc
import time:      1861 |       2031 |   abc
import time:      5073 |       7104 | io
import time:     73518 |      73518 |       _stat
import time:      2963 |      76480 |     stat
import time:      1404 |       1404 |       genericpath
import time:    100572 |     101976 |     posixpath
import time:     99712 |      99712 |     _collections_abc
import time:      8394 |     286560 |   os
import time:      4962 |       4962 |   _sitebuiltins
import time:       797 |        797 |   sitecustomize
import time:       465 |        465 |   usercustomize
import time:      5821 |     298603 | site
import time:      2182 |       2182 |     types
import time:     87238 |      87238 |     _collections
import time:      8005 |      97424 |   enum
import time:       154 |        154 |     _sre
import time:      1343 |       1343 |       sre_constants
import time:      7231 |       8573 |     sre_parse
import time:      7200 |      15925 |   sre_compile
import time:       120 |        120 |     _functools
import time:       178 |        178 |         _operator
import time:     93176 |      93353 |       operator
import time:      1744 |       1744 |       keyword
import time:       372 |        372 |         _heapq
import time:      3370 |       3741 |       heapq
import time:     96271 |      96271 |       itertools
import time:      3532 |       3532 |       reprlib
import time:    103500 |     302139 |     collections
import time:     90438 |     392697 |   functools
import time:       233 |        233 |   _locale
import time:      1529 |       1529 |   copyreg
import time:     86535 |     594341 | re
import time:       477 |        477 |           collections.abc
import time:      2708 |       2708 |             concurrent
import time:       244 |        244 |                 time
import time:      1845 |       1845 |                       token
import time:    102814 |     104658 |                     tokenize
import time:      1602 |     106260 |                   linecache
import time:     90588 |     196847 |                 traceback
import time:     92023 |      92023 |                 warnings
import time:      2348 |       2348 |                   _weakrefset
import time:     95134 |      97482 |                 weakref
import time:       187 |        187 |                   _string
import time:     99503 |      99690 |                 string
import time:     13946 |      13946 |                 threading
import time:       130 |        130 |                 atexit
import time:     96707 |     597065 |               logging
import time:     97216 |     694281 |             concurrent.futures._base
import time:      3781 |     700769 |           concurrent.futures
import time:       494 |        494 |             _socket
import time:       324 |        324 |               math
import time:       833 |        833 |               select
import time:     90818 |      91975 |             selectors
import time:       327 |        327 |             errno
import time:     12336 |     105132 |           socket
import time:      3348 |       3348 |             signal
import time:       527 |        527 |             _posixsubprocess
import time:     98387 |     102261 |           subprocess
import time:      2003 |       2003 |             _ssl
import time:       315 |        315 |                 _struct
import time:     94578 |      94892 |               struct
import time:       894 |        894 |               binascii
import time:      3675 |      99460 |             base64
import time:    106677 |     208140 |           ssl
import time:       698 |        698 |           asyncio.constants
import time:       240 |        240 |                   _opcode
import time:     81569 |      81809 |                 opcode
import time:      3580 |      85388 |               dis
import time:      2616 |       2616 |                 importlib
import time:      1582 |       4197 |               importlib.machinery
import time:    299663 |     389247 |             inspect
import time:      1132 |       1132 |               asyncio.format_helpers
import time:      2138 |       3269 |             asyncio.base_futures
import time:       978 |        978 |             asyncio.log
import time:      2852 |     396346 |           asyncio.coroutines
import time:       275 |        275 |               _contextvars
import time:       499 |        774 |             contextvars
import time:      1275 |       1275 |               asyncio.base_tasks
import time:       775 |       2049 |             _asyncio
import time:     92092 |      94914 |           asyncio.events
import time:      3021 |       3021 |           asyncio.futures
import time:      4722 |       4722 |           asyncio.protocols
import time:      2089 |       2089 |             asyncio.transports
import time:     91472 |      93560 |           asyncio.sslproto
import time:      5257 |       5257 |           asyncio.tasks
import time:    540759 |    2256050 |         asyncio.base_events
import time:      4277 |       4277 |         asyncio.locks
import time:      1357 |       1357 |         asyncio.runners
import time:      2318 |       2318 |         asyncio.queues
import time:     38923 |      38923 |         asyncio.streams
import time:      6261 |       6261 |         asyncio.subprocess
import time:     97375 |      97375 |           asyncio.base_subprocess
import time:      8924 |       8924 |           asyncio.selector_events
import time:    181920 |     288218 |         asyncio.unix_events
import time:      1568 |    2598969 |       asyncio
import time:      1750 |       1750 |       fdk.constants
import time:      2429 |       2429 |           importlib.abc
import time:      3968 |       3968 |           contextlib
import time:     91994 |      98390 |         importlib.util
import time:       618 |      99007 |       fdk.customer_code
import time:      1332 |       1332 |       fdk.log
import time:      1169 |       1169 |       fdk.http
import time:       526 |        526 |             _datetime
import time:    202196 |     202721 |           datetime
import time:      2083 |       2083 |                   numbers
import time:     89055 |      91137 |                 _decimal
import time:       640 |      91777 |               decimal
import time:      4485 |      96262 |             iso8601.iso8601
import time:       976 |      97237 |           iso8601
import time:       217 |        217 |             fdk.headers
import time:       933 |       1150 |           fdk.context
import time:       269 |        269 |             fdk.response
import time:      1760 |       2029 |           fdk.errors
import time:      1733 |     304869 |         fdk.runner
import time:      1499 |     306368 |       fdk.http.event_handler
import time:      1091 |       1091 |         fdk.async_http
import time:      1689 |       1689 |                         _compat_pickle
import time:       557 |        557 |                             org
import time:        91 |        648 |                           org.python
import time:        87 |        735 |                         org.python.core
import time:      1077 |       1077 |                         _pickle
import time:    197836 |     201336 |                       pickle
import time:       414 |        414 |                         _queue
import time:      3558 |       3972 |                       queue
import time:    101548 |     306855 |                     logging.handlers
import time:      3928 |       3928 |                     socketserver
import time:     92155 |     402937 |                   logging.config
import time:       584 |        584 |                     urllib
import time:     91224 |      91807 |                   urllib.parse
import time:      2653 |       2653 |                         multiprocessing.process
import time:     89237 |      89237 |                           array
import time:      2803 |      92039 |                         multiprocessing.reduction
import time:      4185 |      98877 |                       multiprocessing.context
import time:     97875 |     196751 |                     multiprocessing
import time:       386 |     197137 |                   sanic.reloader_helpers
import time:       510 |        510 |                       sanic.helpers
import time:      1181 |       1690 |                     sanic.exceptions
import time:       636 |       2326 |                   sanic.config
import time:       481 |        481 |                   sanic.constants
import time:       600 |        600 |                     sanic.log
import time:       212 |        212 |                         winreg
import time:      3791 |       4003 |                       mimetypes
import time:       725 |        725 |                             aiofiles.base
import time:       432 |        432 |                             aiofiles.threadpool.utils
import time:      1017 |       2173 |                           aiofiles.threadpool.binary
import time:       654 |        654 |                           aiofiles.threadpool.text
import time:       683 |       3510 |                         aiofiles.threadpool
import time:       517 |       4026 |                       aiofiles
import time:    192941 |     192941 |                           platform
import time:       550 |     193490 |                         multidict._compat
import time:     90186 |      90186 |                         multidict._abc
import time:       271 |        271 |                           multidict._istr
import time:       806 |        806 |                           multidict._multidict_base
import time:      2341 |       3418 |                         multidict._multidict
import time:       739 |     287832 |                       multidict
import time:      1774 |       1774 |                       sanic.cookies
import time:      1066 |       1066 |                       ujson
import time:      1382 |     300081 |                     sanic.response
import time:       832 |     301512 |                   sanic.handlers
import time:       179 |        179 |                       _uuid
import time:      6732 |       6910 |                     uuid
import time:     83760 |      83760 |                     sanic.views
import time:      2707 |      93376 |                   sanic.router
import time:       328 |        328 |                           httptools.parser.errors
import time:       443 |        771 |                         httptools.parser.parser
import time:       336 |       1107 |                       httptools.parser
import time:       357 |       1464 |                     httptools
import time:       344 |        344 |                             _json
import time:      2472 |       2815 |                           json.scanner
import time:      3829 |       6644 |                         json.decoder
import time:    101125 |     101125 |                         json.encoder
import time:      2216 |     109984 |                       json
import time:       571 |        571 |                           email
import time:      1324 |       1324 |                             email.errors
import time:     88202 |      88202 |                                 email.quoprimime
import time:      2078 |       2078 |                                 email.base64mime
import time:      2011 |       2011 |                                     quopri
import time:       920 |       2930 |                                   email.encoders
import time:     97197 |     100127 |                                 email.charset
import time:     11005 |     201410 |                               email.header
import time:     86363 |      86363 |                                     _hashlib
import time:      2831 |       2831 |                                     _blake2
import time:     94555 |      94555 |                                     _sha3
import time:      2362 |     186109 |                                   hashlib
import time:       325 |        325 |                                     _bisect
import time:      4002 |       4327 |                                   bisect
import time:      1386 |       1386 |                                   _random
import time:      4747 |     196568 |                                 random
import time:    182213 |     182213 |                                     locale
import time:      6868 |     189080 |                                   calendar
import time:      3906 |     192986 |                                 email._parseaddr
import time:      5391 |     394943 |                               email.utils
import time:      4944 |     601296 |                             email._policybase
import time:      5907 |     608526 |                           email.feedparser
import time:     86297 |     695393 |                         email.parser
import time:      1697 |       1697 |                           uu
import time:     94938 |      94938 |                           email._encoded_words
import time:      3554 |       3554 |                           email.iterators
import time:     97739 |     197928 |                         email.message
import time:     95412 |      95412 |                           html.entities
import time:      4934 |     100346 |                         html
import time:       977 |        977 |                             fnmatch
import time:       912 |        912 |                             zlib
import time:      3975 |       3975 |                               _compression
import time:      1358 |       1358 |                               _bz2
import time:      4876 |      10208 |                             bz2
import time:       840 |        840 |                               _lzma
import time:     94300 |      95139 |                             lzma
import time:       572 |        572 |                             pwd
import time:      1476 |       1476 |                             grp
import time:     98194 |     207475 |                           shutil
import time:     96806 |     304281 |                         tempfile
import time:      7428 |    1305373 |                       cgi
import time:     84357 |      84357 |                         http
import time:     12879 |      97235 |                       http.cookies
import time:     95820 |    1608411 |                     sanic.request
import time:       125 |        125 |                         gc
import time:       893 |       1017 |                       uvloop.includes
import time:      1868 |       1868 |                       uvloop._patch
import time:       529 |        529 |                         backports_abc
import time:       862 |        862 |                         uvloop._noop
import time:      1559 |       1559 |                         concurrent.futures.thread
import time:      6020 |       8970 |                       uvloop.loop
import time:     91527 |     103381 |                     uvloop
import time:      1782 |    1715036 |                   sanic.server
import time:       424 |        424 |                     aiofiles.os
import time:     86435 |      86858 |                   sanic.static
import time:       454 |        454 |                   sanic.testing
import time:       605 |        605 |                         websockets.exceptions
import time:       685 |        685 |                           websockets.extensions
import time:       215 |        215 |                             websockets.speedups
import time:       611 |        826 |                           websockets.framing
import time:      2180 |       3690 |                         websockets.extensions.permessage_deflate
import time:      1114 |       1114 |                           websockets.headers
import time:       683 |       1797 |                         websockets.handshake
import time:       190 |        190 |                           websockets.version
import time:     87595 |      87785 |                         websockets.http
import time:       316 |        316 |                           websockets.compatibility
import time:       295 |        295 |                             websockets.py36
import time:       318 |        613 |                           websockets.py36.protocol
import time:      3073 |       4001 |                         websockets.protocol
import time:       828 |        828 |                         websockets.uri
import time:       616 |        616 |                           websockets.py35
import time:       503 |       1119 |                         websockets.py35.client
import time:      1806 |     101626 |                       websockets.client
import time:       234 |        234 |                         websockets.py35.server
import time:      1026 |       1259 |                       websockets.server
import time:       984 |     103868 |                     websockets
import time:       980 |     104847 |                   sanic.websocket
import time:      1287 |    2998054 |                 sanic.app
import time:      1709 |       1709 |                 sanic.blueprints
import time:       441 |    3000203 |               sanic
import time:        75 |    3000277 |             sanic.request
import time:       441 |    3000718 |           fdk.async_http.protocol
import time:       305 |    3001022 |         fdk.async_http.serve
import time:      1171 |    3003283 |       fdk.async_http.app
import time:      1321 |    6013195 |     fdk
import time:     87309 |    6100503 |   fdk.scripts
import time:      3385 |    6103888 | fdk.scripts.fdk

As you may notice, there 3 big problems here: asyncio (we don’t control it =/ ), sanic.server(1.7 seconds), sanic.app (3 seconds)

sanic.app and sanic.blueprint appears only because of this code: https://github.com/huge-success/sanic/blob/master/sanic/init.py#L1-L2

I do understand the reason of doing so, but having a single entrypoint to all imports probably the worst idea in Python ever because it turns a library into a RAM/CPU bomb.