grammyjs / grammY

The Telegram Bot Framework.
https://grammy.dev
MIT License
2.35k stars 115 forks source link

Grammy is too slow in replying #189

Closed hayyaun closed 2 years ago

hayyaun commented 2 years ago

I wrote a complete bot on Grammy, everyone complains me about my bot being too slow. And I tried Telegraf and compared the difference, it's much more faster than Grammy. If there is any workaround I'd be happy to know. Because it's a tough process rewriting the whole code again... Thanks.

KnorpelSenf commented 2 years ago

Long polling

If you are using bot.start, then you are using a mode that is suited well for development. Instead, use grammY runner. This will be much faster than telegraf, and it is suited for production use. https://grammy.dev/plugins/runner

Webhooks

Webhooks should be equally fast in both frameworks. Telegram determines the speed at which updates are arriving.

hayyaun commented 2 years ago

I tried to use webhooks but could not get it working unfortunately...

KnorpelSenf commented 2 years ago

Polling works fine. In fact, polling with grammY runner can in some cases be much faster than webhooks.

KnorpelSenf commented 2 years ago

You may also want to check out the deployment checklist to see what else you want to do for a large-scale bot in production use: https://grammy.dev/advanced/deployment

hayyaun commented 2 years ago

I also tried run and did't feel any difference

KnorpelSenf commented 2 years ago

Well, there is a difference :)

For example, https://t.me/voicybot is using run(bot) (as you can see here) and it processes more than 100 updates per second. Currently, grammY runner will easily handle 1000 updates per second before it starts to struggle.

Previously, with Telegraf, the bot needed some ugly hacks to make it work, because Telegraf was too slow to cope with the load.

KnorpelSenf commented 2 years ago

In comparison, bot.start() starts to struggle at around 3-5 updates per second. This is of course much, much more than 90 % of all bots need, because they only process 10 messages per day or something.

How high is peak throughput currently for your bot?

hayyaun commented 2 years ago

I read the differences in docs... I might not need that much of users My problem actually is: In my case, for single user, it takes more than a second for bot to reply while using Telegraf it is almost immediate.

KnorpelSenf commented 2 years ago

Yeah that's definitely not normal, grammY is typically able to resopnd within less than 10 µs, so this is not a limitation of this framework. I can take a look at the repo if your bot is open source and you cannot figure it out on your own.

KnorpelSenf commented 2 years ago

Also, it may help you to set DEBUG='*'. This will log all API requests that grammY performs. Maybe you're accidentally performing network requests that you were not aware of.

hayyaun commented 2 years ago

I had to mention that I'm running bot from Iran, which sensored telegram. So I had to use a vpn (ProtonVPN). But as I said it is also immediate using Telegraf to get replied.

KnorpelSenf commented 2 years ago

Are you sure you have configured grammY correctly, so that it uses the same network connections as Telegraf? The configuration works differently for both libraries.

Here is the documentation for the bot configuration with grammY: https://doc.deno.land/https://deno.land/x/grammy/mod.ts/~/BotConfig

hayyaun commented 2 years ago

Yes, I did. I'm using nodejs not deno. Here are debug mode logs:

  grammy:bot Initializing bot +0ms
  grammy:core Calling getMe +0ms
  grammy:bot I am hzrjvbot! +2s
  grammy:core Calling getUpdates +2s
  grammy:bot Processing update 259180708 +12s
  grammy:core Calling getUpdates +12s
  grammy:core Calling sendMessage +15ms
  grammy:core Calling sendMessage +2s
  grammy:bot Processing update 259180709 +20s
  grammy:core Calling getUpdates +18s
  grammy:core Calling sendMessage +2ms
  grammy:core Calling sendMessage +2s
  grammy:bot Processing update 259180710 +5s
  grammy:core Calling getUpdates +3s
  grammy:core Calling sendMessage +4ms
  grammy:bot Processing update 259180711 +7s
  grammy:core Calling getUpdates +7s
  grammy:core Calling sendMessage +6ms
  grammy:core Calling sendMessage +2s
  grammy:bot Processing update 259180712 +3m
  grammy:core Calling getUpdates +13s
  grammy:core Calling sendMessage +6ms
  grammy:core Calling getUpdates +30s

I'm sending 2 messages at once for /start, so you can ignore second one. Below is a command with only 1 reply

  grammy:bot Initializing bot +0ms
  grammy:core Calling getMe +0ms
  grammy:bot I am hzrjvbot! +2s
  grammy:core Calling getUpdates +2s
  grammy:bot Processing update 259180715 +3s
  grammy:core Calling getUpdates +3s
  grammy:core Calling sendMessage +17ms
  grammy:bot Processing update 259180716 +3s
  grammy:core Calling getUpdates +3s
  grammy:core Calling sendMessage +9ms
  grammy:bot Processing update 259180717 +3s
  grammy:core Calling getUpdates +3s
  grammy:core Calling sendMessage +9ms

In debug it shows that it's replying as fast as possible. but there is a lot of delay after it logs sendMessage and when I actually see the reply

rojvv commented 2 years ago

@hayyaun Jfy: The documentation at https://doc.deno.land/https://deno.land/x/grammy/mod.ts applies for both Deno and Node.js.

KnorpelSenf commented 2 years ago
  grammy:core Calling getMe +0ms
  grammy:bot I am hzrjvbot! +2s

You can see that a simple request to getMe already takes 2 seconds. This is surprising, because the call only goes to the Bot API server and back. It does not actually need to communicate with the Telegram backend responsible for message handling. (For reference, typically this takes 170 ms for me.)

You should check via curl (or other tools like postman etc) if you can call getMe and it is faster.

In debug it shows that it's replying as fast as possible. but there is a lot of delay after it logs sendMessage and when I actually see the reply

This confirms the assumption that grammY is not causing this.

If you find out that all requests are slow, no matter which library/client you use, then it may be worth trying out a local Bot API server. (This would be guessing a solution, so no promises.) See https://core.telegram.org/bots/api#using-a-local-bot-api-server for this.

hayyaun commented 2 years ago

I can't conclude, why is Telegraf much faster then.

KnorpelSenf commented 2 years ago

Did you confirm that grammY and curl are equally slow?

Were you running Telegraf on polling, too?

Can you provide the relevant part of the Telegraf code, as well as the part of the grammY code?

Note that both grammY and telegraf are using the exact same underlying implementation for performing web requests. The difference between the frameworks is rather in how to compose middleware, and other things that are unrelated to networking. It very unlikely that the problem is here.

hayyaun commented 2 years ago

Ok, here is the code, It is exactly implemented using docs: main branch
telegraf branch

I would do a minimum implementation and show you the result. It was slow since when I copied the getting started code.

I'm not an expert and not sure what's happening behind the scene.

hayyaun commented 2 years ago

Did you confirm that grammY and curl are equally slow?

Were you running Telegraf on polling, too?

Can you provide the relevant part of the Telegraf code, as well as the part of the grammY code?

Note that both grammY and telegraf are using the exact same underlying implementation for performing web requests. The difference between the frameworks is rather in how to compose middleware, and other things that are unrelated to networking. It very unlikely that the problem is here.

Isn't Telegraf on polling by default?

KnorpelSenf commented 2 years ago

Ok, here is the code, It is exactly implemented using docs: main branch telegraf branch

This code is closed. I do not have access.

Did you confirm that grammY and curl are equally slow? Were you running Telegraf on polling, too? Can you provide the relevant part of the Telegraf code, as well as the part of the grammY code? Note that both grammY and telegraf are using the exact same underlying implementation for performing web requests. The difference between the frameworks is rather in how to compose middleware, and other things that are unrelated to networking. It very unlikely that the problem is here.

Isn't Telegraf on polling by default?

Yes. Telegraf uses a broken implementation of polling by default, can cause data loss. It has acceptable performance.

grammY uses a slow but safe version of polling by default. It can be upgraded to grammY runner which is the fastest long polling client for Telegram Bots. If you want to go faster, you will have to use a different programming language.

hayyaun commented 2 years ago

I can't get webhooks to run for grammy. Do I need extra implementation?

const startBot = async () => {
  await bootstrap();
  bot.use(menuQuestions);
  addListeners();
  const app = express(); // or whatever you're using
  app.use(webhookCallback(bot, "express"));
};

startBot();
KnorpelSenf commented 2 years ago

This is not how to setup a web server with express. Check out the express documentation.

Your integration of grammY into express is correct.

hayyaun commented 2 years ago

This is not how to setup a web server with express. Check out the express documentation.

Your integration of grammY into express is correct.

I used express for many purposes and run some servers, but don't know how to get it working with grammy, this implementation is not working.

KnorpelSenf commented 2 years ago

You are not starting the server.

KnorpelSenf commented 2 years ago

Try adding something like:

const port = 80
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
hayyaun commented 2 years ago

App is running and listening to port 80, and port 80 is open on my laptop. but it's not working. do I need static ip for it? or am I doing anything wrong? How Telegraf uses webhooks by default? (if it does)

KnorpelSenf commented 2 years ago

App is running and listening to port 80, and port 80 is open on my laptop. but it's not working. do I need static ip for it? or am I doing anything wrong?

Are updates arriving at the web server? In other words, did you tell Telegram where to send them? Be sure to read the webhook docs of grammY and the guide that we link to.

My guess is that you didn't call setWebhook correctly. Perhaps we need to make this more clear in the docs too.

How Telegraf uses webhooks by default? (if it does)

It used polling by default.

hayyaun commented 2 years ago

I don't care using hooks or polling I just want to get rid of the unknown delay I'm currently receiving.

KnorpelSenf commented 2 years ago

I also don't care what you're using. It's just not possible to fix it if you don't answer the important questions :)

None of the two methods are inherently slow in grammY. You need to check your setup, and provide information about what you're doing if you want other people to figure out your problem. There's no way to log into your machine and fix it for you.

hayyaun commented 2 years ago

I also don't care what you're using. It's just not possible to fix it if you don't answer the important questions :)

None of the two methods are inherently slow in grammY. You need to check your setup, and provide information about what you're doing if you want other people to figure out your problem. There's no way to log into your machine and fix it for you.

I have provided my code in here. Is there anything I'm doing wrong?

Ok, here is the code, It is exactly implemented using docs: main branch telegraf branch

I would do a minimum implementation and show you the result. It was slow since when I copied the getting started code.

I'm not an expert and not sure what's happening behind the scene.

KnorpelSenf commented 2 years ago

The repository is private. We cannot see it. That's what I meant with https://github.com/grammyjs/grammY/issues/189#issuecomment-1103887322

hayyaun commented 2 years ago

The repository is private. We cannot see it. That's what I meant with #189 (comment)

Now, it is public, sorry.

KnorpelSenf commented 2 years ago

Thanks! I'll check it and and try to reproduce the issue. Will get back to you after that.

KnorpelSenf commented 2 years ago

The bot is not slow for me with grammY. I am not sure why this happens for you.

[1] 2022-04-20T14:27:12.361Z grammy:bot Initializing bot
[1] 2022-04-20T14:27:12.361Z grammy:core Calling getMe
[1] 2022-04-20T14:27:19.643Z grammy:bot I am audizzlebot!
[1] 2022-04-20T14:27:19.643Z grammy:core Calling getUpdates
[1] 2022-04-20T14:27:26.143Z grammy:bot Processing update 98141481
[1] 2022-04-20T14:27:26.146Z grammy:bot Processing update 981414819
[1] 2022-04-20T14:27:26.146Z grammy:bot Processing update 981414820
[1] 2022-04-20T14:27:26.153Z grammy:core Calling getUpdates
[1] 2022-04-20T14:27:26.166Z grammy:core Calling sendMessage
[1] 2022-04-20T14:27:26.172Z grammy:core Calling sendMessage
[1] 2022-04-20T14:27:26.185Z grammy:core Calling sendMessage
[1] 2022-04-20T14:27:26.361Z grammy:core Calling sendMessage
[1] 2022-04-20T14:27:26.886Z grammy:core Calling sendMessage
[1] 2022-04-20T14:27:27.566Z grammy:core Calling sendMessage

You can see it here in action, running locally on my old laptop: doc_2022-04-20_16-28-50 Is this the same for you?

The Telegraf example does not compile, so I did not test it. Does it run substantially faster for you that what's shown here?

hayyaun commented 2 years ago

The speed of this video is speed of Telegraf. Grammy takes so long as I showed above. I don't know why this happens. I'm using ProtonVPN

The Telegraf example does not compile, so I did not test it. Does it run substantially faster for you that what's shown here?

Yes, significantly

KnorpelSenf commented 2 years ago

The speed of this video is speed of Telegraf. Grammy takes so long as I showed above. I don't know why this happens. I'm using ProtonVPN

I'm also not sure because I cannot reproduce this. For me, it's fast with grammY (but that does not help you obviously).

It does not really make much sense to me why Telegraf would be faster, because both frameworks are using node-fetch with exactly the same network configuration. Seems fishy. This is pretty hard to investigate without access to the machine, so I can't help you that much :(

What I can say is how I would start tracking down the problem:

  1. Only look at the getMe call. It is already slow enough, so we can see that the problem occurs there.
  2. Check when getMe is fast and slow. a) Test it with grammY, just call bot.init() and check the logs. b) Test it with Telegraf, start the bot and stop it again c) Test it from the terminal, run time curl https://api.telegram.org/bot<token>/getMe d) Test it from Postman with the same URL e) Test it from a browser, too

That way, you can see when things are slow and when they are fast, this should give you the hint for the next step. Maybe also try different versions of Node, or try out a local Bot API server (if that works in Iran) etc.

hayyaun commented 2 years ago

I can give you access to my machine if you have enough time. This is my telegram id dafaqisgoinon

KnorpelSenf commented 2 years ago

I can have a look, but I can't spend too much time on it :)

KnorpelSenf commented 2 years ago

I don't think we have further comments on this issue.

KnorpelSenf commented 2 years ago

Fixed by moving to a server with reliable connection to Telegram. No code changes needed.

sartoshi-foot-dao commented 2 years ago

Such humble patience and support quality @KnorpelSenf

You're doing great work!