« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга


ПнВтСрЧтПтСбВс
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
    Популярное
Гостевая книга на ASP.NET

Построение систем автоматического протоколирования Си/Си++ кода

Перехват ICQ паролей

Функция AccessResource

Управление проектом с помощью меню

Защита листа

Первая программа

Типы данных, определяемые программистом

Передача данных шлюзу

Функция date() - вывод даты и времени в PHP




    Архив файлов



    Сообщества

    Документация

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 171
Пользователей: 1
  • AlexBass

  • Статьи:: Базы данных :: Microsoft FoxPro :: Начало работы с Visual FoxPro :: Быстродействие программ на VFP



    отправить ссылку другу версия для печати  Обсудить на форуме

    Быстродействие программ на VFP

    Основная часть этой статьи была написана, когда автор пытался ускорить расчеты, выполнявшиеся около получаса. В результате время работы процедуры сократилось до нескольких минут :-)



    Здесь вы можете скачать тексты демонстрационных программ.

    Важное замечание
    Скорость загрузки программы
    Rushmore
    Навигационный и реляционный подходы
    Оптимизация запросов
    Нормализация БД
    Алгоритм
    Скорость выполнения отдельных команд
    Пример
    Как успокоить пользователя
    Тестирование
    Благодарности

    Важное замечание

    Наши пользователи хотят, чтобы программы выполнялись максимально быстро. Но часто бывает, что быстродействие может быть достигнуто в ущерб другим требованиям, например универсальности, модифицируемости или надежности кода. Далеко не всегда стоит добиваться максимальной производительности. Бывает, что код настолько усложняется, что вы рискуете потерять контроль над своей "супер-быстрой" программой. Так же не стоит отказываться от проверок входящих параметров. Сэкономленные секунды могут обернуться долгими часами, потраченными на ликвидацию последствий незначительной ошибки.

    Скорость загрузки программы

    Если пользователи жалуются на слишком длительную загрузку форм, вы можете предпринять следующие действия:

    • Загружайте элементы интерфейса только тогда, когда в них появится необходимость. Это могут быть элементы на неактивных закладках PageFrame, скрытые узлы Treeview, или невидимые формы в FormSet. Практически любой набор объектов можно поместить в контейнер, сохранить его, как класс, а в нужный момент создать экземпляр этого класса.

       
    • Можно поступить "с точностью до наоборот" - при загрузке программы создать самые тяжелые и часто используемые объекты, и сделать их невидимыми до определенного момента. Обращали внимание, как долго загружается программа 1С? Зато потом скорость работы вполне приемлемая. Это пример такого подхода.

       
    • Установите последние обновления. В моей практике было, когда для первоначального открытия десяти таблиц на сервере Novell требовалось полминуты. После установки на рабочих станциях патча для работы с Novell открытие таблиц стало происходить мгновенно.

       

    Rushmore

    Вы уже знаете про оптимизацию Rushmore. Вот наиболее частые ошибки, при которых оптимизация перестает работать:

    • Не совпадает Set Collate (в индексах таблицы используется Russian, а системная установка - Machine)

       
    • Заведен индекс с условием FOR ...

       
    • Выражение для поиска не совпадает с индексным. Часто допускают такую ошибку. У таблицы есть индекс по UPPER(cField1). Для поиска пустого значения используют условие EMPTY(cField1) = .T., что не совпадает с индексным выражением. Для того, чтобы поиск был оптимизированным, выражение должно выглядеть как UPPER(cField1) = SPACE(N), где N - длина поля cField1.

       

    Навигационный и реляционный подходы

    В FoxPro сосуществуют два подхода к обработке данных - навигационный и реляционный.Навигационные команды - это Locate, Seek, Set Relation, Set Order, GoTo. Основная реляционная команда - Select SQL. Скорость выполнения запросов SQL весьма высока, однако во многих случаях навигационный подход работает еще быстрее.

    Пример поиска максимального значения поля различными способами:

    *** поиск с помощью Select SQL
    Select MAX(Field1) as MaxField From Table1 Into Cursor _Temp
    ? _Temp.MaxField
    
    *** а так выполнится значительно быстрее 
    (необходимо наличие индекса по полю Field1)
    Select Table1
    Set Order To Field1
    Go Bottom
    ? Field1
     

    Оптимизация запросов

    Запросы на FoxPro могут выполняться долго, если в них участвует больше трех-четырех таблиц. Речь идет именно о запросах к родным БД на dbf, а не о запросах, отправляемых на сервер. Мне не удавалось увеличить скорость путем разбиения большого запроса на несколько последовательно выполняемых подзапросов. С другой стороны, эффект от разбиения может зависеть от количества и распределения информации в связанных таблицах. Поэтому результаты могут отличаться. Можно выйти из положения, исключая из запроса справочные таблицы (например, ФИО сотрудников), и привязывая их к результату через Set Relation, смешивая таким образом "реляционный" и "навигационный" подходы.

    Использование Outer join снижает скорость выполнения запроса. Если нет прямой необходимости в этой опции, лучше переписать запрос без нее. Как вариант - если у вас есть строки, не имеющие соответствия в связанной таблице, и потому содержащие .NULL., добавьте в связанную таблицу строку с нулевым кодом, а в основной - замените пустые значения на этот нулевой код.

    Подзапросы вида Where Field1 in (Select ... ) или Where Exists (Select ... ) могут замедлить скорость выполнения запроса (хотя это зависит от многих параметров). Если такой запрос выполняется слишком медленно - попробуйте переписать его с использованием простого объединения.

    Для большего быстродействия располагайте первыми те условия, которые максимально сужают область дальнейшего поиска.

    Для анализа оптимальности SQL-запроса воспользуйтесь функцией Sys(3054). Имейте в виду, что если у таблиц нет индексов по Deleted(), эта команда будет показывать частичную оптимизацию, даже если фактически они вносят отрицательный вклад в скорость выполнения запроса. Этот эффект подробно описан Владимиром Максимовым.

    Нормализация БД

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

    Например, в справочнике клиентов есть поле "Город". Исходя из принципов нормализации, необходимо завести таблицу - справочник городов. Так как названия городов меняются нечасто, в таблице клиентов вместо кода города можно записывать его название. Это позволит уменьшить количество таблиц в запросах, но потребует аккуратности, если название города все-таки изменилось, или в нем была допущена ошибка.

    Другой вариант - предварительные расчеты. Например, с помощью триггеров можно заранее пересчитывать суммарные данные о продажах за день в момент добавления или корректировки нового счета. К примеру, пусть счета хранятся в таблице Invoices, а данные о продажах за день - в таблице DailySales. Тогда в триггеры таблицы Invoices нужно добавить примерно такой код:

    *** для триггера Insert
    Update DailySales Set TolalSum = TolalSum + Invoices.InvoiceSum 
    Where DailySales.SalesDate = Invoices.InvoiceDate
    
    *** для триггера Update
    Update DailySales Set TolalSum = TolalSum + Invoices.InvoicesSum - 
    OldVal(Invoices.InvoiceSum) Where DailySales.SalesDate = Invoices.InvoiceDate
    
    *** для триггера Delete
    Update DailySales Set TolalSum = TolalSum - Invoices.InvoiceSum 
    Where DailySales.SalesDate = Invoices.InvoiceDate
    
     

    Естественно, сам код триггеров будет намного сложнее. Кроме приведенных строк там необходимы проверки, обработка ошибок и т.д.

    Если вы решите идти по такому пути, не забудьте написать процедуру синхронизации, если из-за сбоев предварительные расчеты станут отличаться от основных.

    Алгоритм

    Как правило, стройный и понятный алгоритм выполняется быстрее всего, хотя бывают исключения. С другой стороны, применяя "обходные маневры" вы можете потерять возможность исправить что либо в коде, когда условия изменятся.

    Вот несколько общих советов:

    • Вынесите за пределы циклов однократно выполняемые установки типа Set deleted, Set exact, и т.д.

       
    • Поместите проверки в начало подпрограммы. Это позволит не выполнять лишние действия, если проверки окончатся неудачно.

       
    • Освобождайте память от объектов и таблиц, которые вам больше не понадобятся.

       
    • Если позволяют технические возможности, перенесите наиболее тяжелые расчеты на другой компьютер, воспользовавшись технологией DCOM.

       

    Скорость выполнения отдельных команд

    Скорость выполнения отдельных команд приобретает критическое значение, когда они выполняются в цикле, и доли секунды, за которые выполняется команда, умножаются в тысячи, если не в сотни тысяч раз. Так же бывает важным максимально сократить время работы триггеров, чтобы не тормозить операции с таблицей. Вот некоторые приемы:

    • Поиск записей с помощью команды Seek выполняется примерно в 5-10 раз быстрее, чем с помощью Locate. Команда Locate гибче, так как не требует индекса (но может использовать его для оптимизации), и кроме того, позволяет указывать несколько условий, например ClientID = X AND InvoiceDate = Y. Для максимально быстрого поиска по нескольким полям вы можете завести сложный индекс типа STR(ClientID, 10, 0) + DTOS(InvoiceDate), и осуществлять поиск с помощью Seek STR(X, 10, 0) + DTOS(Y). Но учтите, что этот прием усложняет модификацию кода, т.к. требует существенных изменений из-за локальной проблемы.

       
    • Если нужно только проверить наличие строк, удовлетворяющих условию, но нет необходимости перемещать указатель на эти строки, воспользуйтесь функцией IndexSeek() (она появилась в VFP начиная с 6-й версии).

       
    • Стандартные функции VFP хорошо оптимизированы и выполняются достаточно быстро. Например, условиями задачи требуется найти цифру, входящую в текстовую строку. Можно перебирать текстовую строку в поисках цифр
      For I = 1 to LEN(cText)
      
      	If ISDIGIT(SUBSTR(cText, m.I,1))
      		? m.I
      		Exit
      	EndIf
      
      EndFor
      Более быстрый вариант с использованием стандартных функций:
      cText1 = STRTRAN(cText, "123456789", "0")
      ? AT(cText1, "0")
    • Команда Scan...EndScan оптимизирует перебор записей таблицы даже без индекса. Там где это возможно, используйте ее вместо конструкции Do While not EOF() ... Skip ... EndDo.

       
    • Выполнение команд Locate, Scan For.., Set Filter to.. замедлится, если у таблицы установлен активный индекс. Отключите индекс командой Set Order to без параметров, если нет необходимости в сортировке данных.

       
    • Вместо макроподстановки & используйте выражения имени ( ) и функцию EVALUATE(). Разница между ними в следующем. Выражения имени можно использовать там, где Fox ожидает увидеть имя переменной или поля. Функция EVALUATE() может быть использована в операциях присвоения и вычислениях.
      X = "Var1"
      Y = "Var2"
      
      Store EVALUATE(X) to (Y) && так быстрее
      
      &Y = &X && эта команда сделает то же, что и предыдущая, но существенно медленнее.
      Макроподстановка уместна, когда вам нужно вставить в код сложную команду, например сформированную строку запроса SQL.
      *** пример использования макроподстановки ***
      
      OldSettings = Set("TALK") && запоминаем текущую установку
      Set Talk OFF
      ...
      Set Talk &OldSettings && возвращаем прежнее состояние
    • Скорость обращения к переменным выше, чем к свойствам объектов. Если значение какого-то свойства используется многократно, присвойте это значение переменной.

       
    • Подавление системных сообщений с помощью команд Set Talk off, Set Notify off (в последних версиях еще и Set Notify Cursor off) может существенно ускорить процесс.

       
    • Команда Goto nRecordNo выполняется практически мгновенно. Если вам нужно вернуться к какой-либо записи в таблице, переход по номеру записи отработает намного быстрее, чем поиск по идентификатору с помощью Seek или Locate.

       
    • Если вам необходимо просканировать некоторый диапазон значений в таблице, и по этим значениям есть индекс, вы можете воспользоваться приемом, известным как "Set Order + Seek + Scan while".
      Set Order to Field1
      Seek StartValue && устанавливаем указатель на начало диапазона
      Scan While Field1 =< EndValue && перебираем строки до конца диапазона
      ...
      EndScan
      Этот код работает быстрее, чем Scan for Between( Field1, StartValue, EndValue ), но проигрывает ему в читабельности, и кроме того, требует установки активного индекса.

       
    • Сложение текстовых строк происходит быстрее, если к длинной строке добавлять короткую, а не наоборот. То есть
      *** этот код выполнится быстро
      x = ""
      For i = 1 to 10000
      	x = x + Sys(3)
      EndFor
      
      *** а этот - медленно
      x = ""
      For i = 1 to 10000
      	x = Sys(3) + x
      EndFor
      Другими словами, если вам потребуется сложить некоторые значения в обратном порядке, лучше сначала отсортировать их по убыванию, и затем складывать.

       
    • Для поиска "узких мест" воспользуйтесь командой Set Coverage to. Эта команда создаст текстовый файл, в котором будет записано время выполнения каждой строки. Вы можете сохранить этот файл в таблицу, и проанализировать ее. Либо воспользоваться Coverage profiler из дистрибутива Visual FoxPro.

       

    Вы можете самостоятельно сравнить скорость работы различных команд с помощью тестовых примеров.

    Пример

    Предположим, вам необходимо всем клиентам, у которых есть заказ в предыдущем месяце, предоставить скидку 10% на будущие заказы. Данные о заказах хранятся в таблице Invoices, а информация о скидке - в таблице Clients.

    New_Discount = 0.10 && скидка, которую мы хотим предоставить
    
    PrevDate = GoMonth(Date(), -1)
    PrevMonth = Month(PrevDate) && предыдущий месяц
    PrevYear = Year(PrevDate) && год, в котором был предыдущий месяц
    
    
    Go top in Clients
    Do while not EOF("Clients") && перебор записей в таблице клиентов
    
    	Go top in Invoices
    
    	Do while not EOF("Invoices") && перебор записей в таблице счетов
    
    		If Invoices.ClientID = Clients.ClientID AND ;
    		Year(Invoices.InvoiceDate) = PrevYear AND ;
    		Month(Invoices.InvoiceDate) = PrevMonth
    
    			Replace Clients.Discount with New_Discount
    			Exit
    
    		EndIf
    
    		Skip in Invoices
    
    	EndDo
    
    	Skip in Clients
    
    EndDo
     

    Приведенный код логически верен, но абсолютно не оптимизируем.

    Попробуем переписать этот код:

    Month_End = Date() - Day(Date()) && последний день предыдущего месяца
    Month_Start = Month_End - Day(Month_End) + 1 && первый день предыдущего месяца
    
    Select Clients
    
    Scan
    	Select Invoices
    	Locate for ClientID = Clients.ClientID AND Between(InvoiceDate, Month_Start, Month_End)
    
    	If Found("Invoices")
    		Replace Clients.Discount with New_Discount
    	Endif
    EndScan
     

    Перебор записей таблицы Clients осуществляется командой Scan. Поиск в таблице Invoices может быть оптимизирован с помощью индексов по полям ClientID и InvoiceDate. Этот вариант будет выполняться существенно быстрее.

    Для реализации следующего варианта необходимо, чтобы у таблицы Invoices существовал особый индекс:

    Index on STR(ClientID, 10,0) + DTOS(InvoiceDate) tag MIXED
    ...
    ...
    ...
    Set Exact OFF
    
    LastMonth  = LEFT(DTOS( GOMONTH(DATE(), -1) ), 6) && год и месяц в формате "YYYYMM"
    
    Select Clients
    Replace Clients.Discount with New_Discount For IndexSeek( STR(ClientID, 10,0) + m.LastMonth, .F., 
    "Invoices", "MIXED" )
     

    Поиск в таблице Invoices осуществляется по индексу, поэтому этот пример отработает еще быстрее. Но индекс весьма специфический, и не может быть применен для других вычислений. Кроме того, даже автору это кода этого потребуется немало времени, чтобы спустя полгода разобраться, что именно он делает :-)

    Решение с использованием команд SQL:

    Update Clients Set Discount = New_Discount Where Exists ;
    (Select * From Invoices Where ;
    Invoices.ClientID = Clients.ClientID AND ;
    Invoices.InvoiceDate BETWEEN Month_Start AND Month_End)
     

    Возможно, данный вариант не выиграет с точки зрения скорости по сравнению с предыдущим, но он гораздо понятнее. Если время выполнения запроса находится в разумных пределах, я бы остановился именно на нем. К сожалению, такой синтаксис команды SQL-Update возможен только в VFP9.

    Здесь вы можете скачать исходные тексты примеров.

    Как успокоить пользователя, пока выполняется программа

    Если программа в течение минуты не будет подавать признаков жизни, у пользователей возникает жгучее желание нажать Ctrl+Alt+Del, и прервать процесс. Вам необходимо позаботиться об информировании пользователя о состоянии дел. Вот варианты.

    Если расчеты многоступенчатые, перед каждым этапом выводите либо в статус-бар, либо в окно информацию

    Wait window "Этап 1: Проверка данных" nowait
    ...
    Wait window "Этап 5: Суммирование данных за год" nowait
    ...
    Wait window "Этап 10: Окончательное форматирование" nowait
    ...
    Wait clear
     

    Очень полезным может оказаться следующий прием. Запоминайте, сколько времени в секундах длился расчет в прошлый раз, и используйте эти данные для текущего расчета. В самом простом случае можно вывести сообщение

    Wait window "Расчет продлится примерно до " + Transform(DateTime() + Duration) nowait
    Сохранять эту информацию нужно локально, так как скорость вычислений зависит от возможностей данной рабочей станции. Если длительность расчета зависит от каких-то параметров, вы можете экстраполировать данные пропорционально им. Например, если пользователь указывает диапазон дат, разделите длительность процесса на количество дней в диапазоне, и получите длительность в расчете на один день. В следующий раз, когда пользователь введет другой диапазон, умножьте сохраненный результат на новое количество дней, и получите экстраполяцию, сколько будут длиться вычисления. Время, естественно, будет очень приблизительным, но это в любом случае поможет пользователю оценить, сколько чашечек кофе он успеет выпить :-)  

    Для полноты картины можете вывести прогресс-бар. Однако имейте в виду, что любые украшательства требуют системных ресурсов. Так что не переусердствуйте.

    У многих программистов возникает желание написать свой прогресс-бар для запросов. Увы, единственный известный работающий пример - это стандартный "градусник", который выводится при выполнении долгого запроса, если перед этим была дана команда Set Talk on. Все другие решения приводили к многократной задержке в обработке данных.

    Тестирование

    Советы уважаемых гуру, и даже выдержки из HELP не дают гарантий, что именно ваш случай не будет редким, но исключением из общих правил. Скорость работы может зависеть от сервера и сети, от активности пользователей, от объема и частотного распределения данных. Самый хороший способ определить, насколько быстро будет выполняться программа - провести тесты, максимально приближенные к реальности. Использование тестов только кажется сложным. Нет ничего сверхъестественного в том, чтобы сгенерировать табличку, близкую по размерам к максимальному ожидаемому размеру реальной БД, и попробовать поработать. В генерации тестовых данных вам помогут функции RAND(), SYS(3) и SYS(2015), а так же любой осмысленный текст, например kladr - классификатор адресов России. Вы легко можете найти его в Интернете. Для большей достоверности постарайтесь, чтобы данные не были физически отсортированы по какому-либо полю.

    *** Генерация тестовой таблицы ***
    
    =RAND(-1) &&  HELP рекомендует перед началом работы вызвать RAND() с отрицательным параметром
    
    For nCount = 1 to BigNumber && число добавляемых записей
    
    	*** пример генерации случайного числа от 1 до 1000
    	nRandomValue = CEILING(1000 * RAND())
    
    	*** а так можно заполнять почтовые индексы и номера телефонов
    	cZipCode = PADR(CEILING(999999 * RAND()), 6, "0")
    
    	*** поиск случайной записи в связанной таблице
    	Goto CEILING(RECCOUNT("ChildTable") * RAND() ) in ChildTable
    	RelatedTableValue = ChildTable.Field1
    
    	*** пример генерации случайного адреса
    	Goto CEILING(RECCOUNT("Towns") * RAND() ) in Towns
    	Goto CEILING(RECCOUNT("Streets") * RAND() ) in Streets
    
    	cAddress = ALLTRIM(Towns.Name) + ", " + ALLTRIM(Streets.Name) + 
    	", дом " + TRANSFORM( CEILING(200 * RAND()) )
    
    	*** Вставляем полученные данные в таблицу
    	Insert into BigTable (...) values (nRandomValue, cZipCode, cAddress, RelatedTableValue)
    
    EndFor
     

    Регулярное проведение тестов имеет еще одну приятную особенность. Пока выполняется тест, вы имеете полное право откинуться на спинку стула, и несколько минут наслаждаться полным бездельем ;-)

    Благодарности

    В работе над статьей принимали участие члены Фокс-Клуба
    Владимир Максимов
    Игорь Королев
    Alex Shustikov
    is

    Автор: Игорь Ильин
    Источник:www.foxclub.ru








    HTML 5: пять вещей вызывающих особый интер....

    Html

    HTML 5 — это грядущее обновление гипертекстового языка разметки, основного способа создания контента для размещения его во всемирной паутине. Разработка HTML остановилась в 1999 году, на версии HTML 4.01 и с тех пор web-содержимое изменилось так, что текущие спецификации HTML перестали соответствовать сегодняшним требованиям. HTML 5 нацелен на то, чтобы увеличить функциональную совместимость HTML и соответствовать растущим требованиям разнообразного и смешанного web-контента. HTML 5 так же нацелен на устранение недостатков четвертой версии. В этой статье мы взглянем на 5 новых интересных вещей в HTML 5.


    Подробнее... | Рубрика: Html | Добавлено: 22.12.2008

    asp.net: ListView с разных сторон.

    .NET компоненты

    Элемент управления ListView был представлен в .Net Framework 3.5 как замена устаревшему GridView. Новый элемент имеет более расширенный функционал, чем его предшественник, но в тоже время лишен некоторых внутренних механизмов, что впрочем целиком следствие из расширенной универсальности ListView. Среди отличий ListView и GridView можно назвать и гибкую настройку разметки, что позволяет выводить данные не только в табличном виде, но и вообще в любом каком пожелает программист. Благодаря шаблонам ItemTemplate, EditItemTemplate, InsertItemTeplate можно настроить внешний вид при любом из состояний ListView: редактировании или выборе элемента.


    Подробнее... | Рубрика: .NET компоненты | Добавлено: 22.12.2008

    Создание кросс-таб отчета в Stimulsoft Rep....

    .NET компоненты

    Компания Стимулсофт предоставляет для разработчиков мощный набор инструментов для создания отчетов для Microsoft Visual Studio .Net 2005 и 2008; эти инструменты доступны как для Windows Forms, так и для Web Forms. Это генератор отчетов Stimulsoft Reports.Net. Генератор отчетов Stimulsoft Reports.Net имеет ряд особенностей: простая работа с дизайнером отчетов, полная поддержка экспорта в PDF, Word, Excel и многие другие форматы. Crystal Report и Microsoft Reporting Service – очень хорошие программные продукты для повседневной работы, но, если Вам необходимо создать отчеты с поддержкой кросс-табов, drill down, Ajax, штрих-кодов и возможностью подключения одновременно более одного источника данных, то Stimulsoft Reports.Net поможет Вам сэкономить массу времени. Также, данный генератор отчетов позволяет пользователям создавать свои собственные отчеты любой сложности. И все эти особенности делают Stimulsoft Reports.Net хорошим выбором в сфере программных продуктов для Business Intelligence.


    Подробнее... | Рубрика: .NET компоненты | Добавлено: 22.12.2008

    Остальные статьи:

    VivaMP - инструмент для OpenMP
    Создаем контекстно-зависимое WPF-приложени...
    Windows Vista SP2: что внутри и что важно?
    Вышел MySQL 5.1.30, первый стабильный рели...
    Тестирование параллельных программ
    Архитектура AMD64 (EM64T)
    Платформа 2009. Определяя будущее
    Windows Vista Bridge Sample Library - упра...
    Оптимизация 64-битных программ
    Подгрузка через AJAX HTML-кода, содержащег...
    Обзор нового релиза самой мощной Ajax библ...
    Firebug 1.3 и 1.4 alpha — что нового и инт...
    Релиз Microsoft Silverlight 2.0. Что новог...
    XML документация в C#
    Курсоры в MySQL 5
    Microsoft опубликовала подробности о сесси...
    Microsoft делится подробностями о том, что...
    Тестируем новый javascript от нового брауз...
    MySQL Query Cache
    Использование провайдеров компиляции в As...


    Цитата дня (все,добавить):

    Портал фрилансеров

    работа на дому


        Рубрикатор

    Программирование

    C/С++
    Обучение
    Windows API
    XAML
    Моделирование
    Паттерны
    Visual Basic 7 .NET
    WxWidgets
    Функции WinApi
    Функции С++
    Разработка под Mac OS
    Eiffel
    Visual Studio 2008
    UI дизайн
    Алгоритмы
    Конкурсные статьи
    Turbo Pascal
    Visual Studio
    CASE-средства
    Visual Studio 2005
    Без VCL
    Delphi
    Тех. документация
    Тестирование
    Software Testing
    ООП
    TCP/IP
    Google Android
    Windows Installer
    .NET Framework
    Драйвера
    C# C Sharp
    Справка
    Проектирование
    Информ. системы
    Visual Basic
    Assembler
    Оптимизация кода
    Gtk+
    Компоненты
    Реинжиниринг
    Управление проектами
    Extreeme programming
    Lotus Notes
    Алгебраическое проектирование


    Интернет технологии

    PHP
    Perl
    ASP
    WAP
    Cookies
    SSI
    CGI
    Web Servers
    VB Script
    DNS
    CSS
    XML
    Html
    Java Script
    Java2ME
    Firewall
    Flash
    .htaccess
    Apache
    VRML
    Протоколы
    Поисковые системы
    Технология JAVA
    Учебник по PHP
    Учебник по JavaScript
    Учебник по XML
    Java Q&A
    AJAX
    DHTML
    XHTML
    Dreamweaver
    Web 2.0
    Python
    Вебмастеру
    Cisco
    Ruby on Rails
    Silverlight

    Базы данных

    Access
    InterBase
    MySQL
    Oracle
    ADO .NET
    Основы SQL
    Учебник по Access 2002
    MS
    Microsoft FoxPro
    Доступ к данным
    XML в MS SQL Server 2000
    ODBC и MyODBC
    Обучение
    Caché
    DB2
    PostgresSQL
    Sybase
    Теория
    Хранилища данных
    Безопасность
    Реляционные данные
    MySQL и mSQL

    Остальное:

    Разное
    Обзоры книг
    Безопасность
    Графика и дизайн
    Юмор
    Linux
    Фракталы
    Microsoft Axapta
    Многоядерность
    Сети
    Microsoft Office
    Работа
    MS-DOS
    Криптография
    Графика и игроделание
    Новости SDK
    Системы защиты
    Учебник по AutoCad
    CVS
    Windows XP
    Windows Server 2003
    Windows Vista
    Windows 7
    Мероприятия