Callables to Full python 3 take ~15 second, basic python 3 takes no time. why?

I am trying to do this, but i get this error:
Hashlib is not yet supported in the PyPy sandbox at /sbxshims/hashlib.py, line 2

@anvil.server.callable
def get_headers():

# Decode API private key from base64 format displayed in account management
  
  api_secret = base64.b64decode(anvil.secrets.decrypt_with_key('user_private_key', app_tables.keys.search()[0]['private_key']))
  
  # Variables (API method, nonce, and POST data)
  api_path = "/0/private/TradeBalance"
  api_nonce = str(int(time.time()*1000))
  api_post = "nonce=" + api_nonce + "&asset=xbt"
  
  # Cryptographic hash algorithms
  api_sha256 = hashlib.sha256(api_nonce + api_post).digest()
  api_hmac = hmac.new(api_secret, api_path + api_sha256, hashlib.sha512)
  
  # Encode signature into base64 format used in API-Sign value
  api_signature = base64.b64encode(api_hmac.digest())
  
  return api_signature

When I switch from basic python 3 to full python 3, it works but everything takes absurdly long (even modules that don’t import hashlib).

Is there a reason why the Full python 3 environment would slow everything down? Is there a way to fix it?

I just tried in a toy example and it doesn’t seem like the import is causing any time delays.

but if you suspect so, could you move the suspected slow import statements into the function itself and see if this changes anything for other server calls?

have you tried timing lines to see which are slow?

here’s the timeit function decorator i usually use to time an entire function:

from functools import wraps
from time import time

def timeit(f):
  @wraps(f)
  def wrap(*args, **kwargs):
    str_args    = ', '.join(str(arg) for arg in args)
    str_kwargs  = ', '.join(f"{k}={v}" for k,v in kwargs.items())
    args_kwargs = f"{str_args}, {str_kwargs}" if args and kwargs else f"{str_args}{str_kwargs}"
    print(f'{f.__name__}({args_kwargs}) called')
    ts = time()
    result = f(*args, **kwargs)
    te = time()
    print(f'{f.__name__} took: {te-ts:.4f} sec')
    return result
  return wrap

@anvil.server.callable
@timeit
def get_headers():
  ...

You could also do something like

from itertools import count
_i = count()

def time_since(t, msg=''):
  print(f"{next(_i)}: {msg} took {time() - t:.2f} sec")
  return time()

@anvil.server.callable
@timeit
def get_headers():

# Decode API private key from base64 format displayed in account management
  t = time()

  api_secret = base64.b64decode(anvil.secrets.decrypt_with_key('user_private_key', app_tables.keys.search()[0]['private_key']))

  # Variables (API method, nonce, and POST data)
  api_path = "/0/private/TradeBalance"
  api_nonce = str(int(time.time()*1000))
  api_post = "nonce=" + api_nonce + "&asset=xbt"
  
  t = time_since(t, 'variables')

  # Cryptographic hash algorithms
  api_sha256 = hashlib.sha256(api_nonce + api_post).digest()
  api_hmac = hmac.new(api_secret, api_path + api_sha256, hashlib.sha512)

  t = time_since(t, 'Crypto Hash')  

  # Encode signature into base64 format used in API-Sign value
  api_signature = base64.b64encode(api_hmac.digest())
  t = time_since(t, 'Encode')    

  return api_signature

did some more testing and youre right, its not the imports.

Something about running full python 3 on the server causes a massive delay and I have no idea why.

I created a new blank app with a single server module that prints the time between when the call was made from the form and when the server heard it. Using full python 3 - It took 17 seconds for this to run:

class Form1(Form1Template):

  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    ta = time.time()
    anvil.server.call('test', ta)
    tb=time.time()
    print('server call: '+str(tb-ta))

which calls:

@anvil.server.callable
def test(t):
  print('form start til server call: '+str(time.time()-t))

When running basic python 3 on server, it takes a fraction of a second.
I am fine running basic python 3 except the error I mentioned requires the full python 3 environment.
I updated the title of my post to better describe the issue. Here is the app i tested with.
https://anvil.works/build#clone:FII3LKKPPVVWAB6J=Z6HSNAPVGAEDIGJZPK3S5FR6

It took (basically) the same time for me to run either environment…


basic took 0.2 and full took 0.9
(basic python 3 which uses pypy is usually gonna be faster than full python for most things… but 17 seconds is not right…)

Hey there - just to confirm, 17s is definitely outside what we’d expect! I just tried for myself, and got around 0.2s both ways. Could you copy the output from your Output console? (Also, I want to confirm that we’re not just seeing clock skew between your browser and the server…)

Another thought: could you try executing that call twice (ie back to back in the same __init__ function) to see whether it’s a one-time/startup

And finally: Is this a small app or a large one? (Could perhaps be an issue transmitting the app content to the server-side python environment). If it’s large, is a small one different, and vice versa?

(I have checked, and I’m not seeing CPU throttling in your server-side environments, which would be the other thing to check…)

both this test app and the other app i was having bootup issues with are giving the exact same error. Other apps that run full python 3 don’t have any issue.

16A cookie associated with a cross-site resource at <URL> was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at <URL> and <URL>.
ide/partials/modals/live-chat.html:1 Failed to load resource: the server responded with a status of 404 ()
app.js:142 Object
responseError @ app.js:142
IDE.js:115 Loaded app: Material Design 29 (FII3LKKPPVVWAB6J)
IDE.js:2770 Waiting for designer to unload...
IDE.js:2767 Designer unloaded.
IDE.js:2792 Waiting for runner to unload...
IDE.js:2789 Runner unloaded.
DesignerIframe.js:18 Cannot make RPC call to designer - iframe not initialised. setComponents
e @ DesignerIframe.js:18
app.js:11 Assertion failed: TypeError: Cannot read property 'postMessage' of null
    at e (DesignerIframe.js:20)
    at FormEditor.js:89
    at d (rsvp.es.js:317)
    at _ (rsvp.es.js:489)
    at rsvp.es.js:553
    at MutationObserver.ue (rsvp.es.js:2393)
(anonymous) @ app.js:11
IDE.js:2333 Saving path: Array(1)
IDE.js:2333 Saving path: Array(0)
build#app:FII3LKKPPVVWAB6J:1 Access to XMLHttpRequest at 'javascript:void(0)' from origin 'https://anvil.works' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
javascript:void(0) Failed to load resource: net::ERR_FAILED
IDE.js:2767 Designer unloaded.
IDE.js:2792 Waiting for runner to unload...
IDE.js:2789 Runner unloaded.
IDE.js:2333 Saving path: Array(3)
IDE.js:2767 Designer unloaded.
IDE.js:2792 Waiting for runner to unload...
IDE.js:2789 Runner unloaded.
IDE.js:2767 Designer unloaded.
IDE.js:2792 Waiting for runner to unload...
IDE.js:2789 Runner unloaded.
IDE.js:2333 Saving path: Array(1)
IDE.js:2767 Designer unloaded.
jquery-migrate.min.js:35 JQMIGRATE: Migrate is installed, version 3.0.2-pre
runner.bundle.js:176 SERVER: form start til server call: 0.7006125450134277

runner.bundle.js:177 RPC Request (797 ms, 7 ms lost)
runner.bundle.js:176 CLIENT: server call: 0.7998502254486084

DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/contentscript.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/inpage.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/contentscript.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/inpage.js.map
DevTools failed to parse SourceMap: chrome-extension://fleenceagaplaefnklabikkmocalkcpo/content-script.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/contentscript.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/inpage.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/contentscript.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/inpage.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/contentscript.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/inpage.js.map
DevTools failed to parse SourceMap: https://anvil.works/assets/service-worker-5143f3dcc5d4f1827a851e30664e7ccd94e73a88847af8766f86ff8744323b49.js.map
DevTools failed to parse SourceMap: https://anvil.works/runtime/css/bootstrap.css.map
IDE.js:2792 Waiting for runner to unload...
IDE.js:2789 Runner unloaded.
IDE.js:2333 Saving path: ["runtime_options"]
IDE.js:2767 Designer unloaded.
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/contentscript.js.map
DevTools failed to parse SourceMap: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/sourcemaps/inpage.js.map
jquery-migrate.min.js:35 JQMIGRATE: Migrate is installed, version 3.0.2-pre
DevTools failed to parse SourceMap: https://anvil.works/runtime/css/bootstrap.css.map
runner.js:238 SERVER: form start til server call: 8.084161758422852
server.js:653 RPC Request (9145 ms, 8588 ms lost)
runner.js:238 CLIENT: server call: 9.149470090866089

server.js:275 WebSocket closed:  Arguments [CloseEvent, callee: (...), Symbol(Symbol.iterator): ƒ]

So, to be clear, this particular test app shows this issue, but nothing else in your account does? What happens if you clone this test app (in your account)? Does the cloned app show the same issue?

Does it happen if you hit the Published link too, or just if you run in the IDE?

The browser console isn’t showing anything unusual, but something I’d like to see is the Network tab, if you filter for /ws (which will show you the client<->server websocket).

All apps on my personal account slow down when I run fulll python 3 (published and IDE) I think I know why, check your email.

Above when i said “other apps running full python 3 don’t have any issue issue”, I meant to say that on my business account when I run full python 3, there is no speed issue.

RPC Request (6036 ms, 5474 ms lost)
server.js:653 Send call (560 ms, 0 ms lost)
server.js:653 Send to websocket (2 ms, 2 ms lost)