shurillu / CTBot

A simple (and easy to use) Arduino Telegram BOT Library for ESP8266/ESP32
MIT License
147 stars 34 forks source link

When running low on RAM #37

Open ElVasquito opened 4 years ago

ElVasquito commented 4 years ago

Ciao Stefano!

As my sketch got bigger, some RAM problems appeared. Currently I have 33kb of free Heap, and 22kb of MaxBlockSize in the loop(). My bot stopped sending the bigger messages (~800 bytes). So after some investigation (printing ESP.getFreeHeap() through the code) I found out that after telegramServer.connect() heap went as low as 5KB, and after parsing the reply into the JSonBuffer, to 3KB. So those messages started going to the limbo, or the ESP just crashed after a while. After more investigation I ended making three main changes to the lib, to try save Heap: 1) Sending all the strings to Flash, like:

parameters = F("?limit=1&allowed_updates=message,callback_query");

2) Removing the "String response" variable from the code, in favor of streaming the response directly into the JsonBuffer, like:

JsonObject& root = jsonBuffer.parse(sendCommand(F("getUpdates"), parameters));

3) A game changer, before calling connect():

telegramServer.setBufferSizes(512, 512);

Telegram servers fortunately support those buffer sizes! With those changes, the lowest I saw the getFreeHeap() fall, on heavy load (like accessing the ESP's webserver while the bot checks for new messages, or responds, even big messages) was 15kb (!) Now the bigger messages are always sent, it is not crashing anymore (at least for now, hehe) and also I didn't notice any change of speed at all, with that smaller buffer size. That change alone saved about 14kb of Heap! Tremendous for the ESP. So perhaps there are more String type variables that could be optimized, but not for a big change I guess... BTW, I don't know if an ESPAsyncTCP implementation would need more heap than the current one... ;-)

Saluti, Stefano, stammi bene!

shurillu commented 4 years ago

Hola Marton, muy bien hecho hombre! All you said makes me thinking about a full library refactory: all strings, memory management (even the ArduinoJson objects) needs to be revised. I'll do priority to this issue, later the ArduinoJson 5 -> ArduinoJson6 support.

Muchas gracias Marton: si todos fueran como tu, esta libreria seria mucho mejor! Hasta pronto!

Stefano

ElVasquito commented 4 years ago

Muchas gracias a tí, Stefano! Nice to be of help. Talking about improvements, one more thing I needed was the parse_mode option, to be able to send nicely formatted messages, with bold/italics/etc, and to remove the keyboard when needed :) This is the start of sendMessage as I have it:

bool CTBot::sendMessage(int64_t id, String message, String keyboard, bool remove_keyboard, uint8_t parse_mode)
{
    String parameters;
    String strID;

    if (0 == message.length())
        return(false);

    strID = int64ToAscii(id);
    message = URLEncodeMessage(message);
    parameters = (String)F("?chat_id=") + strID + (String)F("&text=") + message;

        if (keyboard.length() == 0 && remove_keyboard)
                parameters += (String)F("&reply_markup={\"remove_keyboard\":true}");
        else if (keyboard.length() != 0)
        parameters += (String)F("&reply_markup=") + keyboard;

    if (parse_mode == 1)
        parameters += (String)F("&parse_mode=Markdown");

    if (parse_mode == 2)
        parameters += (String)F("&parse_mode=HTML");

I think this can be done better, but hey, it works ;)

Gracias de nuevo y que estés muy bien, Stefano!!

shurillu commented 3 years ago

Hola Marton, que tal?

Finally I added your memory improvements suggestions in the version 2.1.1 (for now only in the master branch, but soon I'll publish the release).

Again, thank you so much: saving 15K of heap for the ESP8266 is a giant leap!

Stefano.

P.S.: I added your name in the special thanks section! P.P.S.: I leave this issue open as reminder to add the parse_mode functionality.

ElVasquito commented 3 years ago

Hola Stefano!

Great news! I'm on a different matter these days, plus the previous version is working very well, so for the current time I will follow the popular say: "If it ain't broke, don't fix it!". Thanks for the mention! :)

Que sigas bien, Stefano! Saludos

P.S.: Oh well, before clicking Submit, I just saw that the new 2.1.2 has a non-blocking getNewMessage? Now that sounds so great to let it pass! I will definitely check it! Thanks for your hard work!! :+1: