На которых платформах ограничена локальная память потока и сколько доступно?

Я второй комментарии Разработчика SQL. FWIW, более новые версии Жабы намного более стабильны, чем золотые старые произведения были. Я использую Жабу 9.7, и это довольно хорошо.

15
задан Joseph Garvin 22 September 2009 в 15:11
поделиться

6 ответов

В Linux, если вы используете __ thread данные TLS, единственное ограничение устанавливается вашим доступным адресным пространством. , поскольку эти данные просто выделяются как обычная оперативная память, на которую ссылаются дескрипторы сегментов gs (на x86) или fs (на x86-64). Обратите внимание, что в некоторых случаях выделение данных TLS, используемых динамически загружаемыми библиотеками, может быть исключено в потоках, которые не используют эти данные TLS.

TLS выделен pthread_key_create и другими , однако, ограничен слотами PTHREAD_KEYS_MAX (это относится ко всем соответствующим реализациям pthreads).

Для получения дополнительной информации о реализации TLS в Linux,

11
ответ дан 1 December 2019 в 04:27
поделиться

Может случиться так, что в документации по ускорению просто говорится об общем настраиваемом лимите, а не обязательно о жестком ограничении платформы. В Linux команда ulimit ограничивает ресурсы, которые могут иметь процессы (количество потоков, размер стека, память и множество других вещей). Это косвенно повлияет на локальное хранилище вашего потока. В моей системе, похоже, нет записи в ulimit, специфичной для локального хранилища потоков. У других платформ может быть способ указать это самостоятельно. Кроме того, я думаю, что во многих многопроцессорных системах локальное хранилище потока будет в памяти, выделенной для этого процессора, поэтому вы можете столкнуться с ограничениями физической памяти задолго до того, как вся память в системе будет исчерпана. Я бы предположил, что в этой ситуации есть какое-то резервное поведение для поиска данных в основной памяти, но я не знаю. Как видите, я о многом гадаю. Надеюсь, он по-прежнему ведет вас в правильном направлении ...

0
ответ дан 1 December 2019 в 04:27
поделиться

Я использовал TLS только в Windows, и между версиями есть небольшие различия в том, сколько можно использовать: http://msdn.microsoft.com/en-us/library/ms686749 (VS.85) .aspx

Я предполагаю, что ваш код нацелен только на операционные системы, поддерживающие потоки - в прошлом я работал со встроенными и настольными ОС, которые не поддерживают потоки, поэтому не поддерживают TLS.

3
ответ дан 1 December 2019 в 04:27
поделиться

Declspec локального хранилища потока в Windows ограничивает вас использованием его только для статических переменных, что означает, что вам не повезло, если вы хотите использовать его более творческими способами.

Там - это низкоуровневый API в Windows, но у него нарушена семантика, из-за чего его очень неудобно инициализировать: вы не можете сказать, была ли переменная уже видна вашим потоком, поэтому вам нужно явно инициализировать ее при создании

С другой стороны, pthread API для локального хранилища потока хорошо продуман и гибок.

0
ответ дан 1 December 2019 в 04:27
поделиться

Я использую простой шаблонный класс для обеспечения локального хранилища потоков. Это просто обертывает std :: map и критический раздел. Тогда это не страдает от каких-либо локальных проблем потока, специфичных для платформы, единственное требование платформы - получить текущий идентификатор потока, как в целочисленном. Это может быть немного медленнее, чем локальное хранилище собственных потоков, но оно может хранить данные любого типа.

Ниже представлена ​​урезанная версия моего кода. Я удалил логику значений по умолчанию, чтобы упростить код. Поскольку он может хранить данные любого типа, операторы увеличения и уменьшения доступны только в том случае, если T их поддерживает. Критическая секция требуется только для защиты от просмотра и вставки на карту. Как только ссылка будет возвращена, можно безопасно использовать незащищенное, так как только текущий поток будет использовать это значение.

template <class T>
class ThreadLocal
{
public:
    operator T()
    {
        return value();
    }

    T & operator++()
    {
        return ++value();
    }

    T operator++(int)
    {
        return value()++;
    }

    T & operator--()
    {
        return --value();
    }

    T operator--(int)
    {
        return value()--;
    }

    T & operator=(const T& v)
    {
        return (value() = v);
    }

private:
    T & value()
    {
        LockGuard<CriticalSection> lock(m_cs);
        return m_threadMap[Thread::getThreadID()];
    }

    CriticalSection     m_cs;
    std::map<int, T>    m_threadMap;
};

Чтобы использовать этот класс, я обычно объявляю статический член внутри класса, например

class DBConnection {
    DBConnection() {
        ++m_connectionCount;
    }

    ~DBConnection() {
        --m_connectionCount;
    }

    // ...
    static ThreadLocal<unsigned int> m_connectionCount;
};

ThreadLocal<unsigned int> DBConnection::m_connectionCount

Он может быть не идеальным для каждой ситуации, но он удовлетворяет мои потребности, и я могу легко добавить любые недостающие функции по мере их обнаружения.

] bdonlan верен, этот пример не очищается после выхода потока. Однако это очень легко добавить вручную.

template <class T>
class ThreadLocal
{
public:
    static void cleanup(ThreadLocal<T> & tl)
    {
        LockGuard<CriticalSection> lock(m_cs);
        tl.m_threadMap.erase(Thread::getThreadID());
    }

    class AutoCleanup {
    public:
        AutoCleanup(ThreadLocal<T> & tl) : m_tl(tl) {}
        ~AutoCleanup() {
            cleanup(m_tl);
        }

    private:
        ThreadLocal<T> m_tl
    }

    // ...
}

Затем поток, который знает, что он явно использует ThreadLocal , может использовать ThreadLocal :: AutoCleanup в своей основной функции для очистки

Или в случае DBConnection

~DBConnection() {
    if (--m_connectionCount == 0)
        ThreadLocal<int>::cleanup(m_connectionCount);
}

Метод cleanup () является статическим, чтобы не мешать оператору T () . Для его вызова можно использовать глобальную функцию, которая выводит параметры шаблона.

Однако это очень легко добавить вручную.

template <class T>
class ThreadLocal
{
public:
    static void cleanup(ThreadLocal<T> & tl)
    {
        LockGuard<CriticalSection> lock(m_cs);
        tl.m_threadMap.erase(Thread::getThreadID());
    }

    class AutoCleanup {
    public:
        AutoCleanup(ThreadLocal<T> & tl) : m_tl(tl) {}
        ~AutoCleanup() {
            cleanup(m_tl);
        }

    private:
        ThreadLocal<T> m_tl
    }

    // ...
}

Затем поток, который знает, что он явно использует ThreadLocal , может использовать ThreadLocal :: AutoCleanup в своей основной функции для очистки

Или в случае DBConnection

~DBConnection() {
    if (--m_connectionCount == 0)
        ThreadLocal<int>::cleanup(m_connectionCount);
}

Метод cleanup () является статическим, чтобы не мешать оператору T () . Для его вызова можно использовать глобальную функцию, которая выведет параметры шаблона.

Однако это очень легко добавить вручную.

template <class T>
class ThreadLocal
{
public:
    static void cleanup(ThreadLocal<T> & tl)
    {
        LockGuard<CriticalSection> lock(m_cs);
        tl.m_threadMap.erase(Thread::getThreadID());
    }

    class AutoCleanup {
    public:
        AutoCleanup(ThreadLocal<T> & tl) : m_tl(tl) {}
        ~AutoCleanup() {
            cleanup(m_tl);
        }

    private:
        ThreadLocal<T> m_tl
    }

    // ...
}

Затем поток, который знает, что он явно использует ThreadLocal , может использовать ThreadLocal :: AutoCleanup в своей основной функции для очистки

Или в случае DBConnection

~DBConnection() {
    if (--m_connectionCount == 0)
        ThreadLocal<int>::cleanup(m_connectionCount);
}

Метод cleanup () является статическим, чтобы не мешать оператору T () . Для его вызова можно использовать глобальную функцию, которая выведет параметры шаблона.

0
ответ дан 1 December 2019 в 04:27
поделиться

На Mac я знаю о Хранилище для конкретных задач в API Многопроцессорных служб API:

MPAllocateTaskStorageIndex
MPDeallocateTaskStorageIndex
MPGetTaskStorageValue
MPSetTaskStorageValue

Это очень похоже на локальное хранилище потоков Windows.

Я не уверен, рекомендуется ли этот API в настоящее время для локального хранилища потоков на Mac. Возможно есть что-то новее.

1
ответ дан 1 December 2019 в 04:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: