asyncio + h11 (was #58)#60
Conversation
|
I don't think this is necessary if we manage timeouts better around function initialisation. |
|
This is still necessary, no matter what. Because customer's code can take an enormous amount of time on the module initialization. |
|
@rdallman i've got this to work, need to fix some tests. |
|
not against the module loading thing in principle, it does seem like a problem we'll run into pretty quickly. that being said, this patch is now 2 kinda big (scope, not code necessarily) ideas wrapped into one plus large amounts of code are just being tossed out (which is great), and it's hard to sniff out what's what exactly in this PR now to really review it. any chance you could stage the removals first, then have a couple patches for the changing user module load and asyncio stuff? it would make it easier for a reviewer who may not be very familiar with the inner workings of the fdk (I believe there is only one person really, and we need to get more people into it, is what I'm hinting at). thanks for fixing up h11 stuff, that's great, I hope it's a good solution at least. |
Well, that’s true, however, delayed import change is small and stratightforward. I’ll add better explanation of what this PR consists of. |
|
@rdallman Okay, delayed import change itself is small, honestly, but I removed lots of stale code that nobody uses, I'll split that into a separate PR. |
|
Okay, PR is ready. What you need to test it?
FROM fnproject/python:3.7.1-dev as build-stage
ADD . /function
WORKDIR /function
# add all dependencies you have to install
RUN pip3 install --target /python/ --no-cache --no-cache-dir fdk-test-py3-none-any.whl
RUN rm -fr ~/.cache/pip /tmp* requirements.txt func.yaml Dockerfile .venv
FROM fnproject/python:3.7.1
COPY --from=build-stage /function /function
COPY --from=build-stage /python /python
ENV PYTHONPATH=/python
ENTRYPOINT ["/python/bin/fdk", "/function/func.py", "handler"]
func.py: import json
import io
from fdk import response
def handler(ctx, data=None):
name = "World"
try:
body = json.loads(data.getvalue())
name = body.get("name")
except (Exception, ValueError) as ex:
print(str(ex))
return response.Response(
ctx, response_data=json.dumps(
{"message": "Hello {0}".format(name)}),
headers={"Content-Type": "application/json"}
)
|
|
this patch still seems to rely on delayed import even after rebasing (I didn't push), hard to untangle right now... guess we do the other one first? I'll make some comments there... |
is this the process now for any python fdk function? what's with wheel? I looked up what it is - but is it required? this seems more cumbersome than creating these 2 files in a folder and hitting |
No, that’s for you basically. People would still get it from PYPI. |
77e2116 to
0ab4cb1
Compare
|
rebased on master. |
CLA BotThank you for your submission! It appears that the following authors have not signed our Contributor License Agreement:
Please do so now by visiting http://www.oracle.com/technetwork/community/oca-486395.html Once complete, let us know in our community Slack and we’ll send you an Fn T-shirt. We are working on modernizing the CLA process into a digital signature but it isn’t quite ready yet. Thank you for being a part of the Fn Community! |
57db490 to
9d12f44
Compare
CLA BotAll committers have signed the CLA. |
9d12f44 to
fca663e
Compare
|
@denismakogon so i've ventured down a new road with with the linked branch up there i can reliably run functions via fn on my laptop, 20 at a time, without 502/504 (on startup or otherwise), with keep alives, etc. I don't think that cython is an issue for us since |
I've been this path as well, I had (and having it one more time ) running coroutines within this code. We eventually copying all pieces of code from sanic but within a smaller amount of code. For now, there's only one problem. I/We copied a piece of sanic, which is ok (but i'm not proud of that). The only thing is async-http lib that i've made doesn't start within 3 seconds. So, I'd try to make it lighter, have some basic ideas. |
yeah. i wonder if maybe clamping to old versions of sanic before cruft would start faster (slightly different than async-http lib which is based on newest?)? it seems to be pretty complete solution in about 100 LOC for httptools + asyncio.Protocol (basically copied version of old sanic), and since there's not a lot of code there locking to an old version doesn't seem all that bad (less room for bugs), but the case for just vendoring it and/or calling it our own so that we can modify it and/or reduce out what we don't need is there too I guess (we don't need lots of stuff... pipelining, cookies, multipart). i'm not sure which is better there, obviously it's not ideal to not have an off the shelf solution in this case, but the code itself here is really straight forward and small (httptools and asyncio do all the hard stuff, we're just tying it together) seems like if i get something thrown together we can test with coroutines then? async-http lib seems slightly different but could be a good option too. one difference is async-http version has flow control, but this is pretty easy to add too (should fix coroutine issue I think?). if we can get the start time down on async-http lib then let's try it -- kinda going at it both ways, tearing it down vs building from nothing, not sure which is better but either may work. keep us posted please... |
|
@rdallman newer PR uses 0.0.4 of async-http that is a lot thinner and starts within 2.5 seconds: |
|
|
||
| @staticmethod | ||
| def import_from_source(func_module_path): | ||
| from importlib import util |
There was a problem hiding this comment.
trying to reduce imports time by delaying code initialization as close as possible to the time of the actual call.
| logger.info("request execution completed") | ||
| return func_response | ||
|
|
||
| from async_http import response |
There was a problem hiding this comment.
same, import response only you need that, import are cachable, so, only 1st import is heavy, the rest are not.
|
cool. small bug: b'%s' printing somewhere otherwise, testing it now... |
|
mmm, still seeing a few: :( with the from scratch edition (linked above) it's not having issues opening the socket on time, at least. does sanic based lib have long init sequence we could minimize too? any other ideas? |
that's literally due to the amount of code
without having any logs from the container startup I can't tell you more. I'm not seeing a lot of code in front of asyncio. the number of the dependencies were reduced to 1. I need to know exactly when Fn aborts startup procedure and logs would be very useful. |
|
there's nothing more to reduce in both async-http or fdk in terms of startup time, 2.49 is the best time. |
|
from what i understand wrt how python loads modules (read: unintelligibly), can we include the async-http lib as a subdirectory in fdk-python and import it from there, instead of from requirements.txt? |
|
Yes, I can do that. |
|
@denismakogon any updates I can test? i think i'm probably 2-3 days out from a bottoms up one, but won't pursue that if we can get something else working meanwhile |
|
not yet, need some time, will work on it tomorrow. |
confirmed that this approach seems to resolve the 504 from importing it in requirements.txt. need to fix this bug and probably test a little more extensively, but would like to close this out... |
rdallman
left a comment
There was a problem hiding this comment.
LGTM - i tested a few things this morning; concurrency, latency, large payloads, connections. all looks pretty good, no 502 or 504. i can start a container on my laptop with this in < 800ms now, which is much better than 2500ms number that was thrown out - i think import of subdir is lots faster than loading external module. in any case, I haven't tested the minutia (headers, etc) but that should all be okay I hope... hopefully it's tested somewhere in here, or the users will debug for us - at this point, satisfied that 2 issues were taken care of and this will ease the onboarding process for python users who end up getting failing functions in their first go round.
i forget now whether we broke users that were using main or not and if we provided clear instructions to migrate (not just a blog, but readme). it would be nice to let them run main with a warning just to move things over, but it's nice to force migration too - it would be nice to have the migration process clearly outlined before merging here (maybe it's here and i missed it scanning through).
thanks for your persistence here @denismakogon and thanks others for your time in testing and reviewing this. i've a newfound loathing for this language and i think i've sworn it off for good now.
code check, readme, docs, tutorials and blogpost - suppose to be enough to outline the migration process.
i still don't like the idea of moving the whole async-http here, but i do see a need in it, unfortunately, there's no way to speed up the whole importing system for now.
thanks to all of you for being around and helping to shape it up to the final form. |
all of that covered by unit tests. |


What's being done?
Customer's code import happens right before the first calls.
Why it's so necessary?
With this change, the cold start only affected by FDK itself,
but not by the customer's code.
Minimum Python requirement
3.7.1
Impacts
Fn CLI due to the boilerplate in it.
Based on #62 and #61