ESP32 Arduino Firmware becomes huge with BLE

Hallo,

I am new to ESP32 and I’ve never worked with BT(E) before, but I’ve some experience with Arduino.
I bought the Doit ESP32 DevKit.

The first big question for me was to choose the proper framework.
I decided to go for framework = arduino, espidf as it’s somewhat of a compatibility mode. I can have all the low level APIs from esp-idf but most the time I can use the Arduino libs.

I created a test project and trying to establish a BLE connection with a smartphone/computer to exchange data. I’ve huge configuration files and it’s probably a good idea to send the whole yml in a next step via BLE.

I created a small test project and followed some examples I’ve found on Github.
The first thing, I find strange, is that ~73% of my flash memory is gone, when using BLE. Is that possible?

Processing esp32doit-devkit-v1 (platform: espressif32; board: esp32doit-devkit-v1; framework: arduino, espidf)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32doit-devkit-v1.html
PLATFORM: Espressif 32 (5.2.0) > DOIT ESP32 DEVKIT V1
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - framework-arduinoespressif32 @ 3.20005.220925 (2.0.5) 
 - framework-espidf @ 3.40402.0 (4.4.2) 
 - tool-cmake @ 3.16.4 
 - tool-esptoolpy @ 1.40201.0 (4.2.1) 
 - tool-ninja @ 1.9.0 
 - toolchain-esp32ulp @ 1.22851.191205 (2.28.51) 
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch3
Warning! Arduino framework as an ESP-IDF component doesn't handle the `variant` field! The default `esp32` variant will be used.
Reading CMake configuration...
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 2 compatible libraries
Scanning dependencies...
Dependency Graph
|-- InterruptButton @ 1.0.0
Building in release mode
Compiling .pio/build/esp32doit-devkit-v1/src/main.o
Linking .pio/build/esp32doit-devkit-v1/firmware.elf
Retrieving maximum program size .pio/build/esp32doit-devkit-v1/firmware.elf
Checking size .pio/build/esp32doit-devkit-v1/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]  11.3% (used 36944 bytes from 327680 bytes)
Flash: [=======   ]  73.0% (used 765701 bytes from 1048576 bytes)
Building .pio/build/esp32doit-devkit-v1/firmware.bin
esptool.py v4.2.1
Creating esp32 image...
Merged 25 ELF sections
Successfully created esp32 image.

I activated Bluetooth (controller mode BLE only, Bluedroid dual-mode) and used the following code:

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "InterruptButton.h"

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>

InterruptButton button(GPIO_NUM_0, 0);

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks : public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *pCharacteristic)
    {
        std::string value = pCharacteristic->getValue();

        if (value.length() > 0)
        {
            printf("*********\n");
            printf("New value: %s\n", value.c_str());

            // std::string response = "The answer is no!";
            // pCharacteristic->writeValue(response.c_str(), response.length());

            printf("*********\n\n");
        }
    }
};

void configureLed()
{
    gpio_reset_pin(GPIO_NUM_2);
    gpio_set_direction(GPIO_NUM_2, GPIO_MODE_INPUT_OUTPUT);
}

void callback()
{
    uint8_t state = gpio_get_level(GPIO_NUM_2);
    printf("Toggeling LED: %i\n", state);
    gpio_set_level(GPIO_NUM_2, !state);
}

extern "C" void app_main()
{
    configureLed();
    button.bind(Event_KeyDown, &callback);

    BLEDevice::init("MyESP32");
    BLEServer *pServer = BLEDevice::createServer();

    BLEService *pService = pServer->createService(SERVICE_UUID);

    BLECharacteristic *pCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ |
            BLECharacteristic::PROPERTY_WRITE);

    pCharacteristic->setCallbacks(new MyCallbacks());
    pService->start();

    BLEAdvertising *pAdvertising = pServer->getAdvertising();
    pAdvertising->start();

    while (1)
    {
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
}

Ok, I figured out, that Bluedroid is huge due to the BLE and classic stack.
I am now using NimBLE, but still utilizing ~50% of flash with only ~100 lines of my own code.
Is that normal? Are there better options?

RAM:   [=         ]   9.2% (used 30024 bytes from 327680 bytes)
Flash: [=====     ]  53.9% (used 564825 bytes from 1048576 bytes)