Здравствуйте, VladD2, Вы писали:
VD>Правильно, лишнее это. Так проще заявлять, что в С++ все есть.
VD>Да нельзя все же обижать религиозные чувства.
Это типа наезд что-ли?
Я на C++ не работал, не работаю и работать не буду.
Но не потому что C++ сакс и маздай, а потому что есть более интересные вещи на этом свете.
Но это ни в коей мере не умаляет достоинства языка.
А по-поводу OpenC++. Ты можешь назвать хоть один широко-распространенный продукт, написанный на нем?
Здравствуйте, Lloyd, Вы писали:
lkj>>Итераций много. Накладные расходы не должны влиять. lkj>>В чем некорректность? lkj>>Как быстро могут выполняться вызовы виртуальных функций в программе на С++ для .NET? lkj>>И почему мой пример работает так медленно?
L>Во-первых большой оверхед на загрузке нетовского рантайма. L>Во-вторых первый вызов подпрограммы в управляемом коде приводит к компиляции. L>В-третьих не факт, что компилятор в C++ не заменил прямой f1 вызов на прямой (не виртуальный). Он видит, что наследников больше нет и вправе это сделать. Если сделал, то кроме того мог еще и заинлайнить этот вызов, а заодно и вызов g1. Тогда и получаем, что имеем программу типа int s = 0; for (int i = 0; i < 10000000; i++)s += i; В принцыпе этот цикл можно развернуть. А развернув, обнаруживаем, что результат можно свести к int s = <что-то там>; Тут он обнаруживает, что s никто не ипользует и выбрасывает его нафик. Так что в итоге пришли к тому, что оптимизатором тело main-а может быть сведено на нет. Т.о. получаем, что ты сравниваешь время загрузки операционной системой ничего не делающей программы и время работы .net-программы.
Ты меня за дилетанта принимаешь? Тогда посмотри ссылку на website.
Вопрос не на пустом месте возник.
Можно ли сделать программу на C++.NET 7.1 с большим количеством вызовов виртуальных функций, для которой вызов виртуальной функции выполняется быстрее 100 тактов CPU в среднем?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, IT, Вы писали:
IT>>Причём потеря производительности в этом случае будет напрямую зависить только от диаметра кривизны рук разработчика.
AVK>Обычно инженеры употребляют термин "радиус кривизны"
Когда речь идет о руках, принято говорить "диаметр", т.к. руки -- две, радиусы их кривизны могут быть разными, и самму двух радиусов условно называется диаметром
Здравствуйте, lkj, Вы писали:
lkj>Ты меня за дилетанта принимаешь? Тогда посмотри ссылку на website. lkj>Вопрос не на пустом месте возник. lkj>Можно ли сделать программу на C++.NET 7.1 с большим количеством вызовов виртуальных функций, для которой вызов виртуальной функции выполняется быстрее 100 тактов CPU в среднем?
using System;
namespace VirtualTest
{
public interface IDo
{
void Do();
}
public class Do: IDo
{
#region IDo Members
void IDo.Do()
{
Console.WriteLine();
}
#endregion
}
/// <summary>
/// Summary description for Class1.
/// </summary>class Class1
{
[STAThread]
static void Main(string[] args)
{
IDo @do = new Do();
@do.Do();
}
}
}
Здравствуйте, _wqwa, Вы писали:
AVK>>Обычно инженеры употребляют термин "радиус кривизны" _>Когда речь идет о руках, принято говорить "диаметр", т.к. руки -- две, радиусы их кривизны могут быть разными, и самму двух радиусов условно называется диаметром
Здравствуйте, Lloyd, Вы писали:
lkj>>Можно ли сделать программу на C++.NET 7.1 с большим количеством вызовов виртуальных функций, для которой вызов виртуальной функции выполняется быстрее 100 тактов CPU в среднем?
L>
Здравствуйте, lkj, Вы писали:
lkj>Здравствуйте, Lloyd, Вы писали:
lkj>>>Можно ли сделать программу на C++.NET 7.1 с большим количеством вызовов виртуальных функций, для которой вызов виртуальной функции выполняется быстрее 100 тактов CPU в среднем?
L>>
Здравствуйте, Lloyd, Вы писали:
lkj>>>>Можно ли сделать программу на C++.NET 7.1 с большим количеством вызовов виртуальных функций, для которой вызов виртуальной функции выполняется быстрее 100 тактов CPU в среднем?
L>Это C#.
Я не спрашивал про C#.
Я спрашивал про C++ для .NET
Здравствуйте, lkj, Вы писали:
lkj>Я не спрашивал про C#. lkj>Я спрашивал про C++ для .NET
Я конечно в C++ не силен, но все же:
// This is the main project file for VC++ application project
// generated using an Application Wizard.#include"stdafx.h"
#using <mscorlib.dll>
using namespace System;
public __gc __interface IDo
{
void Do();
};
public __gc class DoClass: public IDo
{
public:
void Do()
{
Console::WriteLine();
}
};
int _tmain()
{
IDo* _do = new DoClass();
_do->Do();
return 0;
}
Здравствуйте, Lloyd, Вы писали:
L>Я конечно в C++ не силен, но все же:
Да. Такой код работает быстро.
Но можно ли заставить обычный C++ код (без этих __gc __interface) работать быстро в варианте для .NET?
Хочу проверить скорость С++ -> IL -> x86 для существующего проекта без какой-либо переделки кода.
Здравствуйте, lkj, Вы писали:
lkj>Здравствуйте, Lloyd, Вы писали:
L>>Я конечно в C++ не силен, но все же:
lkj>Да. Такой код работает быстро. lkj>Но можно ли заставить обычный C++ код (без этих __gc __interface) работать быстро в варианте для .NET? lkj>Хочу проверить скорость С++ -> IL -> x86 для существующего проекта без какой-либо переделки кода.
А почему бы тебе самому не проанализировать свой пример, как это сделал Lloyd для C# & MC++?
IT>Порядок освобождения и блокировки можно так же контролировать атрибутами.
Боюсь, это будет слишком неявно. Другими словами, порядок будет неочевиден при прочтении, что приведёт к ошибкам.
Опять же, есть поля, которые нужно освобождать, а есть ссылки на всяких там Parent.
IT> Обработка исключений — какая проблема? По спецификации Dispose не должен выбрасывать никаких исключений.
Ой, ну это уж точно вряд ли. Ты, наверное с Finalize перепутал.
Как ты думаешь, если я перед завершением using FileStream дискетку из дисковода вытащу. Будет исключение
IT> Да и в клинических случаях никто не запрещает написать Dispose самостоятельно. Но вот 90% спокойно можно имплементировать единообразно.
Для Dispose скорее 40%. И вообще, это будет тот же ужастный стиль C. Чтобы написать просто и кратко нужно будет из мозгов котлету сделать.
Где можно "имплементировать единообразно", где нужно "написать самостоятельно" — иэвечный вопрос этих бедняг сишников.
M>>Ну да, то есть для каждого интерфейса нужно писать расширение. Тогда понятно. Тоже вариант, только такое себе. Как-то не очень вдохновляет
IT>Для интерфейсов, атрибутов и для их комбинаций. Так же как в ATL реализовано что-то подобное для многих интерфейсов COM. Например, можно недельку посидеть и покрыть практически все задачи связанные с маппингом, при этом заметно выиграв в производительности, т.к. сегодня подавляющее число занимающихся этим библиотек реализует это через рефлекшин.
Ты имеешь ввиду маппинг, генерируемый в compile-time? А разве Reflection + Reflection.Emit не решает то же самое проще и надёжнее?
Здравствуйте, alexkro, Вы писали:
lkj>>Да. Такой код работает быстро. lkj>>Но можно ли заставить обычный C++ код (без этих __gc __interface) работать быстро в варианте для .NET? lkj>>Хочу проверить скорость С++ -> IL -> x86 для существующего проекта без какой-либо переделки кода.
A>А почему бы тебе самому не проанализировать свой пример, как это сделал Lloyd для C# & MC++?
Не умею. С++.NET раньше не использовал. Поэтому и пишу на форум.
Здравствуйте, mihailik, Вы писали:
M>Боюсь, это будет слишком неявно. Другими словами, порядок будет неочевиден при прочтении, что приведёт к ошибкам. M>Опять же, есть поля, которые нужно освобождать, а есть ссылки на всяких там Parent.
Я же говорю, в особо клинических случаях никто не запрещает писать реализацию в ручну.
IT>> Обработка исключений — какая проблема? По спецификации Dispose не должен выбрасывать никаких исключений.
M>Ой, ну это уж точно вряд ли. Ты, наверное с Finalize перепутал.
Не перепутал.
namespace System {
// IDisposable is an attempt at helping to solve problems with deterministic
// finalization. The GC of course doesn't leave any way to deterministically
// know when a finalizer will run. This forces classes that hold onto OS
// resources or some sort of important state (such as a FileStream or a
// network connection) to provide a Close or Dispose method so users can
// run clean up code deterministically. We have formalized this into an
// interface with one method. Classes may privately implement IDisposable and
// provide a Close method instead, if that name is by far the expected name
// for objects in that domain (ie, you don't Dispose of a FileStream, you Close
// it).
//
// This interface could be theoretically used as a marker by a compiler to
// ensure a disposable object has been cleaned up along all code paths if it's
// been allocated in that method, though in practice any compiler that
// draconian may tick off any number of people. Perhaps an external tool (like
// like Purify or BoundsChecker) could do this. Instead, C# has added a using
// clause, which will generate a try/finally statement where the resource
// passed into the using clause will always have it's Dispose method called.
// Syntax is using(FileStream fs = ...) { .. };
//
// Dispose should meet the following conditions:
// 1) Be safely callable multiple times
// 2) Release any resources associated with the instance
// 3) Call the base class's Dispose method, if necessary
// 4) Suppress finalization of this class to help the GC by reducing the
// number of objects on the finalization queue.
// 5) Dispose shouldn't generally throw exceptions, except for very serious
// errors that are particularly unexpected. (ie, OutOfMemoryException)
// Ideally, nothing should go wrong with your object by calling Dispose.
//
// If possible, a class should define a finalizer that calls Dispose.
// However, in many situations, this is impractical. For instance, take the
// classic example of a Stream and a StreamWriter (which has an internal
// buffer of data to write to the Stream). If both objects are collected
// before Close or Dispose has been called on either, then the GC may run the
// finalizer for the Stream first, before the StreamWriter. At that point, any
// data buffered by the StreamWriter cannot be written to the Stream. In this
// case, it doesn't make much sense to provide a finalizer on the StreamWriter
// since you cannot solve this problem correctly.
/// <include file='doc\IDisposable.uex' path='docs/doc[@for="IDisposable"]/*' />public interface IDisposable {
/// <include file='doc\IDisposable.uex' path='docs/doc[@for="IDisposable.Dispose"]/*' />void Dispose();
}
}
M>Как ты думаешь, если я перед завершением using FileStream дискетку из дисковода вытащу. Будет исключение
Попробуй сам и посмотри что будет. В чём проблема.
IT>> Да и в клинических случаях никто не запрещает написать Dispose самостоятельно. Но вот 90% спокойно можно имплементировать единообразно.
M>Для Dispose скорее 40%. И вообще, это будет тот же ужастный стиль C. Чтобы написать просто и кратко нужно будет из мозгов котлету сделать.
Такое ощущение, что ты только Dispose и программируешь. Я что-то не замечал, чтобы эта задача так часто возникала. Бывает иногда, бывает даже, что нужно освобождать несколько объектов. Но если в них самих Dispose написан корректно, то особой проблемы с порядком освобождения не возникает.
IT>>Для интерфейсов, атрибутов и для их комбинаций. Так же как в ATL реализовано что-то подобное для многих интерфейсов COM. Например, можно недельку посидеть и покрыть практически все задачи связанные с маппингом, при этом заметно выиграв в производительности, т.к. сегодня подавляющее число занимающихся этим библиотек реализует это через рефлекшин.
M>Ты имеешь ввиду маппинг, генерируемый в compile-time? А разве Reflection + Reflection.Emit не решает то же самое проще и надёжнее?
Решает, но не проще.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Обработка исключений — какая проблема? По спецификации Dispose не должен выбрасывать никаких исключений.
Мне интересно посмотреть на эту спецификацию. MSDN говорит, что может выбросить. Собственно, мне тоже хотелось бы, чтобы не выбрасывал, но пока все, что я встречал говорит об обратном.
Здравствуйте, VladD2, Вы писали:
VD>Он С++ реализовал, а не C with classes, да и то как препроцессор к С.
Он реализовал препроцессор Cpre (в октябре 1979), который использовался в одном реальном и нескольких экспериментальных проектах. В составе этих проектов была "первая библиотека на С++, которая поддерживала многозадачное программирование с применением сопрограмм". "Язык, подаваемый на вход препроцессора, получил название "C with Classes"".
Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius — and a lot of courage — to move in the opposite direction. -- Albert Einstein
Здравствуйте, mihailik, Вы писали:
M>Боюсь, это будет слишком неявно. Другими словами, порядок будет неочевиден при прочтении, что приведёт к ошибкам.
M>Опять же, есть поля, которые нужно освобождать, а есть ссылки на всяких там Parent.
Тут нужно подумать, что больше напрягает программиста, а стало быть приводит к большему количеству ошибок. Явный контроль ресурсов или борьба с неявным контролем. Думаю, что первое более утамительно. К тому же зависимости можно и отследить. Как минимум выдать варнинг, мол у вас циклическое освобождение ресурсов.
Кстати, ссылки на парента обычно помечены как не сериализуемые. Можно это дело анализировать.
M>Как ты думаешь, если я перед завершением using FileStream дискетку из дисковода вытащу. Будет исключение
А черт его знает. Реальное закрытие хэндла происходит внутри ЦЛР, но сдается мне что вряд ли. Хотя все может быть.
M>Для Dispose скорее 40%. И вообще, это будет тот же ужастный стиль C. Чтобы написать просто и кратко нужно будет из мозгов котлету сделать.
Не, ну, моньячество со всех сторон. Ну, что может быть ужастного в дереве? Уж разрушение переменных там сделано просто прекрасно.
M>Где можно "имплементировать единообразно", где нужно "написать самостоятельно" — иэвечный вопрос этих бедняг сишников.
Да нет таких вопросов. Есть другой вопрос "Нужно ли делать руками то, что можно не делать?". И тут я целиком согласен с плюсовиками. Чем меньше пишешь руками, тем надежнее.
M>Ты имеешь ввиду маппинг, генерируемый в compile-time? А разве Reflection + Reflection.Emit не решает то же самое проще и надёжнее?
А ты пробовал? Ну, тогда попробуй. Поймешь насколько это "проще". И насколько "надежнее" получается. К тому, же сама генерация отнимает время. А так все в компайл-тайме.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.