473,698 Members | 2,616 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Dictionary and std::multimap

Hello, Newsgroupians:

I've a question regarding dictionaries. I have an array elements that I
created, and I'm trying to sort those elements into various sections. Here's
the template of my data type.

DT
{
int nSize;
...
}

I'm trying to create a dictionary, which resembles a jagged array, but I
can't figure but how to do this. I'm trying to sort it according to the
nSize.

EXA: Here's a jagged-array of the structure. nSize is the key, which is
before the colon.

1: Car1, Car2, Car3
3: Car4
8: Car5, Car6

From the example, I have three sizes -- but this, of course can vary. How
can I create a dictionary that would allow me to mimic the std::multimap<> ?
I've been trying Dictionary<int, List<DT>>, but I can't figure out how to add
or access the dictionary. One thing I would like to do is determine the
number of keys in the dictionary, which I can do by dictionary.Key. Count, but
then how can I get a count of all the values associated with a specific key?

Thank you, all.
Trecius
Jun 27 '08
18 4291
"Peter Duniho" <Np*********@nn owslpianmk.comw rote in message
news:op******** *******@petes-computer.local. ..
On Tue, 22 Apr 2008 17:29:32 -0700, Willy Denoyette [MVP]
<wi************ *@telenet.bewro te:
>Hmmm... as expected, there is no clear winner.

Well, actually my expectation isn't that there's no clear winner, but
rather than the TryGetValue() version is consistently faster.

What I don't understand is why, at least on my computer (apparently not
yours), Contains() is consistently slower. These tests are very
repeatable, and while the variance is definitely higher on my computer
than yours, the slowest time for Contains() is only slower than one test
of TryGetValue(), and frankly that's only because it's the very first test
(which in my tests has consistently always been very slow...slow enough
that I think it'd actually be more fair to run a couple of throw-away
tests and then run five of each throwing out the high and low).

Speaking of that slow first test, I'll point out that even on your
computer, if you toss out the first run, Contains() is faster than
TryGetValue() for all but one other test. I'm not really convinced that
your tests show "no clear winner". I'd be more willing to accept that
statement if you presented a run that includes a couple of throw-away
tests and still showed a random distribution across both tests. Given the
apparently closer results on your computer, doing that is much more
important than it would be for my tests.

But in any case, I'm still without an explanation as to why there should
be such a clear difference on my computer.

Pete

When I say there is no clear winner, I mean a *Clear* winner between both
_HistDict2 and _HistDict3, I don't consider a difference of ~1% a clear
winner.

Your sample benchmark does not really measure the performance of ContainsKey
or TryGetValue, you are measuring a lot more.

So, let's only consider what happens in :

if (dict.ContainsK ey(value))
..
if (dict.TryGetVal ue(value, out count))
...
and forget about the remainder of the methods.

When you look at the JITTED code you'll see that "ContainsKe y" directly
calls into "FindEntry" , while "TryGetValu e" prepares a call stack before it
calls "FindEntry" , after the return from "FindEntry" , TryGetValue stores the
returned value (if Key is found) or a default value (if no Key found) in the
callers stack before returning.
So basically both are executing the same code (the FindEntry function),
except that TryGetValue takes a 15 instruction overhead in case the key not
found (which is most often the case in your benchmark) or an overhead of 16
instruction when the key was found.

Both foreach loops take:
loop with ContainsKey:
159/174
loop with TryGetValue:
174/190 instructions to complete (not found/found).
This represents a difference of 9% in number of instructions (but much less
in execution time (<5%)), in favor of "ContainsKe y".
Obviously, the difference reflected by the benchmark is much less (< 2%), as
the foreach loop takes only 30% of the total execution time.

Here are the results of some new runs, now after the program was compiled
without /o (yes this runs faster than an optimized build).

Iterations: 5000
Data elements: 5000
Data range: 65536
Tests to run: 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2

_HistDict2: 13080 msec.
_HistDict2: 13080 msec.
_HistDict2: 13169 msec.
_HistDict2: 13060 msec.
_HistDict2: 13173 msec.
_HistDict2: 13068 msec.
_HistDict3: 13275 msec.
_HistDict3: 13167 msec.
_HistDict3: 13233 msec.
_HistDict3: 13181 msec.
_HistDict3: 13268 msec.
_HistDict3: 13175 msec.

Validating results...done.

Note that I changed your like here:

Console.WriteLi ne(hptd.Method. Name + ": " + _sw.ElapsedMill iseconds + "
msec.");

Willy.

Jun 27 '08 #11
So, let's only consider what happens in :
>
if (dict.ContainsK ey(value))
..
if (dict.TryGetVal ue(value, out count))
...
and forget about the remainder of the methods.

When you look at the JITTED code you'll see that "ContainsKe y"
directly calls into "FindEntry" , while "TryGetValu e" prepares a call
stack before it calls "FindEntry" , after the return from "FindEntry" ,
TryGetValue stores the returned value (if Key is found) or a default
value (if no Key found) in the callers stack before returning.
So basically both are executing the same code (the FindEntry
function), except that TryGetValue takes a 15 instruction overhead in
case the key not found (which is most often the case in your
benchmark) or an overhead of 16 instruction when the key was found.
Victim of the 32 byte threshold for inlining then. TryGetValue is a very
simple function and *ought* to be inlined, but because it is over 32 bytes
of IL, it isn't.

Like I surmised earlier... JIT performance bug.
>
Both foreach loops take:
loop with ContainsKey:
159/174
loop with TryGetValue:
174/190 instructions to complete (not found/found).
Is this including the second call to FindEntry from the ContainsKey/found
variant? Seems like the call to operator[] should have added a lot more
than 15 instructions in that case.
This represents a difference of 9% in number of instructions (but
much less in execution time (<5%)), in favor of "ContainsKe y".
Obviously, the difference reflected by the benchmark is much less (<
2%), as the foreach loop takes only 30% of the total execution time.

Here are the results of some new runs, now after the program was
compiled without /o (yes this runs faster than an optimized build).

Iterations: 5000
Data elements: 5000
Data range: 65536
Tests to run: 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2

_HistDict2: 13080 msec.
_HistDict2: 13080 msec.
_HistDict2: 13169 msec.
_HistDict2: 13060 msec.
_HistDict2: 13173 msec.
_HistDict2: 13068 msec.
_HistDict3: 13275 msec.
_HistDict3: 13167 msec.
_HistDict3: 13233 msec.
_HistDict3: 13181 msec.
_HistDict3: 13268 msec.
_HistDict3: 13175 msec.

Validating results...done.

Note that I changed your like here:

Console.WriteLi ne(hptd.Method. Name + ": " + _sw.ElapsedMill iseconds
+ " msec.");

Willy.

Jun 27 '08 #12
"Ben Voigt [C++ MVP]" <rb*@nospam.nos pamwrote in message
news:ua******** ********@TK2MSF TNGP02.phx.gbl. ..
>So, let's only consider what happens in :

if (dict.ContainsK ey(value))
..
if (dict.TryGetVal ue(value, out count))
...
and forget about the remainder of the methods.

When you look at the JITTED code you'll see that "ContainsKe y"
directly calls into "FindEntry" , while "TryGetValu e" prepares a call
stack before it calls "FindEntry" , after the return from "FindEntry" ,
TryGetValue stores the returned value (if Key is found) or a default
value (if no Key found) in the callers stack before returning.
So basically both are executing the same code (the FindEntry
function), except that TryGetValue takes a 15 instruction overhead in
case the key not found (which is most often the case in your
benchmark) or an overhead of 16 instruction when the key was found.

Victim of the 32 byte threshold for inlining then. TryGetValue is a very
simple function and *ought* to be inlined, but because it is over 32 bytes
of IL, it isn't.
The overhead is not (entirely) call overhead, TryGetValue returns the value
of the K/V pair or a default value depending on the type of the value as an
out argument. The call overhead is only 5 instructions on X86 and on X64
there is no overhead at all.

Like I surmised earlier... JIT performance bug.
>>
Both foreach loops take:
loop with ContainsKey:
159/174
loop with TryGetValue:
174/190 instructions to complete (not found/found).

Is this including the second call to FindEntry from the ContainsKey/found
variant? Seems like the call to operator[] should have added a lot more
than 15 instructions in that case.
What do you mean with second call to FindEntry? there is only one call to
FindEntry per loop.

>This represents a difference of 9% in number of instructions (but
much less in execution time (<5%)), in favor of "ContainsKe y".
Obviously, the difference reflected by the benchmark is much less (<
2%), as the foreach loop takes only 30% of the total execution time.

Here are the results of some new runs, now after the program was
compiled without /o (yes this runs faster than an optimized build).

Iterations: 5000
Data elements: 5000
Data range: 65536
Tests to run: 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2

_HistDict2: 13080 msec.
_HistDict2: 13080 msec.
_HistDict2: 13169 msec.
_HistDict2: 13060 msec.
_HistDict2: 13173 msec.
_HistDict2: 13068 msec.
_HistDict3: 13275 msec.
_HistDict3: 13167 msec.
_HistDict3: 13233 msec.
_HistDict3: 13181 msec.
_HistDict3: 13268 msec.
_HistDict3: 13175 msec.

Validating results...done.

Note that I changed your like here:

Console.WriteL ine(hptd.Method .Name + ": " + _sw.ElapsedMill iseconds
+ " msec.");

Willy.


Jun 27 '08 #13
Oops, Hit the send key too soon ;-)

Willy.

"Ben Voigt [C++ MVP]" <rb*@nospam.nos pamwrote in message
news:ua******** ********@TK2MSF TNGP02.phx.gbl. ..
>So, let's only consider what happens in :

if (dict.ContainsK ey(value))
..
if (dict.TryGetVal ue(value, out count))
...
and forget about the remainder of the methods.

When you look at the JITTED code you'll see that "ContainsKe y"
directly calls into "FindEntry" , while "TryGetValu e" prepares a call
stack before it calls "FindEntry" , after the return from "FindEntry" ,
TryGetValue stores the returned value (if Key is found) or a default
value (if no Key found) in the callers stack before returning.
So basically both are executing the same code (the FindEntry
function), except that TryGetValue takes a 15 instruction overhead in
case the key not found (which is most often the case in your
benchmark) or an overhead of 16 instruction when the key was found.

Victim of the 32 byte threshold for inlining then. TryGetValue is a very
simple function and *ought* to be inlined, but because it is over 32 bytes
of IL, it isn't.

Like I surmised earlier... JIT performance bug.
>>
Both foreach loops take:
loop with ContainsKey:
159/174
loop with TryGetValue:
174/190 instructions to complete (not found/found).

Is this including the second call to FindEntry from the ContainsKey/found
variant? Seems like the call to operator[] should have added a lot more
than 15 instructions in that case.
These are the loops I'm talking about.

foreach (int value in rgiValues)
{
if (dict.ContainsK ey(value))
{
dict[value] = dict[value] + 1;
}
else
{
dict[value] = 1;
}
}

Above takes 159 instructions to complete when Key is not found, 174 when
found.
Here ContainsKey directly calls FindEntry...

foreach (int value in rgiValues)
{
int count;
if (dict.TryGetVal ue(value, out count))
{
dict[value] = count + 1;
}
else
{
dict[value] = 1;
}
}

Above takes 174 instructions when key is found, 190 when not found. Here
FindEntry is called from inside TryGetValue .
Note that this code does not take advantage of the value returned by
TryGetValue, which somewhat defeats it's purpose.

Willy.

Jun 27 '08 #14
Willy Denoyette [MVP] <wi************ *@telenet.bewro te:
These are the loops I'm talking about.

foreach (int value in rgiValues)
{
if (dict.ContainsK ey(value))
{
dict[value] = dict[value] + 1;
}
else
{
dict[value] = 1;
}
}

Above takes 159 instructions to complete when Key is not found, 174 when
found.
Here ContainsKey directly calls FindEntry...
Is that taking into account the indexer also calling FindEntry (on the
"get") though?

That's the odd part for me - ContainsKey followed by an indexer get
needs to look through the hashtable twice, whereas TryGetValue should
only need to look through it once.

Are you saying that the overhead for TryGetValue is the same as the
overhead of effectively calling FindEntry an extra time?
>
foreach (int value in rgiValues)
{
int count;
if (dict.TryGetVal ue(value, out count))
{
dict[value] = count + 1;
}
else
{
dict[value] = 1;
}
}

Above takes 174 instructions when key is found, 190 when not found. Here
FindEntry is called from inside TryGetValue .
Note that this code does not take advantage of the value returned by
TryGetValue, which somewhat defeats it's purpose.
Yes it does - it uses "count + 1" instead of "dict[value] + 1", and
uses the actual return value (the boolean) to determine whether or not
it was found.

Which part of the result do you believe isn't being used?

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Jun 27 '08 #15
"Jon Skeet [C# MVP]" <sk***@pobox.co mwrote in message
news:MP******** *************@m snews.microsoft .com...
Willy Denoyette [MVP] <wi************ *@telenet.bewro te:
>These are the loops I'm talking about.

foreach (int value in rgiValues)
{
if (dict.ContainsK ey(value))
{
dict[value] = dict[value] + 1;
}
else
{
dict[value] = 1;
}
}

Above takes 159 instructions to complete when Key is not found, 174 when
found.
Here ContainsKey directly calls FindEntry...

Is that taking into account the indexer also calling FindEntry (on the
"get") though?
Oh I see what Ben was talking about. No, I did not (but agreed I should
have), nor do I consider the possible intermediate GC run and the fact that
the Dictionary (the backing store) is dynamically extended during the run.
The Dictionary starts with the default size, but gets extended several times
during the run, each extention costs ~2000 cycles. The backing store finaly
gets that big that it ends on the LOH.
That's the odd part for me - ContainsKey followed by an indexer get
needs to look through the hashtable twice, whereas TryGetValue should
only need to look through it once.
It only has to look through the hashtable twice if the key was found.
Are you saying that the overhead for TryGetValue is the same as the
overhead of effectively calling FindEntry an extra time?
No I'm not. I'm only discussing the results of the benchmark, run with the
same command-line arguments as posted by Peter.
I'm only comparing both methods when the key is not found (which is quite
common with 64K possible random values for 5000 entries), in which case
ConTainsKey is the winner. Cases where the key is found are a lot more
complex to compare, TryGetValue is the clear winner when the majority of
keys are found in the dictionary, as illustrated here:

Iterations: 5000
Data elements: 5000
Data range: 100
Tests to run: 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2

_HistDict2: 2936 msec.
_HistDict2: 2915 msec.
_HistDict2: 2913 msec.
_HistDict2: 2912 msec.
_HistDict2: 2906 msec.
_HistDict2: 2924 msec.
_HistDict3: 2206 msec.
_HistDict3: 2204 msec.
_HistDict3: 2199 msec.
_HistDict3: 2200 msec.
_HistDict3: 2194 msec.
_HistDict3: 2204 msec.
Here the number of random keys is limitted to 100, and TryGetValue is ~25%
faster due to the extra FindEntry in ContainsKey.
It's obviouw why this is much faster than the test with 64K keys, only a
few extentions of the backing store have to be done in this case.

>>
foreach (int value in rgiValues)
{
int count;
if (dict.TryGetVal ue(value, out count))
{
dict[value] = count + 1;
}
else
{
dict[value] = 1;
}
}

Above takes 174 instructions when key is found, 190 when not found. Here
FindEntry is called from inside TryGetValue .
>Note that this code does not take advantage of the value returned by
TryGetValue, which somewhat defeats it's purpose.

Yes it does - it uses "count + 1" instead of "dict[value] + 1", and
uses the actual return value (the boolean) to determine whether or not
it was found.
True, but only in the case were the key is found.
Note that the above code could have been written like....
...
dict.TryGetValu e(value, out count)
dict[value] = count + 1;
...
Willy.

Jun 27 '08 #16
On Wed, 23 Apr 2008 17:48:41 -0700, Willy Denoyette [MVP]
<wi************ *@telenet.bewro te:
[...]
Here the number of random keys is limitted to 100, and TryGetValue is
~25% faster due to the extra FindEntry in ContainsKey.
It's obviouw why this is much faster than the test with 64K keys, only
a few extentions of the backing store have to be done in this case.
Okay, so I take it that the bottom line here is that there are at least
two issues at work:

TryGetValue() _is_ in fact "inferior" in the sense that it can't be
inlined and so results in more overhead for the operation when the key
isn't found. (This isn't to say it's actually an inferior approach...just
that there's something about it that could be considered "inferior") .

The other issue is, of course, that the particular input I provided
exposes the worst-case scenario in which the key is usually not found. In
other words, even if TryGetValue() can be considered to be "inferior" in
some specific way, that is only going to be apparent in some specific
scenario.

The part I still don't understand: why TryGetValue() should be _faster_
when the key is found, given that you wrote that both forms of the whole
loop take 174 instructions in that case. Shouldn't the two approaches be
equivalent in that case, rather than TryGetValue() showing a marked
improvement? Is my lack of comprehension due to a naïve understanding of
what "174 instructions" means? That is, that the instruction count isn't
a direct measure of the time the .NET code will take to execute?

I admit, I don't really know when you wrote about "instructio ns" what
exactly you're talking about. Is that IL instructions? Or the final x86
code? Either way, I can easily see how the count of instructions does not
necessarily tell you precisely how fast the code will execute.

In the end, I think I am most satisfied that, once again, it's been shown
that performance-tuning this sort of thing is fraught with difficulty, if
not entirely pointless. :)

Pete
Jun 27 '08 #17
"Peter Duniho" <Np*********@nn owslpianmk.comw rote in message
news:op******** *******@petes-computer.local. ..
On Wed, 23 Apr 2008 17:48:41 -0700, Willy Denoyette [MVP]
<wi************ *@telenet.bewro te:
>[...]
Here the number of random keys is limitted to 100, and TryGetValue is
~25% faster due to the extra FindEntry in ContainsKey.
It's obviouw why this is much faster than the test with 64K keys, only
a few extentions of the backing store have to be done in this case.

Okay, so I take it that the bottom line here is that there are at least
two issues at work:

TryGetValue() _is_ in fact "inferior" in the sense that it can't be
inlined and so results in more overhead for the operation when the key
isn't found. (This isn't to say it's actually an inferior approach...just
that there's something about it that could be considered "inferior") .

The other issue is, of course, that the particular input I provided
exposes the worst-case scenario in which the key is usually not found. In
other words, even if TryGetValue() can be considered to be "inferior" in
some specific way, that is only going to be apparent in some specific
scenario.

The part I still don't understand: why TryGetValue() should be _faster_
when the key is found, given that you wrote that both forms of the whole
loop take 174 instructions in that case. Shouldn't the two approaches be
equivalent in that case, rather than TryGetValue() showing a marked
improvement? Is my lack of comprehension due to a naïve understanding of
what "174 instructions" means? That is, that the instruction count isn't
a direct measure of the time the .NET code will take to execute?

I admit, I don't really know when you wrote about "instructio ns" what
exactly you're talking about. Is that IL instructions? Or the final x86
code? Either way, I can easily see how the count of instructions does not
necessarily tell you precisely how fast the code will execute.

In the end, I think I am most satisfied that, once again, it's been shown
that performance-tuning this sort of thing is fraught with difficulty, if
not entirely pointless. :)

Pete


Ok, let me show you the (raw) call graphs for both foreach loops (taken from
a CPU instrumentation analyzer).

1) ContainsKey - Key found case:

caller (the method) callee
Start
|
3
--------------------------->FindEntry
74
<---------------------------
9
--------------------------->get_Item
93 (includes a call to FindEntry)
<----------------------------
7
--------------------------->Insert
85
<----------------------------
19
|
----return to Start

2) TryGetValue - Key found case:

Start
|
6
--------------------------->TryGetValue (calls FindEntry)
94
<---------------------------
12
--------------------------->Insert
85
<----------------------------
17
|
----return to Start

3) ContainsKey - Key NOT found case:

caller (the method) callee
Start
|
3
--------------------------->FindEntry
41
<---------------------------
10
--------------------------->Insert
88
<----------------------------
17
|
----return to Start
4) TryGetValue - Key NOT found case:

Start
|
6
--------------------------->TryGetValue (calls FindEntry)
56
<---------------------------
10
--------------------------->Insert
88
<----------------------------
17
|
----return to Start
Note:
- the figures are X86 instruction numbers
- instruction # in callee include instruction counts of sub calls, the
actual call graph is deeper than shown here.

This gives us for:
ContainsKey
Key found: 290 instructions
Key not found: 159 instructions
TryGetValue
Key found: 214 instructions
Key not found: 177 instructions

Notice that ContainsKey is somewhat faster when the key does not exist,
while ContainsKey is considerably slower when the key exists.

Some more remarks:
Beware that the instruction count isn't a direct measure of the time taken
to execute a loop, it can only be used as a good estimate if a major portion
of the loop executes the same call graph. Modern processors have become so
fast, that the real bottleneck is the memory system (cache speed, sizes and
hierarchy). Running the same benchmark on a 20% faster CPU (clock speed)
won't yield a 20% performance gain, while running on a slower CPU with a
"better" memory system might give you better results.
The performance level of these kind of benchmarks are now constrained by the
memory system (memory bound) , things like memory bandwidth, throughput and
latency are since long more important than CPU clock rates.

Willy.


Jun 27 '08 #18
On Thu, 24 Apr 2008 02:29:34 -0700, Willy Denoyette [MVP]
<wi************ *@telenet.bewro te:
[...]
This gives us for:
ContainsKey
Key found: 290 instructions
Key not found: 159 instructions
TryGetValue
Key found: 214 instructions
Key not found: 177 instructions
Okay, these numbers are quite a bit different from the ones you posted
earlier. With these, it's much easier to understand the time
differences. Thanks!

Pete
Jun 27 '08 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
13452
by: Tanguy Fautré | last post by:
Hello, does std::multimap make any guarantee about the insertion order? for example: int main() { std::multimap<int, int> Map;
9
7861
by: Dennis Jones | last post by:
Hi, Is there a way to iterate through a multimap in such a way as to encounter only the unique keys? In other words, since a multimap allows duplicate keys, I would like to iterate through the entire multimap, and if a particular key has duplicates, only see one of them. I don't think I care about which of the duplicate entries I see, because once I have an entry, I can use lower_bound and upper_bound to iterate through them, right? ...
1
3792
by: melfar | last post by:
Hello. 9 says: '' The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them. '' Does it mean that if I insert values into a multimap with equal keys, I
1
1604
by: SpreadTooThin | last post by:
I have a dictionary that looks like: a0,b0,c0,d0,e0 a1,b1,c1,d1,e1 .... .... Currently I consider (Class Tag) to be the key and (Class Value) to be the value. However I now need to use as the key and as the value.
20
3985
by: puzzlecracker | last post by:
I am using while loop for that but I am sure you can do it quicker and more syntactically clear with copy function. Here is what I do and would like to if someone has a cleaner solution: vector<stringvec; multimap<stirng, intmyMap // populate myMap
0
8683
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8610
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9170
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9031
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8902
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7740
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6528
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4372
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
2007
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.