Я обычно использую этот дополнительный метод с анонимными типами для получения рубина крыла словаря
public static Dictionary<string, object> ToDictionary(this object o)
{
var dictionary = new Dictionary<string, object>();
foreach (var propertyInfo in o.GetType().GetProperties())
{
if (propertyInfo.GetIndexParameters().Length == 0)
{
dictionary.Add(propertyInfo.Name, propertyInfo.GetValue(o, null));
}
}
return dictionary;
}
, можно использовать его
var dummy = new { color = "#000000", width = "100%", id = "myid" };
Dictionary<string, object> dict = dummy.ToDictionary();
, И с расширенным методом как
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (T item in source)
{
action(item);
}
}
можно сделать это
dummy.ToDictionary().ForEach((p) => Console.Write("{0}='{1}' ", p.Key, p.Value));
Вывод
цвет = '#000000' ширина = '100%-й' идентификатор ='myid'
Я бы просто не выполнял ввод-вывод char за раз, если это разумно с точки зрения производительности.
Самый простой способ - прочитать весь файл в памяти, а затем предоставить свой собственный интерфейс, подобный fgetc, для этого буфера.
Почему бы просто не отобразить файл в памяти? Отображение памяти переносимо (за исключением Windows Vista, которая требует, чтобы вы перескочили через надежды использовать его сейчас, тупицы). Во всяком случае, сопоставьте свой файл с памятью, и есть ли у вас собственная блокировка / не блокировка полученной области памяти.
ОС обрабатывает все блокировки, необходимые для фактического чтения с диска - вы НИКОГДА не сможете устранить эти накладные расходы. Но с другой стороны, на накладные расходы на обработку не повлияет посторонняя блокировка, кроме той, которую вы делаете сами.
fgetc почти наверняка не читает байт каждый раз, когда вы его вызываете (где под «чтением» я подразумеваю вызов системного вызова для выполнения ввода-вывода). Поищите где-нибудь еще узкое место в производительности, поскольку это, вероятно, не проблема, и использование небезопасных функций, безусловно, не решение. Любая обработка блокировки, которую вы выполняете, вероятно, будет менее эффективной, чем обработка, выполняемая стандартными подпрограммами.
мультиплатформенный подход довольно прост. Избегайте функций или операторов, в которых стандарт указывает, что они должны использовать часовую. sentry - это внутренний класс в классах iostream, который обеспечивает согласованность потока для каждого выходного символа, а в многопоточной среде он блокирует мьютекс, связанный с потоком, для каждого выводимого символа. Это позволяет избежать состояния гонки на низком уровне, но по-прежнему делает вывод нечитаемым, поскольку строки из двух потоков могут выводиться одновременно, как показано в следующем примере:
поток 1 должен писать: abc
поток 2 должен написать: def
Результат может выглядеть так: adebcf вместо abcdef или defabc. Это связано с тем, что часовой реализован для блокировки и разблокировки каждого символа.
Стандарт определяет его для всех функций и операторов, имеющих дело с istream или ostream. Единственный способ избежать этого - использовать буферы потока и собственную блокировку (например, для каждой строки).
Я написал приложение, которое выводит некоторые данные в файл и измеряет скорость. Если вы добавите сюда функцию, которая напрямую использует fstream без использования буфера и очистки, вы увидите разницу в скорости. Он использует ускорение, но я надеюсь, что это не проблема для вас. Попробуйте удалить все стримбуферы и увидеть разницу с ними и без них. В моем случае снижение производительности было в 2-3 раза или около того.
, следующая за статьей Н. Майерс объяснит, как работают локали и часовой в C ++ IOStreams. И обязательно посмотрите в стандартном документе ISO C ++, где функции используют часовую.
Удачи,
Ovanes
#include <vector>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
double do_copy_via_streambuf()
{
const size_t len = 1024*2048;
const size_t factor = 5;
::std::vector<char> data(len, 1);
std::vector<char> buffer(len*factor, 0);
::std::ofstream
ofs("test.dat", ::std::ios_base::binary|::std::ios_base::out);
noskipws(ofs);
std::streambuf* rdbuf = ofs.rdbuf()->pubsetbuf(&buffer[0], buffer.size());
::std::ostreambuf_iterator<char> oi(rdbuf);
boost::progress_timer pt;
for(size_t i=1; i<=250; ++i)
{
::std::copy(data.begin(), data.end(), oi);
if(0==i%factor)
rdbuf->pubsync();
}
ofs.flush();
double rate = 500 / pt.elapsed();
std::cout << rate << std::endl;
return rate;
}
void count_avarage(const char* op_name, double (*fct)())
{
double av_rate=0;
const size_t repeat = 1;
std::cout << "doing " << op_name << std::endl;
for(size_t i=0; i<repeat; ++i)
av_rate+=fct();
std::cout << "average rate for " << op_name << ": " << av_rate/repeat
<< "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"
<< std::endl;
}
int main()
{
count_avarage("copy via streambuf iterator", do_copy_via_streambuf);
return 0;
}
Одна вещь, которую следует учитывать, это для создания собственной среды выполнения. Большинство компиляторов предоставляют исходный код для библиотеки времени выполнения (я был бы удивлен, если бы его не было в пакете C ++ Builder).
Это может потребовать много работы, но, возможно, они локализовали поддержку потоков на сделать что-то подобное простым. Например, встроенный компилятор системы, который я использую, предназначен для этого - у них есть задокументированные крючки для добавления подпрограмм блокировки. Однако возможно, что это может быть головной болью при обслуживании, даже если поначалу это окажется относительно простым.