Untitled

 avatar
unknown
plain_text
23 days ago
8.8 kB
56
Indexable
import psutil
import os
import ctypes
import time
import logging
import sys
import tkinter as tk
from tkinter import ttk, messagebox
from threading import Thread, Event
from ttkthemes import ThemedTk

# Настройка логирования
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler("memory_optimizer.log"),  # Логирование в файл
        logging.StreamHandler()  # Логирование в консоль
    ]
)

# Глобальная переменная для остановки оптимизации
stop_event = Event()

# Функция для очистки кэша файловой системы (только для Windows)
def clear_file_system_cache():
    if os.name == 'nt':  # Проверяем, что система Windows
        try:
            # Очистка кэша файловой системы
            ctypes.windll.kernel32.SetSystemFileCacheSize(-1, -1, 0)
            ctypes.windll.kernel32.SetSystemFileCacheSize(0, 0, 0)
            logging.info("File system cache cleared.")
        except Exception as e:
            logging.error(f"Failed to clear file system cache: {e}")

# Функция для освобождения неиспользуемой памяти процессов (только для Windows)
def empty_working_set():
    if os.name == 'nt':  # Проверяем, что система Windows
        try:
            # Получаем список всех процессов
            for proc in psutil.process_iter(['pid', 'name']):
                try:
                    # Получаем дескриптор процесса
                    process_handle = ctypes.windll.kernel32.OpenProcess(
                        0x1F0FFF,  # PROCESS_ALL_ACCESS
                        False,     # Не наследуемый
                        proc.info['pid']
                    )
                    if process_handle:
                        # Освобождаем неиспользуемую память
                        ctypes.windll.psapi.EmptyWorkingSet(process_handle)
                        ctypes.windll.kernel32.CloseHandle(process_handle)
                        log_message = f"Freed memory for process: {proc.info['name']} (PID: {proc.info['pid']})"
                        logging.info(log_message)
                        update_process_list(log_message)  # Обновляем список процессов в интерфейсе
                except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                    continue
        except Exception as e:
            logging.error(f"Failed to empty working set: {e}")

# Функция для уменьшения приоритета процессов
def reduce_process_priority():
    for proc in psutil.process_iter(['pid', 'name']):
        try:
            process = psutil.Process(proc.info['pid'])
            # Устанавливаем низкий приоритет
            process.nice(psutil.BELOW_NORMAL_PRIORITY_CLASS)
            logging.info(f"Reduced priority for process: {proc.info['name']} (PID: {proc.info['pid']})")
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            continue

# Функция для получения информации о памяти
def get_memory_info():
    memory = psutil.virtual_memory()
    logging.info(f"Total Memory: {memory.total / (1024 ** 3):.2f} GB")
    logging.info(f"Available Memory: {memory.available / (1024 ** 3):.2f} GB")
    logging.info(f"Used Memory: {memory.used / (1024 ** 3):.2f} GB")
    logging.info(f"Memory Percentage: {memory.percent}%")

# Основная функция оптимизации
def optimize_memory(interval):
    while not stop_event.is_set():
        try:
            logging.info("\nMemory info before optimization:")
            get_memory_info()

            # Очистка кэша файловой системы
            logging.info("Clearing file system cache...")
            clear_file_system_cache()

            # Освобождение неиспользуемой памяти процессов
            logging.info("Freeing unused memory for processes...")
            empty_working_set()

            # Уменьшение приоритета процессов
            logging.info("Reducing process priority...")
            reduce_process_priority()

            logging.info("Memory info after optimization:")
            get_memory_info()

            # Пауза перед следующей итерацией
            logging.info(f"Waiting for the next iteration in {interval} seconds...")
            time.sleep(interval)

        except Exception as e:
            logging.error(f"An error occurred: {e}")
            time.sleep(interval)

# Функция для обновления списка процессов в интерфейсе
def update_process_list(message):
    process_list.insert(tk.END, message)
    process_list.yview(tk.END)  # Автоматическая прокрутка вниз

# Функция для запуска оптимизации в отдельном потоке
def start_optimization():
    try:
        interval = int(interval_entry.get())
        if interval <= 0:
            messagebox.showerror("Ошибка", "Интервал должен быть больше 0.")
            return
        stop_event.clear()  # Сбрасываем флаг остановки
        optimization_thread = Thread(target=optimize_memory, args=(interval,), daemon=True)
        optimization_thread.start()
        start_button.config(state=tk.DISABLED)
        stop_button.config(state=tk.NORMAL)
        interval_entry.config(state=tk.DISABLED)
    except ValueError:
        messagebox.showerror("Ошибка", "Введите корректное число для интервала.")

# Функция для остановки оптимизации
def stop_optimization():
    stop_event.set()  # Устанавливаем флаг остановки
    start_button.config(state=tk.NORMAL)
    stop_button.config(state=tk.DISABLED)
    interval_entry.config(state=tk.NORMAL)
    logging.info("Optimization stopped.")

# Создание графического интерфейса
root = ThemedTk(theme="equilux")  # Темный стиль
root.title("Memory Optimizer")
root.geometry("500x400")  # Увеличенное окно
root.resizable(False, False)  # Запрет изменения размера окна

# Настройка стилей
style = ttk.Style()
style.configure("TFrame", background="#2d2d2d")
style.configure("TLabel", background="#2d2d2d", foreground="white", font=("Arial", 10))
style.configure("TButton", padding=10, font=("Arial", 10), background="#3d3d3d", foreground="white")
style.configure("TEntry", font=("Arial", 10), fieldbackground="#3d3d3d", foreground="white")

# Верхняя часть интерфейса
top_frame = ttk.Frame(root, padding="10")
top_frame.pack(fill=tk.X)

interval_label = ttk.Label(top_frame, text="Интервал очистки (секунды):")
interval_label.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)

interval_entry = ttk.Entry(top_frame, width=10)
interval_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)
interval_entry.insert(0, "60")  # Значение по умолчанию

start_button = ttk.Button(top_frame, text="Запустить", command=start_optimization)
start_button.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)

stop_button = ttk.Button(top_frame, text="Стоп", command=stop_optimization, state=tk.DISABLED)
stop_button.grid(row=0, column=3, padx=5, pady=5, sticky=tk.W)

# Нижняя часть интерфейса (список процессов)
process_list = tk.Listbox(root, height=15, font=("Arial", 10), bg="#2d2d2d", fg="white", selectbackground="#4d4d4d")
process_list.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

# Проверка прав администратора (только для Windows)
if os.name == 'nt':
    try:
        if not ctypes.windll.shell32.IsUserAnAdmin():
            messagebox.showerror("Ошибка", "Программа требует прав администратора.")
            sys.exit(1)
    except Exception as e:
        logging.error(f"Failed to check admin rights: {e}")
        sys.exit(1)

# Запуск основного цикла интерфейса
root.mainloop()
Editor is loading...
Leave a Comment